# Indices

## Definition

There are two types of indices: array indices and flat indices. Consider this example (stored in row-major):

    #include <xtensor/containers/xtensor.hpp>
    #include <xtensor/containers/xarray.hpp>
    #include <xtensor/io/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` (example `a(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/containers/xtensor.hpp>
    #include <xtensor/containers/xarray.hpp>
    #include <xtensor/io/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/containers/xtensor.hpp>
    #include <xtensor/views/xview.hpp>
    #include <xtensor/io/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/containers/xarray.hpp>
    #include <xtensor/containers/xtensor.hpp>
    #include <xtensor/core/xstrides.hpp>
    #include <xtensor/io/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.