Common pitfalls

xarray initialization

xt::xarray<double> a({1, 3, 4, 2});

does not initialize a 4D-array, but a 1D-array containing the values 1, 3, 4, and 2. It is strictly equivalent to

xt::xarray<double> a = {1, 3, 4, 2};

To initialize a 4D-array with the given shape, use the from_shape static method:

auto a = xt::xarray<double>::from_shape({1, 3, 4, 2});

The confusion often comes from the way xtensor can be initialized:

xt::xtensor<double, 4> a = {1, 3, 4, 2};

In this case, a 4D-tensor with shape (1, 3, 4, 2) is initialized.

Intermediate result

Consider the following function:

template <class C>
auto func(const C& c)
{
    return (1 - func_tmp(c)) / (1 + func_tmp(c));
}

where func_tmp is another unary function accepting an xtensor expression. You may be tempted to simplify it a bit:

template <class C>
auto func(const C& c)
{
    auto tmp = func_tmp(c);
    return (1 - tmp) / (1 + tmp);
}

Unfortunately, you introduced a bug; indeed, expressions in xtensor are not evaluated immediately, they capture their arguments by reference or copy depending on their nature, for future evaluation. Since tmp is an lvalue, it is captured by reference in the last statement; when the function returns, tmp is destroyed, leading to a dangling reference in the returned expression.

Replacing auto tmp with xt::xarray<double> tmp does not change anything, tmp is still an lvalue and thus captured by reference.

Random numbers not consistent

Using a random number function from xtensor actually returns a lazy generator. That means, accessing the same element of a random number generator does not give the same random number if called twice.

auto gen = xt::random::rand<double>({10, 10});
auto a0 = gen(0, 0);
auto a1 = gen(0, 0);

// a0 != a1 !!!

You need to explicitly assign or eval a random number generator, like so:

xt::xarray<double> xr = xt::random::rand<double>({10, 10});
auto xr2 = eval(xt::random::rand<double>({10, 10}));

// now xr(0, 0) == xr(0, 0) is true.