The ranges introduce so far were template ranges. Adlib also has an idea of a subrange. A subrange is a subrange of some other range (and, ultimately, of some template range). It retains an alignment to its parent range. The location of a subrange element remains the same as the corresponding element of the parent range.
BlockRange x(N, p.dim(0)) ; Range u = x.subrng(N - 2, 1) ;The range
u
is a subrange of x
. It has extent N - 2 and
offset 1. Element 0 of u
is aligned with element 1 of x
,
element 1 with element 2, and so on. The last element of u
,
element N - 3, is aligned with the penultimate element, N - 2, of
x
.
As an immediate application, the overall construct in figure 2 could be replaced by
Index k(x.subrng(N - 2, 1)) ; Index l(y.subrng(N - 2, 1)) ; OVERALL(k) { OVERALL(l) { w(k, l) = 0.25 * (wnx(k, l) + wpx(k, l) + wny(k, l) + wpy(k, l)) ; } ALLOVER(l) ; } ALLOVER(k) ;This works because a local subscript constructed from a subrange is exactly equivalent to a subscript constructed from a parent range at an aligned point. The advantage of the new version is that we have eliminated an expensive test from the inner body of the loops.
If the original code had been something like
Index i(x), j(y) ; OVERALL(i) { OVERALL(j) { if(i != 0 && i != N - 1 && j != 0 && j != N - 1) w(i, j) = i + j ; } ALLOVER(j) ; } ALLOVER(i) ;with a dependence on global index value, we could still perform the above transformation by declaring
k
, l
as above, then
OVERALL(k) { OVERALL(l) { w(k, l) = x(k) + y(l) ; } ALLOVER(l) ; } ALLOVER(k) ;This exploits the operator
int Range :: operator()(Location&) ;which effectively allows a range to subscripted as if it were a one-dimensional array holding its global index values.
It is possible to specify a stride in a subrange, as in
Range t = x.subrng(10, 20, 2) ;Element 0 of range
t
is aligned with element 20 of range
x
, element 1 with element 22, etc.
Arrays can be declared with subranges. This mechanism allows affine alignment between arrays, as provided in HPF 1.0.