Indexing ¶
Array API specification for indexing arrays.
A conforming implementation of the array API standard must adhere to the following conventions.
Singleaxis Indexing ¶
To index a single array axis, an array must support standard Python indexing rules. Let
n
be the axis (dimension) size.

An integer index must be an object satisfying
operator.index
(e.g.,int
). 
Nonnegative indices must start at
0
(i.e., zerobased indexing). 
Valid nonnegative indices must reside on the halfopen interval
[0, n)
.Note
This specification does not require bounds checking. The behavior for outofbounds integer indices is left unspecified.

Negative indices must count backward from the last array index, starting from
1
(i.e., negativeonebased indexing, where1
refers to the last array index).Note
A negative index
j
is equivalent tonj
; the former is syntactic sugar for the latter, providing a shorthand for indexing elements that would otherwise need to be specified in terms of the axis (dimension) size. 
Valid negative indices must reside on the closed interval
[n, 1]
.Note
This specification does not require bounds checking. The behavior for outofbounds integer indices is left unspecified.

A negative index
j
is related to a zerobased nonnegative indexi
viai = n+j
. 
Colons
:
must be used for slices :start:stop:step
, wherestart
is inclusive andstop
is exclusive.
Slice Syntax ¶
The basic slice syntax is
i:j:k
where
i
is the starting index,
j
is the stopping index, and
k
is the step (
k
!=
0
). A slice may contain either one or two colons, with either an integer value or nothing on either side of each colon. The following are valid slices.
A[:]
A[i:]
A[:j]
A[i:k]
A[::]
A[i::]
A[:j:]
A[::k]
A[i:j:]
A[i::k]
A[:j:k]
A[i::k]
A[i:j:k]
Note
Slice syntax can be equivalently achieved using the Python builtin
slice()
API. From the perspective of
A
, the behavior of
A[i:j:k]
and
A[slice(i,
j,
k)]
is indistinguishable (i.e., both retrieve the same set of items from
__getitem__
).
Using a slice to index a single array axis must select
m
elements with index values
i, i+k, i+2k, i+3k, ..., i+(m1)k
where
m = q + r
and
q
and
r
(
r
!=
0
) are the quotient and remainder obtained by dividing
ji
by
k
j  i = qk + r
such that
j > i + (m1)k
Note
For
i
on the interval
[0,
n)
(where
n
is the axis size),
j
on the interval
(0,
n]
,
i
less than
j
, and positive step
k
, a starting index
i
is
always
included, while the stopping index
j
is
always
excluded. This preserves
x[:i]+x[i:]
always being equal to
x
.
Note
Using a slice to index into a single array axis should select the same elements as using a slice to index a Python list of the same size.
Slice syntax must have the following defaults. Let
n
be the axis (dimension) size.

If
k
is not provided (e.g.,0:10
),k
must equal1
. 
If
k
is greater than0
andi
is not provided (e.g.,:10:2
),i
must equal0
. 
If
k
is greater than0
andj
is not provided (e.g.,0::2
),j
must equaln
. 
If
k
is less than0
andi
is not provided (e.g.,:10:2
),i
must equaln1
. 
If
k
is less than0
andj
is not provided (e.g.,0::2
),j
must equaln1
.
Using a slice to index a single array axis must adhere to the following rules. Let
n
be the axis (dimension) size.

If
i
equalsj
, a slice must return an empty array, whose axis (dimension) size along the indexed axis is0
. 
Indexing via
:
and::
must be equivalent and have defaults derived from the rules above. Both:
and::
indicate to select all elements along a single axis (dimension).
Note
This specification does not require “clipping” outofbounds slice indices. This is in contrast to Python slice semantics where
0:100
and
0:10
are equivalent on a list of length
10
.
The following ranges for the start and stop values of a slice must be supported. Let
n
be the axis (dimension) size being sliced. For a slice
i:j:k
, the behavior specified above should be implemented for the following:

i
orj
omitted (None
). 
n <= i <= n
. 
For
k > 0
ork
omitted (None
),n <= j <= n
. 
For
k < 0
,n  1 <= j <= max(0, n  1)
.
The behavior outside of these bounds is unspecified.
Note
Rationale: this is consistent with bounds checking for integer indexing; the behavior of outofbounds indices is left unspecified. Implementations may choose to clip (consistent with Python
list
slicing semantics), raise an exception, return junk values, or some other behavior depending on device requirements and performance considerations.
Multiaxis Indexing ¶
Multidimensional arrays must extend the concept of singleaxis indexing to multiple axes by applying singleaxis indexing rules along each axis (dimension) and supporting the following additional rules. Let
N
be the number of dimensions (“rank”) of a multidimensional array
A
.

Each axis may be independently indexed via singleaxis indexing by providing a commaseparated sequence (“selection tuple”) of singleaxis indexing expressions (e.g.,
A[:, 2:10, :, 5]
).Note
In Python,
x[(exp1, exp2, ..., expN)]
is equivalent tox[exp1, exp2, ..., expN]
; the latter is syntactic sugar for the former. 
Providing a single nonnegative integer
i
as a singleaxis index must index the same elements as the slicei:i+1
. 
Providing a single negative integer
i
as a singleaxis index must index the same elements as the slicen+i:n+i+1
, wheren
is the axis (dimension) size. 
Providing a single integer as a singleaxis index must reduce the number of array dimensions by
1
(i.e., the array rank should decrease by one; ifA
has rank2
,rank(A)1 == rank(A[0, :])
). In particular, a selection tuple with them
th element an integer (and all other entries:
) indexes a subarray with rankN1
. 
Providing a slice must retain array dimensions (i.e., the array rank must remain the same;
rank(A) == rank(A[:])
). 
Providing ellipsis must apply
:
to each dimension necessary to index all dimensions (e.g., ifA
has rank4
,A[1:, ..., 2:5] == A[1:, :, :, 2:5]
). Only a single ellipsis must be allowed. AnIndexError
exception must be raised if more than one ellipsis is provided. 
Except in the case of providing a single ellipsis (e.g.,
A[2:10, ...]
orA[1:, ..., 2:5]
), the number of provided singleaxis indexing expressions should equalN
. For example, ifA
has rank2
, a singleaxis indexing expression should be explicitly provided for both axes (e.g.,A[2:10, :]
). AnIndexError
exception should be raised if the number of provided singleaxis indexing expressions is less thanN
.Note
Some libraries, such as SymPy, support flat indexing (i.e., providing a singleaxis indexing expression to a higherdimensional array). That practice is not supported here.
To perform flat indexing, use
reshape(x, (1,))[integer]
. 
An
IndexError
exception must be raised if the number of provided singleaxis indexing expressions is greater thanN
.
Note
This specification leaves unspecified the behavior of providing a slice which attempts to select elements along a particular axis, but whose starting index is outofbounds.
Rationale: this is consistent with boundschecking for singleaxis indexing. An implementation may choose to set the axis (dimension) size of the result array to
0
, raise an exception, return junk values, or some other behavior depending on device requirements and performance considerations.
Boolean Array Indexing ¶
Datadependent output shape
For common boolean array use cases (e.g., using a dynamicallysized boolean array mask to filter the values of another array), the shape of the output array is datadependent; hence, array libraries which build computation graphs (e.g., JAX, Dask, etc.) may find boolean array indexing difficult to implement. Accordingly, such libraries may choose to omit boolean array indexing. See Datadependent output shapes section for more details.
An array must support indexing where the
sole index
is an
M
dimensional boolean array
B
with shape
S1
=
(s1,
...,
sM)
according to the following rules. Let
A
be an
N
dimensional array with shape
S2
=
(s1,
...,
sM,
...,
sN)
.

If
N >= M
, thenA[B]
must replace the firstM
dimensions ofA
with a single dimension having a size equal to the number ofTrue
elements inB
. The values in the resulting array must be in rowmajor (Cstyle order); this is equivalent toA[nonzero(B)]
.Note
For example, if
N == M == 2
, indexingA
via a boolean arrayB
will return a onedimensional array whose size is equal to the number ofTrue
elements inB
. 
If
N < M
, then anIndexError
exception must be raised. 
The size of each dimension in
B
must equal the size of the corresponding dimension inA
or be0
, beginning with the first dimension inA
. If a dimension size does not equal the size of the corresponding dimension inA
and is not0
, then anIndexError
exception must be raised. 
The elements of a boolean index array must be iterated in rowmajor, Cstyle order, with the exception of zerodimensional boolean arrays.

A zerodimensional boolean index array (equivalent to
True
orFalse
) must follow the same axis replacement rules stated above. Namely, a zerodimensional boolean index array removes zero dimensions and adds a single dimension of length1
if the index array’s value isTrue
and of length0
if the index array’s value isFalse
. Accordingly, for a zerodimensional boolean index arrayB
, the result ofA[B]
has shapeS = (1, s1, ..., sN)
if the index array’s value isTrue
and has shapeS = (0, s1, ..., sN)
if the index array’s value isFalse
.
Return Values ¶
The result of an indexing operation (e.g., multiaxis indexing, boolean array indexing, etc) must be an array of the same data type as the indexed array.
Note
The specified return value behavior includes indexing operations which return a single value (e.g., accessing a single element within a onedimensional array).