By using boost.python or boost.numpy, you can easily create a python module that can handle numpy.ndarray in c ++. Although boost.numpy is a well-made library, it has some inconveniences in accessing data, such as not being able to use iterators. Therefore, make the data easily accessible.
It is a multidimensional array provided by numpy, one of the python packages. Without this, numerical calculations in python are so widely used that it is impossible.
A library that allows you to operate numpy from c ++. Access the data as follows.
namespace bp = boost::python;
namespace np = boost::numpy;
void func(np::ndarray &data2d) {
//data2d is i as a two-dimensional array,Assign 0 to j element
for (int i = 0; i < data2d.shape(0); ++i) {
for (int j = 0; j < data2d.shape(1); ++j) {
data2d[bp::make_tuple(i, j)] = 0.0;
}
}
}
In order to use this trick, the following conditions must be met.
I think the first condition will be met in many cases. Also, the second one should be satisfied unless it is a variable that was originally cut out from a large array.
Use boost.multi_array_ref. Since numpy.ndarray is a python multidimensional array, c ++ also uses the multidimensional array library. boost.multi_array_ref is a self-allocating version of boost.multi_array. Click here for a detailed explanation of boost.multi_array. (boost :: multi_array --Kmonos.net) By the way, there is a version that can only read boost.const_multi_array_ref and cannot write.
void func(np:ndarray &data2d) {
const std::array<int, 2> shape = {data2d.shape(0), data2d.shape(1)};
boost::multi_array_ref<double, 2> wrapper(reinterpret_cast<double*>(data2d.get_data()), shape);
// i,wrapper for j element[i][j]Can be accessed with, but uses an iterator
for (boost::multi_array_ref_double, 2>::subarray<1>::type &&sub : wrapper) {
boost::fill(sub, 0.0);
}
}
Then you can access it like this.
Of course, there is some overhead associated with using boost.multi_array_ref. There is also a way to manipulate pointers directly (Boost.NumPy Tutorial for Extending Python in C ++ (Practice)), but with some overhead. I would like to take safety measures without worrying about it.
By the way, in the above example, boost :: multi_array_ref <double, 2>
and a wrapper for a two-dimensional array are prepared because it is easy to understand and has a meaning of introduction.
const std::array<int, 1> shape = {data2d.shape(0) * data2d.shape(1)};
boost::multi_array_ref<double, 1> wrapper(reinterpret_cast<double*>(data2d.get_data()), shape);
boost::fill(wrapper, 0.0);
By doing so, the process is completed in one shot.
After all, the boost library can be relied on here as well. If you know of any other good ways (libraries other than boost.multi_array_ref, something to replace boost.numpy, etc.), please let us know.
Recommended Posts