18.2 Slicing with range indexes
Slicing returns a contiguous slice of a one-dimensional array, a contiguous sub-block of a two-dimensional array, and so on. Semantically, it is just a special form of multiple indexing.
Lower and upper bound indexes
For instance, consider supplying an upper and lower bound for an index.
array[7] int c;
// ...
array[4] int d;
d = c[3:6]; // result: d == (c[3], c[4], c[5], c[6])
The range index 3:6
behaves semantically just like the multiple
index (3, 4, 5, 6)
. In terms of implementation, the sliced
upper and/or lower bounded indices are faster and use less memory
because they do not explicitly create a multiple index, but rather use
a direct loop. They are also easier to read, so should be preferred
over multiple indexes where applicable.
Lower or upper bound indexes
It is also possible to supply just a lower bound, or just an upper
bound. Writing c[3:]
is just shorthand for
c[3:size(c)]
. Writing c[:5]
is just shorthand for
c[1:5]
.
Full range indexes
Finally, it is possible to write a range index that covers the entire
range of an array, either by including just the range symbol
(:
) as the index or leaving the index position empty. In both
cases, c[]
and c[:]
are equal to c[1:size(c)]
,
which in turn is just equal to c
.
Slicing functions
Stan provides head
and tail
functions that pull out prefixes or
suffixes of vectors, row vectors, and one-dimensional arrays. In each
case, the return type is the same as the argument type. For
example,
vector[M] a = ...;
vector[N] b = head(a, N);
assigns b
to be a vector equivalent to the first N
elements of the
vector a
. The function tail
works the same way for suffixes, with
array[M] a = ...;
array[N] b = tail(a, N);
Finally, there is a segment function, which specifies a first element and number of elements. For example,
array[15] a = ...;
array[3] b = segment(a, 5, 3);
will set b
to be equal to { a[5], a[6], a[7] }
, so that it starts
at element 5 of a
and includes a total of 3 elements.