Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
92d0ed1
test: rename ref test into eigenpy_ref
jcarpent Feb 23, 2020
db84212
core: fix EIGENPY_DEFAULT_ALIGNMENT_VALUE
jcarpent Feb 23, 2020
b2b30b2
core: allows non dynamic Stride
jcarpent Feb 23, 2020
39629ad
core: add template specialization for NumpyAllocator with Eigen::Ref
jcarpent Feb 24, 2020
8818202
core: fix assert
jcarpent Feb 24, 2020
df06171
core: update signature of init_matrix_or_array
jcarpent Feb 24, 2020
ab986af
core: change signature for allocate
jcarpent Feb 24, 2020
fc4b9e5
core: add helper eigen_from_py_construct
jcarpent Feb 24, 2020
c34b118
core: fix doc
jcarpent Feb 24, 2020
3808282
core: MapNumpy is now templatized by the Stride type
jcarpent Feb 24, 2020
7652c83
core: add exposition of Eigen::Ref<MatrixType>
jcarpent Feb 24, 2020
60c9687
core: template specialization of EigenAllocator for Eigen::Ref<Matrix…
jcarpent Feb 24, 2020
9872bfb
test: add library for eigen_ref
jcarpent Feb 24, 2020
53563e5
core: full templatization of Eigen::Map
jcarpent Feb 25, 2020
b365f4c
core: handle RowMajor types
jcarpent Feb 25, 2020
a110f41
core: add EIGENPY_NO_ALIGNMENT_VALUE
jcarpent Feb 25, 2020
0cd5f10
core: add template AlignmentValue to MapNumpy
jcarpent Feb 25, 2020
3b5e181
core: specify the alignement of data for Eigen::Ref
jcarpent Feb 25, 2020
f3cc1cb
core: check whether memory is aligned or not for Eigen::Ref
jcarpent Feb 25, 2020
bf0259b
core: remove std::cout
jcarpent Feb 25, 2020
04aa313
core: fix issue with old Boost version
jcarpent Feb 25, 2020
77d83f5
core: add is_aligned helper
jcarpent Feb 25, 2020
fb1b4ce
core: fix name
jcarpent Feb 25, 2020
b19eac2
core: fix copy_if_non_const for const types
jcarpent Feb 25, 2020
1fe6a61
core: handle const Eigen::Ref<const MatType>
jcarpent Feb 25, 2020
9e60650
test: add test for Eigen::Ref
jcarpent Feb 25, 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
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ SEARCH_FOR_BOOST()
SET(${PROJECT_NAME}_UTILS_HEADERS
include/eigenpy/utils/scalar-name.hpp
include/eigenpy/utils/is-approx.hpp
include/eigenpy/utils/is-aligned.hpp
)

SET(${PROJECT_NAME}_SOLVERS_HEADERS
Expand Down
212 changes: 204 additions & 8 deletions include/eigenpy/eigen-allocator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "eigenpy/fwd.hpp"
#include "eigenpy/map.hpp"
#include "eigenpy/scalar-conversion.hpp"
#include "eigenpy/utils/is-aligned.hpp"

namespace eigenpy
{
Expand All @@ -17,7 +18,7 @@ namespace eigenpy
template<typename MatType, bool IsVectorAtCompileTime = MatType::IsVectorAtCompileTime>
struct init_matrix_or_array
{
static MatType * run(PyArrayObject * pyArray, void * storage)
static MatType * run(PyArrayObject * pyArray, void * storage = NULL)
{
assert(PyArray_NDIM(pyArray) == 1 || PyArray_NDIM(pyArray) == 2);

Expand All @@ -33,25 +34,34 @@ namespace eigenpy
cols = 1;
}

return new (storage) MatType(rows,cols);
if(storage)
return new (storage) MatType(rows,cols);
else
return new MatType(rows,cols);
}
};

template<typename MatType>
struct init_matrix_or_array<MatType,true>
{
static MatType * run(PyArrayObject * pyArray, void * storage)
static MatType * run(PyArrayObject * pyArray, void * storage = NULL)
{
if(PyArray_NDIM(pyArray) == 1)
{
const int rows_or_cols = (int)PyArray_DIMS(pyArray)[0];
return new (storage) MatType(rows_or_cols);
if(storage)
return new (storage) MatType(rows_or_cols);
else
return new MatType(rows_or_cols);
}
else
{
const int rows = (int)PyArray_DIMS(pyArray)[0];
const int cols = (int)PyArray_DIMS(pyArray)[1];
return new (storage) MatType(rows,cols);
if(storage)
return new (storage) MatType(rows,cols);
else
return new MatType(rows,cols);
}
}
};
Expand Down Expand Up @@ -79,7 +89,7 @@ namespace eigenpy
const Eigen::MatrixBase<MatrixOut> & /*dest*/)
{
// do nothing
assert("Must never happened");
assert(false && "Must never happened");
}
};

Expand All @@ -97,9 +107,11 @@ namespace eigenpy
typedef MatType Type;
typedef typename MatType::Scalar Scalar;

static void allocate(PyArrayObject * pyArray, void * storage)
static void allocate(PyArrayObject * pyArray,
bp::converter::rvalue_from_python_storage<MatType> * storage)
{
Type * mat_ptr = details::init_matrix_or_array<Type>::run(pyArray,storage);
void * raw_ptr = storage->storage.bytes;
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);
Expand Down Expand Up @@ -193,6 +205,190 @@ namespace eigenpy
};

#if EIGEN_VERSION_AT_LEAST(3,2,0)
template<typename MatType, int Options, typename Stride>
struct EigenAllocator<Eigen::Ref<MatType,Options,Stride> >
{
typedef Eigen::Ref<MatType,Options,Stride> RefType;
typedef typename MatType::Scalar Scalar;

typedef typename ::boost::python::detail::referent_storage<RefType&>::StorageType StorageType;

static void allocate(PyArrayObject * pyArray,
bp::converter::rvalue_from_python_storage<RefType> * storage)
{
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)
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)))
|| MatType::IsVectorAtCompileTime
|| (PyArray_IS_F_CONTIGUOUS(pyArray) && PyArray_IS_C_CONTIGUOUS(pyArray))) // no need to allocate
need_to_allocate |= false;
else
need_to_allocate |= true;
if(Options != Eigen::Unaligned) // we need to check whether the memory is correctly aligned and composed of a continuous segment
{
void * data_ptr = PyArray_DATA(pyArray);
if(!PyArray_ISONESEGMENT(pyArray) || !is_aligned(data_ptr,Options))
need_to_allocate |= true;
}

void * raw_ptr = storage->storage.bytes;
if(need_to_allocate)
{
MatType * mat_ptr;
mat_ptr = details::init_matrix_or_array<MatType>::run(pyArray);
RefType mat_ref(*mat_ptr);

new (raw_ptr) StorageType(mat_ref,pyArray,mat_ptr);

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

switch(pyArray_Type)
{
case NPY_INT:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,int,Scalar,pyArray,mat);
break;
case NPY_LONG:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,long,Scalar,pyArray,mat);
break;
case NPY_FLOAT:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,float,Scalar,pyArray,mat);
break;
case NPY_CFLOAT:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,std::complex<float>,Scalar,pyArray,mat);
break;
case NPY_DOUBLE:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,double,Scalar,pyArray,mat);
break;
case NPY_CDOUBLE:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,std::complex<double>,Scalar,pyArray,mat);
break;
case NPY_LONGDOUBLE:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,long double,Scalar,pyArray,mat);
break;
case NPY_CLONGDOUBLE:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,std::complex<long double>,Scalar,pyArray,mat);
break;
default:
throw Exception("You asked for a conversion which is not implemented.");
}
}
else
{
assert(pyArray_Type == NumpyEquivalentType<Scalar>::type_code);
typename MapNumpy<MatType,Scalar,Options,NumpyMapStride>::EigenMap numpyMap = MapNumpy<MatType,Scalar,Options,NumpyMapStride>::map(pyArray);
RefType mat_ref(numpyMap);
new (raw_ptr) StorageType(mat_ref,pyArray);
}
}

static void copy(RefType const & ref, PyArrayObject * pyArray)
{
EigenAllocator<MatType>::copy(ref,pyArray);
}
};

template<typename MatType, int Options, typename Stride>
struct EigenAllocator<const Eigen::Ref<const MatType,Options,Stride> >
{
typedef const Eigen::Ref<const MatType,Options,Stride> RefType;
typedef typename MatType::Scalar Scalar;

typedef typename ::boost::python::detail::referent_storage<RefType&>::StorageType StorageType;

static void allocate(PyArrayObject * pyArray,
bp::converter::rvalue_from_python_storage<RefType> * storage)
{
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)
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)))
|| MatType::IsVectorAtCompileTime
|| (PyArray_IS_F_CONTIGUOUS(pyArray) && PyArray_IS_C_CONTIGUOUS(pyArray))) // no need to allocate
need_to_allocate |= false;
else
need_to_allocate |= true;
if(Options != Eigen::Unaligned) // we need to check whether the memory is correctly aligned and composed of a continuous segment
{
void * data_ptr = PyArray_DATA(pyArray);
if(!PyArray_ISONESEGMENT(pyArray) || !is_aligned(data_ptr,Options))
need_to_allocate |= true;
}

void * raw_ptr = storage->storage.bytes;
if(need_to_allocate)
{
MatType * mat_ptr;
mat_ptr = details::init_matrix_or_array<MatType>::run(pyArray);
RefType mat_ref(*mat_ptr);

new (raw_ptr) StorageType(mat_ref,pyArray,mat_ptr);

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

switch(pyArray_Type)
{
case NPY_INT:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,int,Scalar,pyArray,mat);
break;
case NPY_LONG:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,long,Scalar,pyArray,mat);
break;
case NPY_FLOAT:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,float,Scalar,pyArray,mat);
break;
case NPY_CFLOAT:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,std::complex<float>,Scalar,pyArray,mat);
break;
case NPY_DOUBLE:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,double,Scalar,pyArray,mat);
break;
case NPY_CDOUBLE:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,std::complex<double>,Scalar,pyArray,mat);
break;
case NPY_LONGDOUBLE:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,long double,Scalar,pyArray,mat);
break;
case NPY_CLONGDOUBLE:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,std::complex<long double>,Scalar,pyArray,mat);
break;
default:
throw Exception("You asked for a conversion which is not implemented.");
}
}
else
{
assert(pyArray_Type == NumpyEquivalentType<Scalar>::type_code);
typename MapNumpy<MatType,Scalar,Options,NumpyMapStride>::EigenMap numpyMap = MapNumpy<MatType,Scalar,Options,NumpyMapStride>::map(pyArray);
RefType mat_ref(numpyMap);
new (raw_ptr) StorageType(mat_ref,pyArray);
}
}

static void copy(RefType const & ref, PyArrayObject * pyArray)
{
EigenAllocator<MatType>::copy(ref,pyArray);
}
};

template<typename MatType>
struct EigenAllocator< eigenpy::Ref<MatType> >
{
Expand Down
Loading