Expanded words about make-shared-array, trying to clarify what linear means, and adding lots of example usages.
The examples make it a bit on the long side, it's worth it though, since it's not easy to think of these usages if you don't already know. I'm thinking of splitting out a "shared arrays" section to collect up shared array bits, and perhaps enclose-array too (if anyone can explain what it actually does :-). The quotient/remainder example flattening two dims to one works I think, but I'm not sure it obeys a strict reading of what's described for a "linear" mapfunc. Maybe some description involving the actual strides used in the implementation would be better. -- Scheme Procedure: make-shared-array oldarray mapfunc bound ... -- C Function: scm_make_shared_array (oldarray, mapfunc, boundlist) Return a new array which shares the storage of OLDARRAY. Changes made through either affect the same underlying storage. The BOUND... arguments are the shape of the new array, the same as `make-array' above. MAPFUNC translates coordinates from the new array to the OLDARRAY. It's called as `(MAPFUNC newidx1 ...)' with one parameter for each dimension of the new array, and should return a list of indices for OLDARRAY, one for each dimension of OLDARRAY. MAPFUNC must be linear, meaning that each OLDARRAY index must be formed by adding integer multiples (possibly negative) of some or all of NEWIDX1 etc, plus a possible integer offset. The multiples and offset must be the same in each call. One good use for a shared array is to restrict the range of some dimensions, so as to apply say `array-for-each' or `array-fill!' to only part of an array. The plain `list' function can be used for MAPFUNC in this case, making no changes to the index values. For example, (make-shared-array #2((a b c) (d e f) (g h i)) list 3 2) => #2((a b) (d e) (g h)) The new array can have fewer dimensions than OLDARRAY, for example to take a column from an array. (make-shared-array #2((a b c) (d e f) (g h i)) (lambda (i) (list i 2)) '(0 2)) => #1(c f i) A diagonal can be taken by using the single new array index for both row and column in the old array. For example, (make-shared-array #2((a b c) (d e f) (g h i)) (lambda (i) (list i i)) '(0 2)) => #1(a e i) An array can be flattened from say two dimensions to one by having the MAPFUNC translate portions of the new array to rows in the old, (make-shared-array #2((a b c d) (e f g h) (i j k l)) (lambda (i) (list (quotient i 4) (remainder i 4))) 12) => #(a b c d e f g h i j k l) The opposite is possible too, taking say a one dimensional array and considering portions of it as rows, (make-shared-array #1(a b c d e f g h i j k l) (lambda (i j) (list (+ (* i 3) j))) 4 3) => #2((a b c) (d e f) (g h i) (j k l)) With a negation on an index, the order that elements appear can be reversed. This is the sort of thing `array-transpose' below does. The following just reverses the column order, (make-shared-array #2((a b c) (d e f) (g h i)) (lambda (i j) (list i (- 2 j))) 3 3) => #2((c b a) (f e d) (i h g)) A fixed offset on indexes allows for instance a change from a 0 based to a 1 based array, (define x #2((a b c) (d e f) (g h i))) (define y (make-shared-array x (lambda (i j) (list (1- i) (1- j))) '(1 3) '(1 3))) (array-ref x 0 0) => a (array-ref y 1 1) => a A multiple on an index allows every Nth element of an array to be taken. The following is every third element, (make-shared-array #1(a b c d e f g h i j k l) (lambda (i) (* i 3)) 4) => #1(a d g j) The above examples can be combined to make weird and wonderful selections from an array, but it's important to note that because MAPFUNC must be linear, arbitrary permutations are not possible. In the current implementation, MAPFUNC is not called for every access to the new array but only on some sample points to establish a base and stride for new array indices in OLDARRAY data. A few sample points are enough because MAPFUNC is linear. _______________________________________________ Guile-devel mailing list [EMAIL PROTECTED] http://lists.gnu.org/mailman/listinfo/guile-devel