@@ -119,6 +119,28 @@ namespace eigenpy
119119 {
120120 return getInstance ().CurrentNumpyType ;
121121 }
122+
123+ static const PyTypeObject * getNumpyMatrixType ()
124+ {
125+ return getInstance ().NumpyMatrixType ;
126+ }
127+
128+ static const PyTypeObject * getNumpyArrayType ()
129+ {
130+ return getInstance ().NumpyArrayType ;
131+ }
132+
133+ static bool isMatrix ()
134+ {
135+ return PyType_IsSubtype (reinterpret_cast <PyTypeObject*>(getInstance ().CurrentNumpyType .ptr ()),
136+ getInstance ().NumpyMatrixType );
137+ }
138+
139+ static bool isArray ()
140+ {
141+ return PyType_IsSubtype (reinterpret_cast <PyTypeObject*>(getInstance ().CurrentNumpyType .ptr ()),
142+ getInstance ().NumpyArrayType );
143+ }
122144
123145 protected:
124146 NumpyType ()
@@ -150,6 +172,39 @@ namespace eigenpy
150172 bp::object NumpyArrayObject; PyTypeObject * NumpyArrayType;
151173
152174 };
175+
176+ template <typename MatType, bool IsVectorAtCompileTime = MatType::IsVectorAtCompileTime>
177+ struct initEigenObject
178+ {
179+ static MatType * run (PyArrayObject * pyArray, void * storage)
180+ {
181+ assert (PyArray_NDIM (pyArray) == 2 );
182+
183+ const int rows = (int )PyArray_DIMS (pyArray)[0 ];
184+ const int cols = (int )PyArray_DIMS (pyArray)[1 ];
185+
186+ return new (storage) MatType (rows,cols);
187+ }
188+ };
189+
190+ template <typename MatType>
191+ struct initEigenObject <MatType,true >
192+ {
193+ static MatType * run (PyArrayObject * pyArray, void * storage)
194+ {
195+ if (PyArray_NDIM (pyArray) == 1 )
196+ {
197+ const int rows_or_cols = (int )PyArray_DIMS (pyArray)[0 ];
198+ return new (storage) MatType (rows_or_cols);
199+ }
200+ else
201+ {
202+ const int rows = (int )PyArray_DIMS (pyArray)[0 ];
203+ const int cols = (int )PyArray_DIMS (pyArray)[1 ];
204+ return new (storage) MatType (rows,cols);
205+ }
206+ }
207+ };
153208
154209 template <typename MatType>
155210 struct EigenObjectAllocator
@@ -159,10 +214,7 @@ namespace eigenpy
159214
160215 static void allocate (PyArrayObject * pyArray, void * storage)
161216 {
162- const int rows = (int )PyArray_DIMS (pyArray)[0 ];
163- const int cols = (int )PyArray_DIMS (pyArray)[1 ];
164-
165- Type * mat_ptr = new (storage) Type (rows,cols);
217+ Type * mat_ptr = initEigenObject<Type>::run (pyArray,storage);
166218
167219 if (NumpyEquivalentType<Scalar>::type_code == GET_PY_ARRAY_TYPE (pyArray))
168220 {
@@ -294,124 +346,113 @@ namespace eigenpy
294346 template <typename MatType>
295347 struct EigenFromPy
296348 {
349+
350+ static bool isScalarConvertible (const int np_type)
351+ {
352+ if (NumpyEquivalentType<typename MatType::Scalar>::type_code == np_type)
353+ return true ;
354+
355+ switch (np_type)
356+ {
357+ case NPY_INT:
358+ return FromTypeToType<int ,typename MatType::Scalar>::value;
359+ case NPY_LONG:
360+ return FromTypeToType<long ,typename MatType::Scalar>::value;
361+ case NPY_FLOAT:
362+ return FromTypeToType<float ,typename MatType::Scalar>::value;
363+ case NPY_DOUBLE:
364+ return FromTypeToType<double ,typename MatType::Scalar>::value;
365+ default :
366+ return false ;
367+ }
368+ }
369+
297370 // / \brief Determine if pyObj can be converted into a MatType object
298371 static void * convertible (PyArrayObject* pyArray)
299372 {
300373 if (!PyArray_Check (pyArray))
301374 return 0 ;
375+
376+ if (!isScalarConvertible (GET_PY_ARRAY_TYPE (pyArray)))
377+ return 0 ;
302378
303379 if (MatType::IsVectorAtCompileTime)
304380 {
305- // Special care of scalar matrix of dimension 1x1.
306- if (PyArray_DIMS (pyArray)[0 ] == 1 && PyArray_DIMS (pyArray)[1 ] == 1 )
307- return pyArray;
308-
309- if (PyArray_DIMS (pyArray)[0 ] > 1 && PyArray_DIMS (pyArray)[1 ] > 1 )
381+ switch (PyArray_NDIM (pyArray))
310382 {
383+ case 0 :
384+ return 0 ;
385+ case 1 :
386+ return pyArray;
387+ case 2 :
388+ {
389+ // Special care of scalar matrix of dimension 1x1.
390+ if (PyArray_DIMS (pyArray)[0 ] == 1 && PyArray_DIMS (pyArray)[1 ] == 1 )
391+ return pyArray;
392+
393+ if (PyArray_DIMS (pyArray)[0 ] > 1 && PyArray_DIMS (pyArray)[1 ] > 1 )
394+ {
311395#ifndef NDEBUG
312- std::cerr << " The number of dimension of the object does not correspond to a vector" << std::endl;
396+ std::cerr << " The number of dimension of the object does not correspond to a vector" << std::endl;
313397#endif
314- return 0 ;
315- }
316-
317- if (((PyArray_DIMS (pyArray)[0 ] == 1 ) && (MatType::ColsAtCompileTime == 1 ))
318- || ((PyArray_DIMS (pyArray)[1 ] == 1 ) && (MatType::RowsAtCompileTime == 1 )))
319- {
398+ return 0 ;
399+ }
400+
401+ if (((PyArray_DIMS (pyArray)[0 ] == 1 ) && (MatType::ColsAtCompileTime == 1 ))
402+ || ((PyArray_DIMS (pyArray)[1 ] == 1 ) && (MatType::RowsAtCompileTime == 1 )))
403+ {
320404#ifndef NDEBUG
321- if (MatType::ColsAtCompileTime == 1 )
322- std::cerr << " The object is not a column vector" << std::endl;
323- else
324- std::cerr << " The object is not a row vector" << std::endl;
405+ if (MatType::ColsAtCompileTime == 1 )
406+ std::cerr << " The object is not a column vector" << std::endl;
407+ else
408+ std::cerr << " The object is not a row vector" << std::endl;
325409#endif
326- return 0 ;
410+ return 0 ;
411+ }
412+ break ;
413+ }
414+ default :
415+ return 0 ;
327416 }
328417 }
329-
330- if (PyArray_NDIM (pyArray) != 2 )
418+ else // this is a matrix
331419 {
332- if ( ( PyArray_NDIM (pyArray) !=1 ) || (! MatType::IsVectorAtCompileTime) )
420+ if ( PyArray_NDIM (pyArray) != 2 )
333421 {
422+ if ( (PyArray_NDIM (pyArray) !=1 ) || (! MatType::IsVectorAtCompileTime) )
423+ {
334424#ifndef NDEBUG
335- std::cerr << " The number of dimension of the object is not correct." << std::endl;
425+ std::cerr << " The number of dimension of the object is not correct." << std::endl;
336426#endif
337- return 0 ;
427+ return 0 ;
428+ }
338429 }
339- }
340-
341- if (PyArray_NDIM (pyArray) == 2 )
342- {
343- const int R = (int )PyArray_DIMS (pyArray)[0 ];
344- const int C = (int )PyArray_DIMS (pyArray)[1 ];
345430
346- if ( (MatType::RowsAtCompileTime!=R)
347- && (MatType::RowsAtCompileTime!=Eigen::Dynamic) )
348- return 0 ;
349- if ( (MatType::ColsAtCompileTime!=C)
350- && (MatType::ColsAtCompileTime!=Eigen::Dynamic) )
351- return 0 ;
352- }
353-
354- // Check if the Scalar type of the obj_ptr is compatible with the Scalar type of MatType
355- if (GET_PY_ARRAY_TYPE (pyArray) == NPY_INT)
356- {
357- if (!FromTypeToType<int ,typename MatType::Scalar>::value)
431+ if (PyArray_NDIM (pyArray) == 2 )
358432 {
359- #ifndef NDEBUG
360- std::cerr << " The Python matrix scalar type (int) cannot be converted into the scalar type of the Eigen matrix. Loss of arithmetic precision" << std::endl;
361- #endif
362- return 0 ;
433+ const int R = (int )PyArray_DIMS (pyArray)[0 ];
434+ const int C = (int )PyArray_DIMS (pyArray)[1 ];
435+
436+ if ( (MatType::RowsAtCompileTime!=R)
437+ && (MatType::RowsAtCompileTime!=Eigen::Dynamic) )
438+ return 0 ;
439+ if ( (MatType::ColsAtCompileTime!=C)
440+ && (MatType::ColsAtCompileTime!=Eigen::Dynamic) )
441+ return 0 ;
363442 }
364443 }
365- else if (GET_PY_ARRAY_TYPE (pyArray) == NPY_LONG)
366- {
367- if (!FromTypeToType<long ,typename MatType::Scalar>::value)
368- {
369- #ifndef NDEBUG
370- std::cerr << " The Python matrix scalar type (long) cannot be converted into the scalar type of the Eigen matrix. Loss of arithmetic precision" << std::endl;
371- #endif
372- return 0 ;
373- }
374- }
375- else if (GET_PY_ARRAY_TYPE (pyArray) == NPY_FLOAT)
376- {
377- if (!FromTypeToType<float ,typename MatType::Scalar>::value)
378- {
379- #ifndef NDEBUG
380- std::cerr << " The Python matrix scalar type (float) cannot be converted into the scalar type of the Eigen matrix. Loss of arithmetic precision" << std::endl;
381- #endif
382- return 0 ;
383- }
384- }
385- else if (GET_PY_ARRAY_TYPE (pyArray) == NPY_DOUBLE)
386- {
387- if (!FromTypeToType<double ,typename MatType::Scalar>::value)
388- {
389- #ifndef NDEBUG
390- std::cerr << " The Python matrix scalar (double) type cannot be converted into the scalar type of the Eigen matrix. Loss of arithmetic precision." << std::endl;
391- #endif
392- return 0 ;
393- }
394- }
395- else if (GET_PY_ARRAY_TYPE (pyArray) != NumpyEquivalentType<typename MatType::Scalar>::type_code)
396- {
397- #ifndef NDEBUG
398- std::cerr << " The internal type as no Eigen equivalent." << std::endl;
399- #endif
400444
401- return 0 ;
402- }
403-
404445#ifdef NPY_1_8_API_VERSION
405446 if (!(PyArray_FLAGS (pyArray)))
406447#else
407448 if (!(PyArray_FLAGS (pyArray) & NPY_ALIGNED))
408449#endif
409- {
450+ {
410451#ifndef NDEBUG
411- std::cerr << " NPY non-aligned matrices are not implemented." << std::endl;
452+ std::cerr << " NPY non-aligned matrices are not implemented." << std::endl;
412453#endif
413- return 0 ;
414- }
454+ return 0 ;
455+ }
415456
416457 return pyArray;
417458 }
0 commit comments