Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
d8ee710
core: set default Scalar type to be an NPY_OBJECT
jcarpent Apr 17, 2020
afcf90e
core: extend current API to hanle allocation of arrays of PyTypeObject
jcarpent Apr 17, 2020
261a8da
core: change variable name to avoid confusion
jcarpent Apr 18, 2020
38ac962
core: add getPyArrayType from Python helper
jcarpent Apr 18, 2020
c860031
core: add generic method getPyType
jcarpent Apr 18, 2020
3f7aa4d
core: rely on getPyType function to get the PyTypeObject related to a…
jcarpent Apr 18, 2020
7a0a4fc
core: use const_cast
jcarpent Apr 18, 2020
3cf24b0
core: fix windows issue
jcarpent Apr 18, 2020
53b7495
core: add helper to check if the current Scalar is a Numpy native type
jcarpent Apr 24, 2020
a7341f2
core: remove useless include
jcarpent Apr 24, 2020
6f5fb19
core: add new caller for Numpy functions
jcarpent May 5, 2020
6a9a45c
core: add bool type_code
jcarpent May 5, 2020
66e3935
core: set default type to be NPY_USERDEF
jcarpent May 5, 2020
e3add2c
core: add first version of user-type registration
jcarpent May 5, 2020
10eb218
core: add missing include
jcarpent May 5, 2020
747ef90
core: remove getPyType, now in Register
jcarpent May 5, 2020
afec732
core: allows the use of user types
jcarpent May 5, 2020
1a65119
core: remove useless std::cout
jcarpent May 5, 2020
6e22a54
core: move ufunc to a dedicated file
jcarpent May 5, 2020
3424d6f
core/ufunc: add missing code input
jcarpent May 5, 2020
8635eb6
core/ufunc: rename macro
jcarpent May 5, 2020
2754461
core/ufunc: remove useless include
jcarpent May 5, 2020
31276cb
core/ufunc: add registration of Unary operators
jcarpent May 5, 2020
095ebed
core: add dotfunc
jcarpent May 5, 2020
fe2240d
core: add register file
jcarpent May 5, 2020
a4ba7e8
test: add test for user types
jcarpent May 5, 2020
de7250a
cmake: sync submodule
jcarpent May 5, 2020
95af56b
core: fix Win32 issue
jcarpent May 5, 2020
4da428e
core: remove useless function
jcarpent May 5, 2020
41d2650
core/register: comment self used normally for Singleton
jcarpent May 5, 2020
20b8955
core: move Python call to the dynamic lib
jcarpent May 5, 2020
9387d8e
core: fix signature
jcarpent May 5, 2020
382ca0a
core/register: make Register a pure singleton class
jcarpent May 5, 2020
024de8e
core: fix cast for Win32
jcarpent May 5, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ SET(${PROJECT_NAME}_HEADERS
include/eigenpy/registration.hpp
include/eigenpy/angle-axis.hpp
include/eigenpy/quaternion.hpp
include/eigenpy/user-type.hpp
include/eigenpy/ufunc.hpp
include/eigenpy/register.hpp
include/eigenpy/stride.hpp
include/eigenpy/version.hpp
)
Expand Down Expand Up @@ -150,6 +153,7 @@ SET(${PROJECT_NAME}_SOURCES
src/matrix-float.cpp
src/matrix-complex-float.cpp
src/matrix-complex-double.cpp
src/register.cpp
src/matrix-double.cpp
src/matrix-long-double.cpp
src/matrix-complex-long-double.cpp
Expand Down
2 changes: 1 addition & 1 deletion cmake
Submodule cmake updated 1 files
+5 −0 package-config.cmake
38 changes: 22 additions & 16 deletions include/eigenpy/eigen-allocator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "eigenpy/fwd.hpp"
#include "eigenpy/numpy-map.hpp"
#include "eigenpy/register.hpp"
#include "eigenpy/scalar-conversion.hpp"
#include "eigenpy/utils/is-aligned.hpp"

Expand Down Expand Up @@ -114,14 +115,15 @@ namespace eigenpy
Type * mat_ptr = details::init_matrix_or_array<Type>::run(pyArray,raw_ptr);
Type & mat = *mat_ptr;

const int pyArray_Type = EIGENPY_GET_PY_ARRAY_TYPE(pyArray);
if(pyArray_Type == NumpyEquivalentType<Scalar>::type_code)
const int pyArray_type_code = EIGENPY_GET_PY_ARRAY_TYPE(pyArray);
const int Scalar_type_code = Register::getTypeCode<Scalar>();
if(pyArray_type_code == Scalar_type_code)
{
mat = NumpyMap<MatType,Scalar>::map(pyArray); // avoid useless cast
return;
}

switch(pyArray_Type)
switch(pyArray_type_code)
{
case NPY_INT:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,int,Scalar,pyArray,mat);
Expand Down Expand Up @@ -158,11 +160,12 @@ namespace eigenpy
PyArrayObject * pyArray)
{
const MatrixDerived & mat = const_cast<const MatrixDerived &>(mat_.derived());
const int pyArray_Type = EIGENPY_GET_PY_ARRAY_TYPE(pyArray);
const int pyArray_type_code = EIGENPY_GET_PY_ARRAY_TYPE(pyArray);
const int Scalar_type_code = Register::getTypeCode<Scalar>();

typedef typename NumpyMap<MatType,Scalar>::EigenMap MapType;

if(pyArray_Type == NumpyEquivalentType<Scalar>::type_code) // no cast needed
if(pyArray_type_code == Scalar_type_code) // no cast needed
{
MapType map_pyArray = NumpyMap<MatType,Scalar>::map(pyArray);
if(mat.rows() == map_pyArray.rows())
Expand All @@ -172,7 +175,7 @@ namespace eigenpy
return;
}

switch(pyArray_Type)
switch(pyArray_type_code)
{
case NPY_INT:
EIGENPY_CAST_FROM_EIGEN_MATRIX_TO_PYARRAY(MatType,Scalar,int,mat,pyArray);
Expand Down Expand Up @@ -219,8 +222,9 @@ namespace eigenpy
typedef typename StrideType<MatType,Eigen::internal::traits<RefType>::StrideType::InnerStrideAtCompileTime, Eigen::internal::traits<RefType>::StrideType::OuterStrideAtCompileTime >::type NumpyMapStride;

bool need_to_allocate = false;
const int pyArray_Type = EIGENPY_GET_PY_ARRAY_TYPE(pyArray);
if(pyArray_Type != NumpyEquivalentType<Scalar>::type_code)
const int pyArray_type_code = EIGENPY_GET_PY_ARRAY_TYPE(pyArray);
const int Scalar_type_code = Register::getTypeCode<Scalar>();
if(pyArray_type_code != Scalar_type_code)
need_to_allocate |= true;
if( (MatType::IsRowMajor && (PyArray_IS_C_CONTIGUOUS(pyArray) && !PyArray_IS_F_CONTIGUOUS(pyArray)))
|| (!MatType::IsRowMajor && (PyArray_IS_F_CONTIGUOUS(pyArray) && !PyArray_IS_C_CONTIGUOUS(pyArray)))
Expand All @@ -246,13 +250,13 @@ namespace eigenpy
new (raw_ptr) StorageType(mat_ref,pyArray,mat_ptr);

RefType & mat = *reinterpret_cast<RefType*>(raw_ptr);
if(pyArray_Type == NumpyEquivalentType<Scalar>::type_code)
if(pyArray_type_code == Scalar_type_code)
{
mat = NumpyMap<MatType,Scalar>::map(pyArray); // avoid useless cast
return;
}

switch(pyArray_Type)
switch(pyArray_type_code)
{
case NPY_INT:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,int,Scalar,pyArray,mat);
Expand Down Expand Up @@ -284,7 +288,7 @@ namespace eigenpy
}
else
{
assert(pyArray_Type == NumpyEquivalentType<Scalar>::type_code);
assert(pyArray_type_code == Scalar_type_code);
typename NumpyMap<MatType,Scalar,Options,NumpyMapStride>::EigenMap numpyMap = NumpyMap<MatType,Scalar,Options,NumpyMapStride>::map(pyArray);
RefType mat_ref(numpyMap);
new (raw_ptr) StorageType(mat_ref,pyArray);
Expand All @@ -311,8 +315,10 @@ namespace eigenpy
typedef typename StrideType<MatType,Eigen::internal::traits<RefType>::StrideType::InnerStrideAtCompileTime, Eigen::internal::traits<RefType>::StrideType::OuterStrideAtCompileTime >::type NumpyMapStride;

bool need_to_allocate = false;
const int pyArray_Type = EIGENPY_GET_PY_ARRAY_TYPE(pyArray);
if(pyArray_Type != NumpyEquivalentType<Scalar>::type_code)
const int pyArray_type_code = EIGENPY_GET_PY_ARRAY_TYPE(pyArray);
const int Scalar_type_code = Register::getTypeCode<Scalar>();

if(pyArray_type_code != Scalar_type_code)
need_to_allocate |= true;
if( (MatType::IsRowMajor && (PyArray_IS_C_CONTIGUOUS(pyArray) && !PyArray_IS_F_CONTIGUOUS(pyArray)))
|| (!MatType::IsRowMajor && (PyArray_IS_F_CONTIGUOUS(pyArray) && !PyArray_IS_C_CONTIGUOUS(pyArray)))
Expand All @@ -338,13 +344,13 @@ namespace eigenpy
new (raw_ptr) StorageType(mat_ref,pyArray,mat_ptr);

MatType & mat = *mat_ptr;
if(pyArray_Type == NumpyEquivalentType<Scalar>::type_code)
if(pyArray_type_code == Scalar_type_code)
{
mat = NumpyMap<MatType,Scalar>::map(pyArray); // avoid useless cast
return;
}

switch(pyArray_Type)
switch(pyArray_type_code)
{
case NPY_INT:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,int,Scalar,pyArray,mat);
Expand Down Expand Up @@ -376,7 +382,7 @@ namespace eigenpy
}
else
{
assert(pyArray_Type == NumpyEquivalentType<Scalar>::type_code);
assert(pyArray_type_code == Scalar_type_code);
typename NumpyMap<MatType,Scalar,Options,NumpyMapStride>::EigenMap numpyMap = NumpyMap<MatType,Scalar,Options,NumpyMapStride>::map(pyArray);
RefType mat_ref(numpyMap);
new (raw_ptr) StorageType(mat_ref,pyArray);
Expand Down
2 changes: 1 addition & 1 deletion include/eigenpy/eigen-to-python.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ namespace boost { namespace python {

#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
inline PyTypeObject const*
get_pytype()const
get_pytype() const
{
return converter::registered_pytype<MatrixRef>::get_pytype();
}
Expand Down
21 changes: 15 additions & 6 deletions include/eigenpy/numpy-allocator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
#include "eigenpy/numpy-type.hpp"
#include "eigenpy/eigen-allocator.hpp"

#include "eigenpy/register.hpp"

namespace eigenpy
{

template<typename MatType>
struct NumpyAllocator
{
Expand All @@ -20,8 +23,8 @@ namespace eigenpy
{
typedef typename SimilarMatrixType::Scalar Scalar;

PyArrayObject * pyArray = (PyArrayObject*) call_PyArray_SimpleNew(static_cast<int>(nd), shape,
NumpyEquivalentType<Scalar>::type_code);
const int code = Register::getTypeCode<Scalar>();
PyArrayObject * pyArray = (PyArrayObject*) call_PyArray_SimpleNew(static_cast<int>(nd), shape, code);

// Copy data
EigenAllocator<SimilarMatrixType>::copy(mat,pyArray);
Expand All @@ -42,8 +45,11 @@ namespace eigenpy

if(NumpyType::sharedMemory())
{
PyArrayObject * pyArray = (PyArrayObject*) call_PyArray_New(static_cast<int>(nd), shape,
NumpyEquivalentType<Scalar>::type_code,
const int Scalar_type_code = Register::getTypeCode<Scalar>();
PyArrayObject * pyArray = (PyArrayObject*) call_PyArray_New(getPyArrayType(),
static_cast<int>(nd),
shape,
Scalar_type_code,
mat.data(),
NPY_ARRAY_MEMORY_CONTIGUOUS | NPY_ARRAY_ALIGNED);

Expand Down Expand Up @@ -77,8 +83,11 @@ namespace eigenpy

if(NumpyType::sharedMemory())
{
PyArrayObject * pyArray = (PyArrayObject*) call_PyArray_New(static_cast<int>(nd), shape,
NumpyEquivalentType<Scalar>::type_code,
const int Scalar_type_code = Register::getTypeCode<Scalar>();
PyArrayObject * pyArray = (PyArrayObject*) call_PyArray_New(getPyArrayType(),
static_cast<int>(nd),
shape,
Scalar_type_code,
const_cast<SimilarMatrixType &>(mat.derived()).data(),
NPY_ARRAY_MEMORY_CONTIGUOUS_RO | NPY_ARRAY_ALIGNED);

Expand Down
15 changes: 14 additions & 1 deletion include/eigenpy/numpy-type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,35 @@
#include "eigenpy/scalar-conversion.hpp"

#include <patchlevel.h> // For PY_MAJOR_VERSION
#include <stdexcept>
#include <typeinfo>
#include <sstream>

namespace eigenpy
{
namespace bp = boost::python;

template <typename SCALAR> struct NumpyEquivalentType {};
// By default, the Scalar is considered as a Python object
template <typename Scalar> struct NumpyEquivalentType { enum { type_code = NPY_USERDEF };};

template <> struct NumpyEquivalentType<float> { enum { type_code = NPY_FLOAT };};
template <> struct NumpyEquivalentType< std::complex<float> > { enum { type_code = NPY_CFLOAT };};
template <> struct NumpyEquivalentType<double> { enum { type_code = NPY_DOUBLE };};
template <> struct NumpyEquivalentType< std::complex<double> > { enum { type_code = NPY_CDOUBLE };};
template <> struct NumpyEquivalentType<long double> { enum { type_code = NPY_LONGDOUBLE };};
template <> struct NumpyEquivalentType< std::complex<long double> > { enum { type_code = NPY_CLONGDOUBLE };};
template <> struct NumpyEquivalentType<bool> { enum { type_code = NPY_BOOL };};
template <> struct NumpyEquivalentType<int> { enum { type_code = NPY_INT };};
template <> struct NumpyEquivalentType<long> { enum { type_code = NPY_LONG };};

template<typename Scalar>
bool isNumpyNativeType()
{
if(NumpyEquivalentType<Scalar>::type_code == NPY_USERDEF)
return false;
return true;
}

template<typename Scalar>
bool np_type_is_convertible_into_scalar(const int np_type)
{
Expand Down
22 changes: 18 additions & 4 deletions include/eigenpy/numpy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#endif

#include <numpy/noprefix.h>
#include <numpy/ufuncobject.h>

#if defined _WIN32 || defined __CYGWIN__
#define EIGENPY_GET_PY_ARRAY_TYPE(array) \
Expand All @@ -30,21 +31,34 @@
namespace eigenpy
{
void EIGENPY_DLLEXPORT import_numpy();
int EIGENPY_DLLEXPORT PyArray_TypeNum(PyTypeObject * type);
}

#if defined _WIN32 || defined __CYGWIN__
namespace eigenpy
{
EIGENPY_DLLEXPORT PyObject* call_PyArray_SimpleNew(int nd, npy_intp * shape, int np_type);
EIGENPY_DLLEXPORT PyObject* call_PyArray_SimpleNew(int nd, npy_intp * shape, int np_type);

EIGENPY_DLLEXPORT PyObject* call_PyArray_New(int nd, npy_intp * shape, int np_type, void * data_ptr, int options);
EIGENPY_DLLEXPORT PyObject* call_PyArray_New(PyTypeObject * py_type_ptr, int nd, npy_intp * shape, int np_type, void * data_ptr, int options);

EIGENPY_DLLEXPORT int call_PyArray_ObjectType(PyObject *, int);

EIGENPY_DLLEXPORT PyTypeObject * getPyArrayType();

EIGENPY_DLLEXPORT PyArray_Descr * call_PyArray_DescrFromType(int typenum);

EIGENPY_DLLEXPORT void call_PyArray_InitArrFuncs(PyArray_ArrFuncs * funcs);

EIGENPY_DLLEXPORT int call_PyArray_RegisterDataType(PyArray_Descr * dtype);
}
#else
#define call_PyArray_SimpleNew PyArray_SimpleNew
#define call_PyArray_New(nd,shape,np_type,data_ptr,options) \
PyArray_New(&PyArray_Type,nd,shape,np_type,NULL,data_ptr,0,options,NULL)
#define call_PyArray_New(py_type_ptr,nd,shape,np_type,data_ptr,options) \
PyArray_New(py_type_ptr,nd,shape,np_type,NULL,data_ptr,0,options,NULL)
#define getPyArrayType() &PyArray_Type
#define call_PyArray_DescrFromType(typenum) PyArray_DescrFromType(typenum)
#define call_PyArray_InitArrFuncs(funcs) PyArray_InitArrFuncs(funcs)
#define call_PyArray_RegisterDataType(dtype) PyArray_RegisterDataType(dtype)
#endif

#endif // ifndef __eigenpy_numpy_hpp__
Loading