# 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 to `N` at compile time.

- `xtensor_fixed<T, xshape<I, J, K>`: tensor whose shape is fixed at compile time.

- `xchunked_array<CS>`: chunked array using the `CS` 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/containers/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/containers/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/containers/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/chunk/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/containers/xarray.hpp>
    #include <xtensor/containers/xfixed.hpp>
    #include <xtensor/io/xio.hpp>
    #include <xtensor/containers/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.}}