I’m trying to write the following Perl subroutine. Given are an array a of length n, an index i in the array (0<=i<n an upstream window length u and a downstream window length d.
I want to iterate over the values in the upstream window and the downstream window to i. In the simplest case, this will iterating over the values in a[i-u..i-1] (upstream window) and a[i+1..i+d] (downstream window).
For example: if my array is 1 2 3 4 5 6 7 8 9 10, i=5 and both window sizes are 2, the upstream values are simply 6 7 and the downstream values are 9 10.
However, there are two complications:
-
I would like to consider my array is cyclic. If
iis relatively small (close to
0) or large (close ton), then one
of the windows may not fit in the
array. In that case, I want to look
at the array as a cyclic one. for
example, if my array is1 2 3 4 5 6 7 8 9 10,i=8and both window sizes
are4, the upstream values are
simply4 5 6 7, but the downstream
values are9 10 1 2. -
I would prefer some way to iterate
over these values without explicitly
copying them into a new array, since
they might be very long.
You can just get a list of indices using the range operator (
..) by subtracting the upstream window from$iand adding the downstream window to$i. You will need to remember to skip the iterator when the iterator is equal to$iif you don’t want that$ith value.You will need to use the modulo operator (
%) to keep the index within the bounds of the array. Given an array of size11, we can see that by modifying the index with11it will always point to the right place in the array:You may run into problems with huge numbers (i.e., numbers larger than what your platform holds in an unsigned integer), because Perl 5 changes the algorithm the modulus uses around there. It becomes more like C’s
fmod(but there are some differences).You may also want to not use the
integerpragma. It makes%faster, but you get the behavior of the C modulo operator. Neither ANSI nor ISO define what C should do with negative numbers, so you may or may not get a valid index back. Of course, so long as the version of C spits back eitheror
it should be fine (if not very portable).
It looks like C99 defines the modulo operator to return the second case, so long as
perlgets compiled with a C99 compiler (with the C99 flag on) it should be safe to use theintegerpragma.