NumCpp  2.1.0
A C++ implementation of the Python Numpy library
BoostNumpyNdarrayHelper.hpp
Go to the documentation of this file.
1 #pragma once
30 
31 #ifdef INCLUDE_BOOST_PYTHON_INTERFACE
32 
34 #include "NumCpp/Core/Types.hpp"
35 #include "NumCpp/Utils/num2str.hpp"
36 
37 #include <cmath>
38 #include <iostream>
39 #include <string>
40 #include <utility>
41 #include <vector>
42 
43 #include "boost/python.hpp"
44 #include "boost/python/numpy.hpp"
45 
46 namespace nc
47 {
48  namespace boostPythonInterface
49  {
50  //================================================================================
52  template<typename dtype>
54  {
55  public:
56  //================================================================================
58  enum class Order { F, C };
59 
60  //============================================================================
65  explicit BoostNdarrayHelper(const boost::python::numpy::ndarray& inArray) :
66  theArray_(inArray.astype(boost::python::numpy::dtype::get_builtin<dtype>())),
67  numDimensions_(static_cast<uint8>(inArray.get_nd())),
68  shape_(numDimensions_),
69  strides_(numDimensions_),
70  order_(Order::C)
71 
72  {
73  Py_intptr_t const * shapePtr = inArray.get_shape();
74  for (uint8 i = 0; i < numDimensions_; ++i)
75  {
76  strides_[i] = static_cast<uint32>(theArray_.strides(i));
77  shape_[i] = shapePtr[i];
78  }
79 
80  if (numDimensions_ > 1 && inArray.strides(0) < inArray.strides(1))
81  {
82  order_ = Order::F;
83  }
84  }
85 
86  //============================================================================
91  explicit BoostNdarrayHelper(boost::python::tuple inShape) :
92  theArray_(boost::python::numpy::zeros(inShape, boost::python::numpy::dtype::get_builtin<dtype>())),
93  numDimensions_(static_cast<uint8>(theArray_.get_nd())),
94  shape_(numDimensions_),
95  strides_(numDimensions_),
96  order_(Order::C)
97  {
98  Py_intptr_t const * shapePtr = theArray_.get_shape();
99  for (uint8 i = 0; i < numDimensions_; ++i)
100  {
101  strides_[i] = static_cast<uint32>(theArray_.strides(i));
102  shape_[i] = shapePtr[i];
103  }
104 
105  if (numDimensions_ > 1 && theArray_.strides(0) < theArray_.strides(1))
106  {
107  order_ = Order::F;
108  }
109 
110  }
111 
112 
113  //============================================================================
118  const boost::python::numpy::ndarray& getArray() noexcept
119  {
120  return theArray_;
121  }
122 
123  //============================================================================
128  boost::python::numpy::matrix getArrayAsMatrix()
129  {
130  return boost::python::numpy::matrix(theArray_);
131  }
132 
133  //============================================================================
138  uint8 numDimensions() noexcept
139  {
140  return numDimensions_;
141  }
142 
143  //============================================================================
148  const std::vector<Py_intptr_t>& shape() noexcept
149  {
150  return shape_;
151  }
152 
153  //============================================================================
159  {
160  uint32 theSize = 1;
161  for (auto dimSize : shape_)
162  {
163  theSize *= static_cast<uint32>(dimSize);
164  }
165  return theSize;
166  }
167 
168 
169  //============================================================================
174  const std::vector<uint32>& strides()
175  {
176  return strides_;
177  }
178 
179  //============================================================================
185  {
186  return order_;
187  }
188 
189  //============================================================================
196  bool shapeEqual(BoostNdarrayHelper& otherNdarrayHelper)
197  {
198  if (shape_.size() != otherNdarrayHelper.shape_.size())
199  {
200  return false;
201  }
202 
203  return stl_algorithms::equal(shape_.begin(), shape_.end(), otherNdarrayHelper.shape_.begin());
204  }
205 
206  //============================================================================
213  dtype& operator()(uint32 index)
214  {
215  checkIndices1D(index);
216 
217  return *reinterpret_cast<dtype*>(theArray_.get_data() + strides_.front() * index);
218  }
219 
220  //============================================================================
228  dtype& operator()(uint32 index1, uint32 index2)
229  {
230  checkIndices2D(index1, index2);
231 
232  return *reinterpret_cast<dtype*>(theArray_.get_data() + strides_.front() * index1 + strides_[1] * index2);
233  }
234 
235  //============================================================================
239  {
240  printf("array = \n");
241  if (numDimensions_ != 1)
242  {
243  std::cout << "printArray1D can only be used on a 1D array." << std::endl;
244  return;
245  }
246 
247  for (int32 i = 0; i < shape_.front(); ++i)
248  {
249  printf("\t%f\n", operator()(i));
250  }
251  }
252 
253  //============================================================================
257  {
258  printf("array = \n");
259  if (numDimensions_ != 2)
260  {
261  std::cout << "printArray2D can only be used on a 2D array." << std::endl;
262  return;
263  }
264 
265  for (int32 index1 = 0; index1 < shape_.front(); ++index1)
266  {
267  for (int32 index2 = 0; index2 < shape_.back(); ++index2)
268  {
269  printf("\t%f", operator()(index1, index2));
270  }
271  printf("\n");
272  }
273  }
274 
275  private:
276  //====================================Attributes==============================
277  boost::python::numpy::ndarray theArray_;
278  uint8 numDimensions_;
279  std::vector<Py_intptr_t> shape_;
280  std::vector<uint32> strides_;
281  Order order_;
282 
283  //============================================================================
288  void checkIndicesGeneric(boost::python::tuple indices)
289  {
290  if (boost::python::len(indices) != numDimensions_)
291  {
292  std::string errStr = "Error: BoostNdarrayHelper::checkIndicesGeneric: Array has " + utils::num2str(numDimensions_);
293  errStr += " dimensions, you asked for " + utils::num2str(static_cast<int>(boost::python::len(indices))) + "!";
294  PyErr_SetString(PyExc_RuntimeError, errStr.c_str());
295  }
296 
297  for (int i = 0; i < numDimensions_; ++i)
298  {
299  int index = boost::python::extract<int>(indices[i]);
300  if (index > shape_[i])
301  {
302  std::string errStr = "Error: BoostNdarrayHelper::checkIndicesGeneric: Input index [" + utils::num2str(index);
303  errStr += "] is larger than the size of the array [" + utils::num2str(shape_[i]) + "].";
304  PyErr_SetString(PyExc_RuntimeError, errStr.c_str());
305  }
306  }
307  }
308 
309  //============================================================================
314  void checkIndices1D(uint32 index)
315  {
316  boost::python::tuple indices = boost::python::make_tuple(index);
317  checkIndicesGeneric(indices);
318  }
319 
320  //============================================================================
326  void checkIndices2D(uint32 index1, uint32 index2)
327  {
328  boost::python::tuple indices = boost::python::make_tuple(index1, index2);
329  checkIndicesGeneric(indices);
330  }
331  };
332  } // namespace boostPythonInterface
333 } // namespace nc
334 #endif
nc::zeros
NdArray< dtype > zeros(uint32 inSquareSize)
Definition: zeros.hpp:51
nc::int32
std::int32_t int32
Definition: Types.hpp:37
nc::boostPythonInterface::BoostNdarrayHelper::Order
Order
C or Fortran ordering from python.
Definition: BoostNumpyNdarrayHelper.hpp:58
nc::astype
NdArray< dtypeOut > astype(const NdArray< dtype > inArray)
Definition: astype.hpp:48
nc::uint8
std::uint8_t uint8
Definition: Types.hpp:43
nc::utils::num2str
std::string num2str(dtype inNumber)
Definition: num2str.hpp:47
nc::boostPythonInterface::BoostNdarrayHelper::strides
const std::vector< uint32 > & strides()
Definition: BoostNumpyNdarrayHelper.hpp:174
nc::boostPythonInterface::BoostNdarrayHelper::shape
const std::vector< Py_intptr_t > & shape() noexcept
Definition: BoostNumpyNdarrayHelper.hpp:148
nc::uint32
std::uint32_t uint32
Definition: Types.hpp:41
nc::boostPythonInterface::BoostNdarrayHelper::getArray
const boost::python::numpy::ndarray & getArray() noexcept
Definition: BoostNumpyNdarrayHelper.hpp:118
nc::boostPythonInterface::BoostNdarrayHelper::Order::C
@ C
num2str.hpp
nc::boostPythonInterface::BoostNdarrayHelper::shapeEqual
bool shapeEqual(BoostNdarrayHelper &otherNdarrayHelper)
Definition: BoostNumpyNdarrayHelper.hpp:196
nc::boostPythonInterface::BoostNdarrayHelper::BoostNdarrayHelper
BoostNdarrayHelper(const boost::python::numpy::ndarray &inArray)
Definition: BoostNumpyNdarrayHelper.hpp:65
nc::boostPythonInterface::BoostNdarrayHelper::operator()
dtype & operator()(uint32 index1, uint32 index2)
Definition: BoostNumpyNdarrayHelper.hpp:228
nc::boostPythonInterface::BoostNdarrayHelper
Helper class for ndarray.
Definition: BoostNumpyNdarrayHelper.hpp:53
nc
Definition: Coordinate.hpp:45
nc::boostPythonInterface::BoostNdarrayHelper::size
uint32 size()
Definition: BoostNumpyNdarrayHelper.hpp:158
nc::boostPythonInterface::BoostNdarrayHelper::printArray1D
void printArray1D()
Definition: BoostNumpyNdarrayHelper.hpp:238
nc::boostPythonInterface::BoostNdarrayHelper::numDimensions
uint8 numDimensions() noexcept
Definition: BoostNumpyNdarrayHelper.hpp:138
nc::boostPythonInterface::BoostNdarrayHelper::getArrayAsMatrix
boost::python::numpy::matrix getArrayAsMatrix()
Definition: BoostNumpyNdarrayHelper.hpp:128
nc::boostPythonInterface::BoostNdarrayHelper::printArray2D
void printArray2D()
Definition: BoostNumpyNdarrayHelper.hpp:256
StlAlgorithms.hpp
nc::stl_algorithms::equal
bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2) noexcept
Definition: StlAlgorithms.hpp:136
Types.hpp
nc::boostPythonInterface::BoostNdarrayHelper::Order::F
@ F
nc::boostPythonInterface::BoostNdarrayHelper::operator()
dtype & operator()(uint32 index)
Definition: BoostNumpyNdarrayHelper.hpp:213
nc::boostPythonInterface::BoostNdarrayHelper::order
Order order()
Definition: BoostNumpyNdarrayHelper.hpp:184
nc::boostPythonInterface::BoostNdarrayHelper::BoostNdarrayHelper
BoostNdarrayHelper(boost::python::tuple inShape)
Definition: BoostNumpyNdarrayHelper.hpp:91