Python bindings for the xtensor C++ multi-dimensional array library.
-
xtensor
is a C++ library for multi-dimensional arrays enabling numpy-style broadcasting and lazy computing. -
xtensor-python
enables inplace use of numpy arrays in C++ with all the benefits fromxtensor
- C++ universal function and broadcasting
- STL - compliant APIs.
- A broad coverage of numpy APIs (see the numpy to xtensor cheat sheet).
The Python bindings for xtensor
are based on the pybind11 C++ library, which enables seamless interoperability between C++ and Python.
xtensor-python
is a header-only library. We provide a package for the mamba (or conda) package manager.
mamba install -c conda-forge xtensor-python
To get started with using xtensor-python
, check out the full documentation
http://xtensor-python.readthedocs.io/
xtensor-python offers two container types wrapping numpy arrays inplace to provide an xtensor semantics
pytensor
pyarray
.
Both containers enable the numpy-style APIs of xtensor (see the numpy to xtensor cheat sheet).
-
On the one hand,
pyarray
has a dynamic number of dimensions. Just like numpy arrays, it can be reshaped with a shape of a different length (and the new shape is reflected on the python side). -
On the other hand
pytensor
has a compile time number of dimensions, specified with a template parameter. Shapes ofpytensor
instances are stack allocated, makingpytensor
a significantly faster expression thanpyarray
.
C++ code
#include <numeric> // Standard library import for std::accumulate
#include <pybind11/pybind11.h> // Pybind11 import to define Python bindings
#include <xtensor/xmath.hpp> // xtensor import for the C++ universal functions
#define FORCE_IMPORT_ARRAY
#include <xtensor-python/pyarray.hpp> // Numpy bindings
double sum_of_sines(xt::pyarray<double>& m)
{
auto sines = xt::sin(m); // sines does not actually hold values.
return std::accumulate(sines.begin(), sines.end(), 0.0);
}
PYBIND11_MODULE(xtensor_python_test, m)
{
xt::import_numpy();
m.doc() = "Test module for xtensor python bindings";
m.def("sum_of_sines", sum_of_sines, "Sum the sines of the input values");
}
Python Code
import numpy as np
import xtensor_python_test as xt
v = np.arange(15).reshape(3, 5)
s = xt.sum_of_sines(v)
print(s)
Outputs
1.2853996391883833
Working example
Get the working example here:
C++ code
#include <pybind11/pybind11.h>
#define FORCE_IMPORT_ARRAY
#include <xtensor-python/pyvectorize.hpp>
#include <numeric>
#include <cmath>
namespace py = pybind11;
double scalar_func(double i, double j)
{
return std::sin(i) - std::cos(j);
}
PYBIND11_MODULE(xtensor_python_test, m)
{
xt::import_numpy();
m.doc() = "Test module for xtensor python bindings";
m.def("vectorized_func", xt::pyvectorize(scalar_func), "");
}
Python Code
import numpy as np
import xtensor_python_test as xt
x = np.arange(15).reshape(3, 5)
y = [1, 2, 3, 4, 5]
z = xt.vectorized_func(x, y)
print(z)
Outputs
[[-0.540302, 1.257618, 1.89929 , 0.794764, -1.040465],
[-1.499227, 0.136731, 1.646979, 1.643002, 0.128456],
[-1.084323, -0.583843, 0.45342 , 1.073811, 0.706945]]
We provide a package for the conda package manager.
conda install -c conda-forge xtensor-python
This will pull the dependencies to xtensor-python, that is pybind11
and xtensor
.