Slice assignment


Description

Slice assignment means assigning a value into an element or slice into an array contained by a local value:

a[I = x] := e

«a» must be a local value (i.e., declared by Local..Do, not a local alias), «I» is an index (local or global), and «x» and «e» are expressions that are evaluated. «x» may be an array of values of «I» (see array abstraction below).

You can write some algorithms much more easily and efficiently using slice assignment than was possible in previous releases lacking this feature.

For example, consider:

Function Fibonacci_series(f1, f2, n) :=
LocalIndex m := 1..n;
Local result := 0;
result[m = 1] := f1;
result[m = 2] := f2;
For i := 3..n DO result[m = i] := result[m = i -1] + result[m = i - 2];
result

In the first slice assignment in this function:

result[m = 1] := f1;

result was not previously indexed by m. So the assignment adds the index m to result, sets the value to f1 for m = 1 and leaves result with its original value, 0, for other values of m.

More generally, in a slice assignment:

a[i = x] := e

if a was already indexed by «i», it will set a[i = x] to the value of «e». For other values of «i», «a» will retain its previous value. If «a» was not already indexed by «i», the assignment adds «i» as a dimension of «a», and sets the slice a[i = x] to «e». All other slices of «a» over «i» will retain their previous values. If «a» was indexed by other indexes, say j, the result will be indexed by «i» and j. The assigned slice a[i = x] will have the value «e» for all values of the other index(es) j. Again, slices for other values of «i» will retain their original values of «a».

You may index by position as well as name in a slice assignment, for example:

a[@I = 2] := e

assigns the value of e as the second slice of a over index I.

Return Value

The return value of a slice assignment, a[I = x] := v, is the result of «v». Note that it is not the full array assigned to. The assignment is parsed in a right-associative fashion, which means you can cascade assignments such as

a[I=1] := a[I=3] := v

having the effect of assigning «v» to both a[I = 3] and to a[I = 1].

Additional capabilities

You can nest several levels of slices and subscripts, enabling easier assignment to individual cells in a multi-dimensional array. So, for example, assignments such as:

a[I = x, J = y] := v

are supported. You can have any number (up to Analytica maximum of 24 dimensions per array) of nestings, and can intermix subscripts and slices, e.g.,

a[@I = n, J =y] := v

The coordinates, x and y can also be array-valued. When the coordinates are array-valued, Analytica iterates over those dimensions, performing many assignments in one swoop. The details are described in the next subsection.

Slice Assignment and Array Abstraction

You can assign to many cells in one operation when the coordinate is an array. For example,

a[I = [2, 5, 7]] := 7

would set the indicated three cells to the value of 7. The iteration is coordinated, so that a[I = J ]:= J would set each cell named in J to the value of J. In the assignment a[I = x] := v, any index contained in «x» that does not already appear in «a» becomes an iteration index -- the assignment is repeated for each element of that index, but the index does not appear in the final array. When there are two or more such dimensions and the array contains repeated values, this can create an ambiguity. The following example demonstrates:

Variable x :=
J ▶
K ▼ 'j1' 'j2'
'k1' 2 1
'k2' 1 2
Variable v :=
J ▶
K ▼ 'j1' 'j2'
'k1' 11 12
'k2' 13 14

Then, after a[I = x] := v:

a →
I ▶
12 14

or,

a →
I ▶
13 14

The ambiguity arises because the result depends on which order Analytica iterates over J and K. In one case, the following set of assignments occur (in this order):

a[I=2] := 11 { at J='j1', K='k1' }
a[I=1] := 13 { at J='j1', K='k2' }
a[I=1] := 12 { at J='j2', K='k1' }
a[I=2] := 14 { at J='j2', K='k2' }

In the other case, the assignments occur in this order:

a[I=2] := 11 { at J='j1', K='k1' }
a[I=1] := 12 { at J='j2', K='k1' }
a[I=1] := 13 { at J='j1', K='k2' }
a[I=2] := 14 { at J='j2', K='k2' }

Although currently the a[I=2]:=11 assignment always occurs before the a[I=2]:=14 assignment, this is not something that is guaranteed, and future releases of Analytica may parallelize the operation, opening the possibility that the assignment of 14 happens before 11.

When «a» contains one of the indexes of «x», then iteration on that index is coordinated, so that the final result also contains that index, and the associated assignments apply only to the appropriate slice. In the above example, suppose b contains the K index before the assignment occurs. Now there is no ambiguity, After

b[I = x] := v
b →
I ▶
K ▼ 1 2
'k1' 12 11
'k2' 13 14

When using array abstraction to iterate, that the right-hand side, «v», is evaluated entirely before any assignment occurs. Thus if «a» occurs in the right-hand side, at each iteration it is the value in «a» that was there before the assignment operation started that is used, not the value present at the previous iteration.

Examples

A sieve algorithm to efficiently generate all the prime numbers up to MaxPrime:

Local isPrime :=1;
LocalIndex n := Sequence(3,MaxPrime,2);
For i:=n do (
	If isPrime[n=i] Then 
		isPrime[n=Sequence(3*i,MaxPrime,2*i,strict:true)] := 0;
);
Concat([2],Subset(isPrime))

Notice that the slice assignment line zeroes out all multiples of i in a single step. When the For-loop finishes, isPrime is an array of 0s and 1s, with 1s where n is prime. On my computer purchased in 2011 (i7-2600), this takes about 40 seconds when MaxPrimes is 10M.

See Also

Comments


You are not allowed to post comments.