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 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 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 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 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.}}