Basics
Tensor types
xarray<T>
: tensor that can be reshaped to any number of dimensions.xtensor<T, N>
: tensor with a number of dimensions set toN
at compile time.xtensor_fixed<T, xshape<I, J, K>
: tensor whose shape is fixed at compile time.xchunked_array<CS>
: chunked array using theCS
chunk storage.
Note
Except if mentioned otherwise, the methods described below are available for the
three kinds of containers, even if the examples show xt::xarray
usage only.
Initialization
Tensor with dynamic shape:
#include <xtensor/xarray.hpp>
xt::xarray<double>::shape_type shape = {2, 3};
xt::xarray<double> a0(shape);
xt::xarray<double> a1(shape, 2.5);
xt::xarray<double> a2 = {{1., 2., 3.}, {4., 5., 6.}};
auto a3 = xt::xarray<double>::from_shape(shape);
Tensor with static number of dimensions:
#include <xtensor/xtensor.hpp>
xt::xtensor<double, 2>::shape_type shape = {2, 3};
xt::xtensor<double, 2> a0(shape);
xt::xtensor<double, 2> a1(shape, 2.5);
xt::xtensor<double, 2> a2 = {{1., 2., 3.}, {4., 5., 6.}};
auto a3 = xt::xtensor<double, 2>::from_shape(shape);
Tensor with fixed shape:
#include <xtensor/xfixed.hpp>
xt::xtensor_fixed<double, xt::xshape<2, 3>> = {{1., 2., 3.}, {4., 5., 6.}};
In-memory chunked tensor with dynamic shape:
#include <xtensor/xchunked_array.hpp>
std::vector<std::size_t> shape = {10, 10, 10};
std::vector<std::size_t> chunk_shape = {2, 3, 4};
auto a = xt::chunked_array<double>(shape, chunk_shape);
Output
#include <xtensor/xarray.hpp>
#include <xtensor/xfixed.hpp>
#include <xtensor/xio.hpp>
#include <xtensor/xtensor.hpp>
xt::xarray<double> a = {{1., 2.}, {3., 4.}};
std::cout << a << std::endl;
xt::xtensor<double, 2> b = {{1., 2.}, {3., 4.}};
std::cout << b << std::endl;
xt::xtensor_fixed<double, xt::xshape<2, 2>> c = {{1., 2.}, {3., 4.}};
std::cout << c << std::endl;
Shape - dimension - size
xt::xarray<double> a = {{1., 2., 3.}, {4., 5., 6.}};
auto size = a.size(); // size = 6
auto dim = a.dimension(); // dim = 2
auto shape = a.shape(); // shape = {2, 3}
auto sh1 = a.shape(1); // sh1 = 3
Print the shape
xt::xarray<double> a = {{1., 2., 3.}, {4., 5., 6.}};
auto shape = a.shape();
std::cout << xt::adapt(shape) << std::endl;
Reshape
The number of elements of an xt::xarray
must remain the same:
xt::xarray<double> a0 = {1., 2., 3., 4., 5., 6.};
a0.reshape({2, 3});
std::cout << a0 << std::endl;
// outputs {{1., 2., 3.}, {4., 5., 6. }}
For xt::xtensor
the number of elements and the number of dimensions
must remain the same:
xt::xtensor<double, 2> a1 = {{1., 2.}, {3., 4.}, {5., 6.}};
a1.reshape({2, 3});
std::cout << a1 << std::endl;
// outputs {{1., 2., 3.}, {4., 5., 6. }}
One value in the shape can be -1. In this case, the value is inferred from the length of the underlying buffer and remaining dimensions:
xt::xarray<double> a0 = {1., 2., 3., 4., 5., 6.};
a0.reshape({2, -1});
std::cout << a0 << std::endl;
// outputs {{1., 2., 3.}, {4., 5., 6. }}
xt::xtensor<double, 2> a1 = {{1., 2.}, {3., 4.}, {5., 6.}};
a1.reshape({-1, 3});
std::cout << a1 << std::endl;
// outputs {{1., 2., 3.}, {4., 5., 6. }}
reshape
is not defined for xtensor_fixed
.
Resize
xt::xarray<double> a0 = {1., 2., 3, 4.};
a0.resize({2, 3});
When resizing an xt::xtensor
object, the number of dimensions must remain
the same:
xt::xtensor<double, 2> a1 = {{1., 2.}, {3., 4.}};
a1.resize({2, 3});
resize
is not defined for xtensor_fixed
.
Warning
Contrary to STL containers like std::vector, resize do NOT preserve elements.
Element access
xt::xarray<double> a = {{1., 2., 3.}, {4., 5., 6.}};
double d0 = a(0, 2); // d0 is 3.
double d1 = a(2); // d1 is a(0, 2)
double d2 = a[{0, 2}]; // d2 is a(0, 2)
The same operators are used for writing values:
xt::xarray<double> a = {{1., 2., 3.}, {4., 5., 6.}};
a(0, 2) = 8.;
a(2) = 8.;
a[{0, 2}] = 8.;
The at
method is an access operator with bound checking:
xt::xarray<double> a = {{1., 2., 3.}, {4., 5., 6.}};
double d0 = a.at(0, 3); // throws
double d1 = a.at(3); // throws
The periodic
method is an access operator that applies periodicity
to its arguments:
xt::xarray<double> a = {{1., 2., 3.}, {4., 5., 6.}};
double d0 = a.periodic(2, -1); // d0 is 3
Fill
auto a = xt::xarray<double>::from_shape({2, 3});
a.fill(2.);
std::cout << a << std::endl;
// Outputs {{2., 2., 2.}, {2., 2., 2.}}
Iterators
xtensor containers provide iterators compatible with algorithms from the STL:
xt::xarray<double> a = {{1., 2., 3.}, {4., 5., 6.}};
xt::xarray<double> b(a.shape());
std::transform(a.cbegin(), a.cend(), b.begin(), [](auto&& v) { return v + 1; });
std::cout << b << std::endl;
// Outputs {{2., 3., 4.}, {5., 6., 7.}}
Reverse iterators are also available:
xt::xarray<double> a = {{1., 2., 3.}, {4., 5., 6.}};
xt::xarray<double> b(a.shape());
std::copy(a.crbegin(), a.crend(), b.begin());
std::cout << b << std::endl;
// Outputs {{6., 5., 4.}, {3., 2., 1.}}
Data buffer
The underlying 1D data buffer can be accessed with the data
method:
xt::xarray<double> a = {{1., 2., 3.}, {4., 5., 6.}};
a.data()[4] = 8.;
std::cout << a << std::endl;
// Outputs {{1., 2., 3.}, {8., 5., 6.}}