Boost C++ 库

……全球备受推崇且设计精湛的 C++ 库项目之一。 Herb SutterAndrei Alexandrescu《C++ 编码标准》

创建 ndarrays - Boost.Python NumPy 扩展 1.0 文档 - Boost C++ 函数库

(NumPy)

创建 ndarrays

Boost.Numpy 库提供了许多创建 ndarrays 的方法。ndarray 可以通过多种方式创建,包括空数组和全零数组。ndarray 还可以从任意 Python 序列以及数据和 dtypes 创建。

本教程将介绍创建 ndarrays 的一些方法。这里介绍的方法包括从任意 Python 序列创建 ndarrays,以及从 C++ 容器创建,同时使用单位步幅和非单位步幅。

首先,一如既往,初始化必要的命名空间和运行时。

#include <boost/python/numpy.hpp>
#include <iostream>

namespace p = boost::python;
namespace np = boost::python::numpy;

int main(int argc, char **argv)
{
  Py_Initialize();
  np::initialize();

现在,我们从一个简单的元组创建一个 ndarray。我们先创建一个元组对象,然后将其传递给 array 方法,以生成所需的元组。

p::object tu = p::make_tuple('a','b','c');
np::ndarray example_tuple = np::array(tu);

现在,我们尝试用列表做同样的事情。我们创建一个空列表,使用 append 方法添加一个元素,然后像以前一样调用 array 方法。

p::list l;
l.append('a');
np::ndarray example_list = np::array (l);

可选地,我们还可以为数组指定 dtype。

np::dtype dt = np::dtype::get_builtin<int>();
np::ndarray example_list1 = np::array (l,dt);

我们还可以通过提供数据数组和其他一些参数来创建数组。

首先,创建一个整数数组。

int data[] = {1,2,3,4,5};

创建函数所需的 shape 和 strides。

p::tuple shape = p::make_tuple(5);
p::tuple stride = p::make_tuple(sizeof(int));

这里,shape 是 (4,),stride 是 `sizeof(int)`。步幅是在构造 ndarray 时,为了获取下一个期望的元素而必须跳过的字节数。

该函数还需要一个 owner,来跟踪传递的数据数组。传递 None 是危险的。

p::object own;

from_data 函数以数据数组、数据类型、shape、stride 和 owner 作为参数,并返回一个 ndarray。

np::ndarray data_ex1 = np::from_data(data,dt, shape,stride,own);

现在,我们打印创建的 ndarray。

std::cout << "Single dimensional array ::" << std::endl
          << p::extract<char const *>(p::str(data_ex)) << std::endl;

让我们让事情变得更有趣一些。让我们使用非单位步幅,从一个多维数组创建一个 3x2 的 ndarray。

首先,创建一个包含 8 位整数的 3x4 数组。

uint8_t mul_data[][4] = {{1,2,3,4},{5,6,7,8},{1,3,5,7}};

现在,让我们创建一个包含 3x2 个元素的数组,从每一行中选择第一个和第三个元素。为此,shape 将是 3x2。strides 将是 4x2,即 4 字节移动到下一个期望的行,2 字节移动到下一个期望的列。

shape = p::make_tuple(3,2);
stride = p::make_tuple(sizeof(uint8_t)*2,sizeof(uint8_t));

获取内置 8 位整数数据类型的 NumPy dtype。

np::dtype dt1 = np::dtype::get_builtin<uint8_t>();

现在,我们先创建并打印出 ndarray。请注意,我们可以直接在函数中传递 shape 和 strides,以及 owner。最后一部分可以这样做,因为我们不需要操作“owner”对象。

np::ndarray mul_data_ex = np::from_data(mul_data, dt1,
                                        p::make_tuple(3,4),
                                        p::make_tuple(4,1),
                                        p::object());
std::cout << "Original multi dimensional array :: " << std::endl
          << p::extract<char const *>(p::str(mul_data_ex)) << std::endl;

现在,使用 shape 和 strides 创建新的 ndarray,并打印出我们使用非单位步幅创建的数组。

  mul_data_ex = np::from_data(mul_data, dt1, shape, stride, p::object());
  std::cout << "Selective multidimensional array :: "<<std::endl
            << p::extract<char const *>(p::str(mul_data_ex)) << std::endl ;
}

注意

如果 shape 和相应的 strides 所规定的元素数量不匹配,from_data 方法将抛出 `error_already_set`。