Indices
Definition
There are two types of indices: array indices and flat indices. Consider this example (stored in row-major):
#include <xtensor/xtensor.hpp>
#include <xtensor/xarray.hpp>
#include <xtensor/xio.hpp>
int main()
{
xt::xarray<size_t> a = xt::arange<size_t>(3 * 4);
a.reshape({3,4});
std::cout << a << std::endl;
}
Which prints
{{ 0, 1, 2, 3},
{ 4, 5, 6, 7},
{ 8, 9, 10, 11}}
The array index {1, 2}
corresponds to the flat index 6
.
Operators: array index
An array index can be specified to an operators by a sequence of numbers. To this end the following operators are at your disposal:
operator()(args...)
Example:
a(1, 2) == 6
.See also:
xt::xcontainer::operator()()
.
Returns a (constant) reference to the element, specified by an array index given by a number of unsigned integers.
If the number of indices is less that the dimension of the array, the indices are pre-padded with zeros until the dimension is matched (example:
a(2) == a(0, 2) == 2
).If the number of indices is greater than the dimension of the array, the first
#indices - dimension
indices are ignored.To post-pad an arbitrary number of zeros use
xt::missing
(examplea(2, xt::missing) == a(2, 0) == 8
.
at(args...)
Example:
a.at(1, 2) == 6
.See also:
xt::xcontainer::at()
.
Same as operator()()
:
Returns a (constant) reference to the element,
specified by an array index given by a number of unsigned integers.
unchecked(args...)
Example:
a.unchecked(1, 2) == 6
.See also:
xt::xcontainer::unchecked()
.
Returns a (constant) reference to the element,
specified by an array index given by a number of unsigned integers.
Different than operator()()
there are no bounds checks (even when assertions)
are turned on, and the number of indices is assumed to match the dimension of the array.
unchecked()
is thus aimed at performance.
Note
If you assume responsibility for bounds-checking, this operator can be used to virtually
post-pad zeros if you specify less indices than the rank of the array.
Example: a.unchecked(1) == a(1, 0)
.
periodic(args...)
Example:
a.periodic(-1, -2) == 7
.See also:
xt::xcontainer::periodic()
.
Returns a (constant) reference to the element,
specified by an array index given by a number of signed integers.
Negative and ‘overflowing’ indices are changed by assuming periodicity along that axis.
For example, for the first axis: -1 -> a.shape(0) - 1 = 2
,
likewise for example 3 -> 3 - a.shape(0) = 0
.
Of course this comes as the cost of some extra complexity.
in_bounds(args...)
Example:
a.in_bounds(1, 2) == true
.See also:
xt::xcontainer::in_bounds()
.
Check if the array index is ‘in bounds’, return false
otherwise.
operator[]({...})
Example:
a[{1, 2}] == 6
.See also:
xt::xcontainer::operator[]()
.
Returns a (constant) reference to the element, specified by an array index given by a list of unsigned integers.
Operators: flat index
flat(i)
Example:
a.flat(6) == 6
.See also:
xt::xcontainer::flat()
.
Returns a (constant) reference to the element specified by a flat index, given an unsigned integer.
Note
If the layout would not have been the default row major,
but column major, then a.flat(6) == 2
.
Note
In many cases a.flat(i) == a.data()[i]
.
Array indices
Functions like xt::argwhere(a < 5)
return a std::vector
of array indices.
Using the same matrix as above, we can do
int main()
{
xt::xarray<size_t> a = xt::arange<size_t>(3 * 4);
a.reshape({3,4});
auto idx = xt::from_indices(xt::argwhere(a >= 6));
std::cout << idx << std::endl;
}
which prints
{{1, 2},
{1, 3},
{2, 0},
{2, 1},
{2, 2},
{2, 3}}
To print the std::vector
, it is converted to a xt::xtensor<size_t, 2>
array, which is done using xt::from_indices()
.
From array indices to flat indices
To convert the array indices to a xt::xtensor<size_t, 1>
of flat indices,
xt::ravel_indices()
can be used.
For the same example:
#include <xtensor/xtensor.hpp>
#include <xtensor/xarray.hpp>
#include <xtensor/xio.hpp>
int main()
{
xt::xarray<size_t> a = xt::arange<size_t>(3 * 4);
a.reshape({3,4});
auto idx = xt::ravel_indices(xt::argwhere(a >= 6), a.shape());
std::cout << idx << std::endl;
}
which prints
{ 6, 7, 8, 9, 10, 11}
Note
To convert to a std::vector
use
auto idx = xt::ravel_indices<xt::ravel_vector_tag>(xt::argwhere(a >= 6), a.shape());
1-D arrays: array indices == flat indices
For 1-D arrays the array indices and flat indices coincide.
One can use the generic functions xt::flatten_indices()
to get a
xt::xtensor<size_t, 1>
of (array/flat) indices.
For example:
#include <xtensor/xtensor.hpp>
#include <xtensor/xview.hpp>
#include <xtensor/xio.hpp>
int main()
{
xt::xtensor<size_t, 1> a = xt::arange<size_t>(16);
auto idx = xt::flatten_indices(xt::argwhere(a >= 6));
std::cout << idx << std::endl;
std::cout << xt::view(a, xt::keep(idx)) << std::endl;
}
which prints the indices and the selection (which are in this case identical):
{ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
{ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
From flat indices to array indices
To convert flat indices to array_indices the function xt::unravel_indices()
can be used.
For example
#include <xtensor/xarray.hpp>
#include <xtensor/xtensor.hpp>
#include <xtensor/xstrides.hpp>
#include <xtensor/xio.hpp>
int main()
{
xt::xarray<size_t> a = xt::arange<size_t>(3 * 4);
a.reshape({3,4});
auto flat_indices = xt::ravel_indices(xt::argwhere(a >= 6), a.shape());
auto array_indices = xt::from_indices(xt::unravel_indices(flat_indices, a.shape()));
std::cout << "flat_indices = " << std::endl << flat_indices << std::endl;
std::cout << "array_indices = " << std::endl << array_indices << std::endl;
}
which prints
flat_indices =
{ 6, 7, 8, 9, 10, 11}
array_indices =
{{1, 2},
{1, 3},
{2, 0},
{2, 1},
{2, 2},
{2, 3}}
Notice that once again the function xt::from_indices()
has been used to convert a
std::vector
of indices to a xt::xtensor
array for printing.