numpy-map.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2014-2019, CNRS
3  * Copyright 2018-2020, INRIA
4  */
5 
6 #ifndef __eigenpy_numpy_map_hpp__
7 #define __eigenpy_numpy_map_hpp__
8 
9 #include "eigenpy/fwd.hpp"
10 #include "eigenpy/exception.hpp"
11 #include "eigenpy/stride.hpp"
12 
13 namespace eigenpy
14 {
15  template<typename MatType, typename InputScalar, int AlignmentValue, typename Stride, bool IsVector = MatType::IsVectorAtCompileTime>
16  struct NumpyMapTraits {};
17 
18  /* Wrap a numpy::array with an Eigen::Map. No memory copy. */
19  template<typename MatType, typename InputScalar, int AlignmentValue = EIGENPY_NO_ALIGNMENT_VALUE, typename Stride = typename StrideType<MatType>::type>
20  struct NumpyMap
21  {
23  typedef typename Impl::EigenMap EigenMap;
24 
25  static EigenMap map(PyArrayObject* pyArray, bool swap_dimensions = false);
26  };
27 
28 } // namespace eigenpy
29 
30 /* --- DETAILS ------------------------------------------------------------------ */
31 /* --- DETAILS ------------------------------------------------------------------ */
32 /* --- DETAILS ------------------------------------------------------------------ */
33 
34 namespace eigenpy
35 {
36  template<typename MatType, typename InputScalar, int AlignmentValue, typename Stride>
37  struct NumpyMapTraits<MatType,InputScalar,AlignmentValue,Stride,false>
38  {
39  typedef Eigen::Matrix<InputScalar,MatType::RowsAtCompileTime,MatType::ColsAtCompileTime,MatType::Options> EquivalentInputMatrixType;
40  typedef Eigen::Map<EquivalentInputMatrixType,AlignmentValue,Stride> EigenMap;
41 
42  static EigenMap mapImpl(PyArrayObject* pyArray, bool swap_dimensions = false)
43  {
44  enum {
45  OuterStrideAtCompileTime = Stride::OuterStrideAtCompileTime,
46  InnerStrideAtCompileTime = Stride::InnerStrideAtCompileTime,
47  };
48 
49  assert(PyArray_NDIM(pyArray) == 2 || PyArray_NDIM(pyArray) == 1);
50 
51  const long int itemsize = PyArray_ITEMSIZE(pyArray);
52  int inner_stride = -1, outer_stride = -1;
53  int rows = -1, cols = -1;
54  if(PyArray_NDIM(pyArray) == 2)
55  {
56  assert( (PyArray_DIMS(pyArray)[0] < INT_MAX)
57  && (PyArray_DIMS(pyArray)[1] < INT_MAX)
58  && (PyArray_STRIDE(pyArray,0) < INT_MAX)
59  && (PyArray_STRIDE(pyArray,1) < INT_MAX) );
60 
61  rows = (int)PyArray_DIMS(pyArray)[0];
62  cols = (int)PyArray_DIMS(pyArray)[1];
63 
64  if(EquivalentInputMatrixType::IsRowMajor)
65  {
66  inner_stride = (int)PyArray_STRIDE(pyArray, 1) / (int)itemsize;
67  outer_stride = (int)PyArray_STRIDE(pyArray, 0) / (int)itemsize;
68  }
69  else
70  {
71  inner_stride = (int)PyArray_STRIDE(pyArray, 0) / (int)itemsize;
72  outer_stride = (int)PyArray_STRIDE(pyArray, 1) / (int)itemsize;
73  }
74  }
75  else if(PyArray_NDIM(pyArray) == 1)
76  {
77  assert( (PyArray_DIMS(pyArray)[0] < INT_MAX)
78  && (PyArray_STRIDE(pyArray,0) < INT_MAX));
79 
80  if(!swap_dimensions)
81  {
82  rows = (int)PyArray_DIMS(pyArray)[0];
83  cols = 1;
84 
85  inner_stride = (int)PyArray_STRIDE(pyArray, 0) / (int)itemsize;
86  outer_stride = 0;
87  }
88  else
89  {
90  rows = 1;
91  cols = (int)PyArray_DIMS(pyArray)[0];
92 
93  inner_stride = 0;
94  outer_stride = (int)PyArray_STRIDE(pyArray, 0) / (int)itemsize;
95  }
96  }
97 
98  // Specific care for Eigen::Stride<-1,0>
99  if(InnerStrideAtCompileTime==0 && OuterStrideAtCompileTime==Eigen::Dynamic)
100  {
101  outer_stride = std::max(inner_stride,outer_stride); inner_stride = 0;
102  }
103 
104  Stride stride(OuterStrideAtCompileTime==Eigen::Dynamic?outer_stride:OuterStrideAtCompileTime,
105  InnerStrideAtCompileTime==Eigen::Dynamic?inner_stride:InnerStrideAtCompileTime);
106 
107  if( (MatType::RowsAtCompileTime != rows)
108  && (MatType::RowsAtCompileTime != Eigen::Dynamic) )
109  { throw eigenpy::Exception("The number of rows does not fit with the matrix type."); }
110 
111  if( (MatType::ColsAtCompileTime != cols)
112  && (MatType::ColsAtCompileTime != Eigen::Dynamic) )
113  { throw eigenpy::Exception("The number of columns does not fit with the matrix type."); }
114 
115  InputScalar* pyData = reinterpret_cast<InputScalar*>(PyArray_DATA(pyArray));
116 
117  return EigenMap(pyData, rows, cols, stride);
118  }
119  };
120 
121  template<typename MatType, typename InputScalar, int AlignmentValue, typename Stride>
122  struct NumpyMapTraits<MatType,InputScalar,AlignmentValue,Stride,true>
123  {
124  typedef Eigen::Matrix<InputScalar,MatType::RowsAtCompileTime,MatType::ColsAtCompileTime,MatType::Options> EquivalentInputMatrixType;
125  typedef Eigen::Map<EquivalentInputMatrixType,AlignmentValue,Stride> EigenMap;
126 
127  static EigenMap mapImpl(PyArrayObject* pyArray, bool swap_dimensions = false)
128  {
129  EIGENPY_UNUSED_VARIABLE(swap_dimensions);
130  assert( PyArray_NDIM(pyArray) <= 2 );
131 
132  int rowMajor;
133  if( PyArray_NDIM(pyArray)==1 ) rowMajor = 0;
134  else if (PyArray_DIMS(pyArray)[0] == 0) rowMajor = 0; // handle zero-size vector
135  else if (PyArray_DIMS(pyArray)[1] == 0) rowMajor = 1; // handle zero-size vector
136  else rowMajor = (PyArray_DIMS(pyArray)[0]>PyArray_DIMS(pyArray)[1])?0:1;
137 
138  assert( (PyArray_DIMS(pyArray)[rowMajor]< INT_MAX)
139  && (PyArray_STRIDE(pyArray, rowMajor) ));
140  const int R = (int)PyArray_DIMS(pyArray)[rowMajor];
141  const long int itemsize = PyArray_ITEMSIZE(pyArray);
142  const int stride = (int) PyArray_STRIDE(pyArray, rowMajor) / (int) itemsize;;
143 
144  if( (MatType::MaxSizeAtCompileTime != R)
145  && (MatType::MaxSizeAtCompileTime != Eigen::Dynamic) )
146  { throw eigenpy::Exception("The number of elements does not fit with the vector type."); }
147 
148  InputScalar* pyData = reinterpret_cast<InputScalar*>(PyArray_DATA(pyArray));
149 
150  return EigenMap( pyData, R, Stride(stride) );
151  }
152  };
153 
154  template<typename MatType, typename InputScalar, int AlignmentValue, typename Stride>
156  NumpyMap<MatType,InputScalar,AlignmentValue,Stride>::map(PyArrayObject * pyArray, bool swap_dimensions)
157  {
158  return Impl::mapImpl(pyArray,swap_dimensions);
159  }
160 
161 } // namespace eigenpy
162 
163 #endif // define __eigenpy_numpy_map_hpp__
Impl::EigenMap EigenMap
Definition: numpy-map.hpp:23
static EigenMap mapImpl(PyArrayObject *pyArray, bool swap_dimensions=false)
Definition: numpy-map.hpp:42
Eigen::Matrix< InputScalar, MatType::RowsAtCompileTime, MatType::ColsAtCompileTime, MatType::Options > EquivalentInputMatrixType
Definition: numpy-map.hpp:124
Eigen::Matrix< InputScalar, MatType::RowsAtCompileTime, MatType::ColsAtCompileTime, MatType::Options > EquivalentInputMatrixType
Definition: numpy-map.hpp:39
static EigenMap mapImpl(PyArrayObject *pyArray, bool swap_dimensions=false)
Definition: numpy-map.hpp:127
NumpyMapTraits< MatType, InputScalar, AlignmentValue, Stride > Impl
Definition: numpy-map.hpp:22
Eigen::Map< EquivalentInputMatrixType, AlignmentValue, Stride > EigenMap
Definition: numpy-map.hpp:125
static EigenMap map(PyArrayObject *pyArray, bool swap_dimensions=false)
Definition: numpy-map.hpp:156
#define EIGENPY_UNUSED_VARIABLE(var)
Definition: fwd.hpp:33
Eigen::Map< EquivalentInputMatrixType, AlignmentValue, Stride > EigenMap
Definition: numpy-map.hpp:40


eigenpy
Author(s): Justin Carpentier, Nicolas Mansard
autogenerated on Sat Apr 17 2021 02:37:59