1381 lines
49 KiB
Scheme
1381 lines
49 KiB
Scheme
|
;;; array
|
|||
|
;;; 1997 - 2001 Jussi Piitulainen
|
|||
|
|
|||
|
|
|||
|
;; This file is the result of
|
|||
|
;; cat array.scm as-srfi-9-record.scm ix-ctor.scm op-ctor.scm > srfi-25.scm
|
|||
|
|
|||
|
|
|||
|
;;; --- Intro ---
|
|||
|
|
|||
|
;;; This interface to arrays is based on Alan Bawden's array.scm of
|
|||
|
;;; 1993 (earlier version in the Internet Repository and another
|
|||
|
;;; version in SLIB). This is a complete rewrite, to be consistent
|
|||
|
;;; with the rest of Scheme and to make arrays independent of lists.
|
|||
|
|
|||
|
;;; Some modifications are due to discussion in srfi-25 mailing list.
|
|||
|
|
|||
|
;;; (array? obj)
|
|||
|
;;; (make-array shape [obj]) changed arguments
|
|||
|
;;; (shape bound ...) new
|
|||
|
;;; (array shape obj ...) new
|
|||
|
;;; (array-rank array) changed name back
|
|||
|
;;; (array-start array dimension) new
|
|||
|
;;; (array-end array dimension) new
|
|||
|
;;; (array-ref array k ...)
|
|||
|
;;; (array-ref array index) new variant
|
|||
|
;;; (array-set! array k ... obj) changed argument order
|
|||
|
;;; (array-set! array index obj) new variant
|
|||
|
;;; (share-array array shape proc) changed arguments
|
|||
|
|
|||
|
;;; All other variables in this file have names in "array:".
|
|||
|
|
|||
|
;;; Should there be a way to make arrays with initial values mapped
|
|||
|
;;; from indices? Sure. The current "initial object" is lame.
|
|||
|
;;;
|
|||
|
;;; Removed (array-shape array) from here. There is a new version
|
|||
|
;;; in arlib though.
|
|||
|
|
|||
|
;;; --- Representation type dependencies ---
|
|||
|
|
|||
|
;;; The mapping from array indices to the index to the underlying vector
|
|||
|
;;; is whatever array:optimize returns. The file "opt" provides three
|
|||
|
;;; representations:
|
|||
|
;;;
|
|||
|
;;; mbda) mapping is a procedure that allows an optional argument
|
|||
|
;;; tter) mapping is two procedures that takes exactly the indices
|
|||
|
;;; ctor) mapping is a vector of a constant term and coefficients
|
|||
|
;;;
|
|||
|
;;; Choose one in "opt" to make the optimizer. Then choose the matching
|
|||
|
;;; implementation of array-ref and array-set!.
|
|||
|
;;;
|
|||
|
;;; These should be made macros to inline them. Or have a good compiler
|
|||
|
;;; and plant the package as a module.
|
|||
|
|
|||
|
;;; 1. Pick an optimizer.
|
|||
|
;;; 2. Pick matching index representation.
|
|||
|
;;; 3. Pick a record implementation; as-procedure is generic; syntax inlines.
|
|||
|
;;; 3. This file is otherwise portable.
|
|||
|
|
|||
|
;;; --- Portable R5RS (R4RS and multiple values) ---
|
|||
|
|
|||
|
;;; (array? obj)
|
|||
|
;;; returns #t if `obj' is an array and #t or #f otherwise.
|
|||
|
|
|||
|
(define (array? obj)
|
|||
|
(array:array? obj))
|
|||
|
|
|||
|
;;; (make-array shape)
|
|||
|
;;; (make-array shape obj)
|
|||
|
;;; makes array of `shape' with each cell containing `obj' initially.
|
|||
|
|
|||
|
(define (make-array shape . rest)
|
|||
|
(or (array:good-shape? shape)
|
|||
|
(error "make-array: shape is not a shape"))
|
|||
|
(apply array:make-array shape rest))
|
|||
|
|
|||
|
(define (array:make-array shape . rest)
|
|||
|
(let ((size (array:size shape)))
|
|||
|
(array:make
|
|||
|
(if (pair? rest)
|
|||
|
(apply (lambda (o) (make-vector size o)) rest)
|
|||
|
(make-vector size))
|
|||
|
(if (= size 0)
|
|||
|
(array:optimize-empty
|
|||
|
(vector-ref (array:shape shape) 1))
|
|||
|
(array:optimize
|
|||
|
(array:make-index shape)
|
|||
|
(vector-ref (array:shape shape) 1)))
|
|||
|
(array:shape->vector shape))))
|
|||
|
|
|||
|
;;; (shape bound ...)
|
|||
|
;;; makes a shape. Bounds must be an even number of exact, pairwise
|
|||
|
;;; non-decreasing integers. Note that any such array can be a shape.
|
|||
|
|
|||
|
(define (shape . bounds)
|
|||
|
(let ((v (list->vector bounds)))
|
|||
|
(or (even? (vector-length v))
|
|||
|
(error (string-append "shape: uneven number of bounds: "
|
|||
|
(array:list->string bounds))))
|
|||
|
(let ((shp (array:make
|
|||
|
v
|
|||
|
(if (pair? bounds)
|
|||
|
(array:shape-index)
|
|||
|
(array:empty-shape-index))
|
|||
|
(vector 0 (quotient (vector-length v) 2)
|
|||
|
0 2))))
|
|||
|
(or (array:good-shape? shp)
|
|||
|
(error (string-append "shape: bounds are not pairwise "
|
|||
|
"non-decreasing exact integers: "
|
|||
|
(array:list->string bounds))))
|
|||
|
shp)))
|
|||
|
|
|||
|
;;; (array shape obj ...)
|
|||
|
;;; is analogous to `vector'.
|
|||
|
|
|||
|
(define (array shape . elts)
|
|||
|
(or (array:good-shape? shape)
|
|||
|
(error (string-append "array: shape " (array:thing->string shape)
|
|||
|
" is not a shape")))
|
|||
|
(let ((size (array:size shape)))
|
|||
|
(let ((vector (list->vector elts)))
|
|||
|
(or (= (vector-length vector) size)
|
|||
|
(error (string-append "array: an array of shape "
|
|||
|
(array:shape-vector->string
|
|||
|
(array:vector shape))
|
|||
|
" has "
|
|||
|
(number->string size)
|
|||
|
" elements but got "
|
|||
|
(number->string (vector-length vector))
|
|||
|
" values: "
|
|||
|
(array:list->string elts))))
|
|||
|
(array:make
|
|||
|
vector
|
|||
|
(if (= size 0)
|
|||
|
(array:optimize-empty
|
|||
|
(vector-ref (array:shape shape) 1))
|
|||
|
(array:optimize
|
|||
|
(array:make-index shape)
|
|||
|
(vector-ref (array:shape shape) 1)))
|
|||
|
(array:shape->vector shape)))))
|
|||
|
|
|||
|
;;; (array-rank array)
|
|||
|
;;; returns the number of dimensions of `array'.
|
|||
|
|
|||
|
(define (array-rank array)
|
|||
|
(quotient (vector-length (array:shape array)) 2))
|
|||
|
|
|||
|
;;; (array-start array k)
|
|||
|
;;; returns the lower bound index of array along dimension k. This is
|
|||
|
;;; the least valid index along that dimension if the dimension is not
|
|||
|
;;; empty.
|
|||
|
|
|||
|
(define (array-start array d)
|
|||
|
(vector-ref (array:shape array) (+ d d)))
|
|||
|
|
|||
|
;;; (array-end array k)
|
|||
|
;;; returns the upper bound index of array along dimension k. This is
|
|||
|
;;; not a valid index. If the dimension is empty, this is the same as
|
|||
|
;;; the lower bound along it.
|
|||
|
|
|||
|
(define (array-end array d)
|
|||
|
(vector-ref (array:shape array) (+ d d 1)))
|
|||
|
|
|||
|
;;; (share-array array shape proc)
|
|||
|
;;; makes an array that shares elements of `array' at shape `shape'.
|
|||
|
;;; The arguments to `proc' are indices of the result. The values of
|
|||
|
;;; `proc' are indices of `array'.
|
|||
|
|
|||
|
;;; Todo: in the error message, should recognise the mapping and show it.
|
|||
|
|
|||
|
(define (share-array array subshape f)
|
|||
|
(or (array:good-shape? subshape)
|
|||
|
(error (string-append "share-array: shape "
|
|||
|
(array:thing->string subshape)
|
|||
|
" is not a shape")))
|
|||
|
(let ((subsize (array:size subshape)))
|
|||
|
(or (array:good-share? subshape subsize f (array:shape array))
|
|||
|
(error (string-append "share-array: subshape "
|
|||
|
(array:shape-vector->string
|
|||
|
(array:vector subshape))
|
|||
|
" does not map into supershape "
|
|||
|
(array:shape-vector->string
|
|||
|
(array:shape array))
|
|||
|
" under mapping "
|
|||
|
(array:map->string
|
|||
|
f
|
|||
|
(vector-ref (array:shape subshape) 1)))))
|
|||
|
(let ((g (array:index array)))
|
|||
|
(array:make
|
|||
|
(array:vector array)
|
|||
|
(if (= subsize 0)
|
|||
|
(array:optimize-empty
|
|||
|
(vector-ref (array:shape subshape) 1))
|
|||
|
(array:optimize
|
|||
|
(lambda ks
|
|||
|
(call-with-values
|
|||
|
(lambda () (apply f ks))
|
|||
|
(lambda ks (array:vector-index g ks))))
|
|||
|
(vector-ref (array:shape subshape) 1)))
|
|||
|
(array:shape->vector subshape)))))
|
|||
|
|
|||
|
;;; --- Hrmph ---
|
|||
|
|
|||
|
;;; (array:share/index! ...)
|
|||
|
;;; reuses a user supplied index object when recognising the
|
|||
|
;;; mapping. The mind balks at the very nasty side effect that
|
|||
|
;;; exposes the implementation. So this is not in the spec.
|
|||
|
;;; But letting index objects in at all creates a pressure
|
|||
|
;;; to go the whole hog. Arf.
|
|||
|
|
|||
|
;;; Use array:optimize-empty for an empty array to get a
|
|||
|
;;; clearly invalid vector index.
|
|||
|
|
|||
|
;;; Surely it's perverse to use an actor for index here? But
|
|||
|
;;; the possibility is provided for completeness.
|
|||
|
|
|||
|
(define (array:share/index! array subshape proc index)
|
|||
|
(array:make
|
|||
|
(array:vector array)
|
|||
|
(if (= (array:size subshape) 0)
|
|||
|
(array:optimize-empty
|
|||
|
(quotient (vector-length (array:shape array)) 2))
|
|||
|
((if (vector? index)
|
|||
|
array:optimize/vector
|
|||
|
array:optimize/actor)
|
|||
|
(lambda (subindex)
|
|||
|
(let ((superindex (proc subindex)))
|
|||
|
(if (vector? superindex)
|
|||
|
(array:index/vector
|
|||
|
(quotient (vector-length (array:shape array)) 2)
|
|||
|
(array:index array)
|
|||
|
superindex)
|
|||
|
(array:index/array
|
|||
|
(quotient (vector-length (array:shape array)) 2)
|
|||
|
(array:index array)
|
|||
|
(array:vector superindex)
|
|||
|
(array:index superindex)))))
|
|||
|
index))
|
|||
|
(array:shape->vector subshape)))
|
|||
|
|
|||
|
(define (array:optimize/vector f v)
|
|||
|
(let ((r (vector-length v)))
|
|||
|
(do ((k 0 (+ k 1)))
|
|||
|
((= k r))
|
|||
|
(vector-set! v k 0))
|
|||
|
(let ((n0 (f v))
|
|||
|
(cs (make-vector (+ r 1)))
|
|||
|
(apply (array:applier-to-vector (+ r 1))))
|
|||
|
(vector-set! cs 0 n0)
|
|||
|
(let wok ((k 0))
|
|||
|
(if (< k r)
|
|||
|
(let ((k1 (+ k 1)))
|
|||
|
(vector-set! v k 1)
|
|||
|
(let ((nk (- (f v) n0)))
|
|||
|
(vector-set! v k 0)
|
|||
|
(vector-set! cs k1 nk)
|
|||
|
(wok k1)))))
|
|||
|
(apply (array:maker r) cs))))
|
|||
|
|
|||
|
(define (array:optimize/actor f a)
|
|||
|
(let ((r (array-end a 0))
|
|||
|
(v (array:vector a))
|
|||
|
(i (array:index a)))
|
|||
|
(do ((k 0 (+ k 1)))
|
|||
|
((= k r))
|
|||
|
(vector-set! v (array:actor-index i k) 0))
|
|||
|
(let ((n0 (f a))
|
|||
|
(cs (make-vector (+ r 1)))
|
|||
|
(apply (array:applier-to-vector (+ r 1))))
|
|||
|
(vector-set! cs 0 n0)
|
|||
|
(let wok ((k 0))
|
|||
|
(if (< k r)
|
|||
|
(let ((k1 (+ k 1))
|
|||
|
(t (array:actor-index i k)))
|
|||
|
(vector-set! v t 1)
|
|||
|
(let ((nk (- (f a) n0)))
|
|||
|
(vector-set! v t 0)
|
|||
|
(vector-set! cs k1 nk)
|
|||
|
(wok k1)))))
|
|||
|
(apply (array:maker r) cs))))
|
|||
|
|
|||
|
;;; --- Internals ---
|
|||
|
|
|||
|
(define (array:shape->vector shape)
|
|||
|
(let ((idx (array:index shape))
|
|||
|
(shv (array:vector shape))
|
|||
|
(rnk (vector-ref (array:shape shape) 1)))
|
|||
|
(let ((vec (make-vector (* rnk 2))))
|
|||
|
(do ((k 0 (+ k 1)))
|
|||
|
((= k rnk)
|
|||
|
vec)
|
|||
|
(vector-set! vec (+ k k)
|
|||
|
(vector-ref shv (array:shape-vector-index idx k 0)))
|
|||
|
(vector-set! vec (+ k k 1)
|
|||
|
(vector-ref shv (array:shape-vector-index idx k 1)))))))
|
|||
|
|
|||
|
;;; (array:size shape)
|
|||
|
;;; returns the number of elements in arrays of shape `shape'.
|
|||
|
|
|||
|
(define (array:size shape)
|
|||
|
(let ((idx (array:index shape))
|
|||
|
(shv (array:vector shape))
|
|||
|
(rnk (vector-ref (array:shape shape) 1)))
|
|||
|
(do ((k 0 (+ k 1))
|
|||
|
(s 1 (* s
|
|||
|
(- (vector-ref shv (array:shape-vector-index idx k 1))
|
|||
|
(vector-ref shv (array:shape-vector-index idx k 0))))))
|
|||
|
((= k rnk) s))))
|
|||
|
|
|||
|
;;; (array:make-index shape)
|
|||
|
;;; returns an index function for arrays of shape `shape'. This is a
|
|||
|
;;; runtime composition of several variable arity procedures, to be
|
|||
|
;;; passed to array:optimize for recognition as an affine function of
|
|||
|
;;; as many variables as there are dimensions in arrays of this shape.
|
|||
|
|
|||
|
(define (array:make-index shape)
|
|||
|
(let ((idx (array:index shape))
|
|||
|
(shv (array:vector shape))
|
|||
|
(rnk (vector-ref (array:shape shape) 1)))
|
|||
|
(do ((f (lambda () 0)
|
|||
|
(lambda (k . ks)
|
|||
|
(+ (* s (- k (vector-ref
|
|||
|
shv
|
|||
|
(array:shape-vector-index idx (- j 1) 0))))
|
|||
|
(apply f ks))))
|
|||
|
(s 1 (* s (- (vector-ref
|
|||
|
shv
|
|||
|
(array:shape-vector-index idx (- j 1) 1))
|
|||
|
(vector-ref
|
|||
|
shv
|
|||
|
(array:shape-vector-index idx (- j 1) 0)))))
|
|||
|
(j rnk (- j 1)))
|
|||
|
((= j 0)
|
|||
|
f))))
|
|||
|
|
|||
|
|
|||
|
;;; --- Error checking ---
|
|||
|
|
|||
|
;;; (array:good-shape? shape)
|
|||
|
;;; returns true if `shape' is an array of the right shape and its
|
|||
|
;;; elements are exact integers that pairwise bound intervals `[lo..hi)<29>.
|
|||
|
|
|||
|
(define (array:good-shape? shape)
|
|||
|
(and (array:array? shape)
|
|||
|
(let ((u (array:shape shape))
|
|||
|
(v (array:vector shape))
|
|||
|
(x (array:index shape)))
|
|||
|
(and (= (vector-length u) 4)
|
|||
|
(= (vector-ref u 0) 0)
|
|||
|
(= (vector-ref u 2) 0)
|
|||
|
(= (vector-ref u 3) 2))
|
|||
|
(let ((p (vector-ref u 1)))
|
|||
|
(do ((k 0 (+ k 1))
|
|||
|
(true #t (let ((lo (vector-ref
|
|||
|
v
|
|||
|
(array:shape-vector-index x k 0)))
|
|||
|
(hi (vector-ref
|
|||
|
v
|
|||
|
(array:shape-vector-index x k 1))))
|
|||
|
(and true
|
|||
|
(integer? lo)
|
|||
|
(exact? lo)
|
|||
|
(integer? hi)
|
|||
|
(exact? hi)
|
|||
|
(<= lo hi)))))
|
|||
|
((= k p) true))))))
|
|||
|
|
|||
|
;;; (array:good-share? subv subsize mapping superv)
|
|||
|
;;; returns true if the extreme indices in the subshape vector map
|
|||
|
;;; into the bounds in the supershape vector.
|
|||
|
|
|||
|
;;; If some interval in `subv' is empty, then `subv' is empty and its
|
|||
|
;;; image under `f' is empty and it is trivially alright. One must
|
|||
|
;;; not call `f', though.
|
|||
|
|
|||
|
(define (array:good-share? subshape subsize f super)
|
|||
|
(or (zero? subsize)
|
|||
|
(letrec
|
|||
|
((sub (array:vector subshape))
|
|||
|
(dex (array:index subshape))
|
|||
|
(ck (lambda (k ks)
|
|||
|
(if (zero? k)
|
|||
|
(call-with-values
|
|||
|
(lambda () (apply f ks))
|
|||
|
(lambda qs (array:good-indices? qs super)))
|
|||
|
(and (ck (- k 1)
|
|||
|
(cons (vector-ref
|
|||
|
sub
|
|||
|
(array:shape-vector-index
|
|||
|
dex
|
|||
|
(- k 1)
|
|||
|
0))
|
|||
|
ks))
|
|||
|
(ck (- k 1)
|
|||
|
(cons (- (vector-ref
|
|||
|
sub
|
|||
|
(array:shape-vector-index
|
|||
|
dex
|
|||
|
(- k 1)
|
|||
|
1))
|
|||
|
1)
|
|||
|
ks)))))))
|
|||
|
(let ((rnk (vector-ref (array:shape subshape) 1)))
|
|||
|
(or (array:unchecked-share-depth? rnk)
|
|||
|
(ck rnk '()))))))
|
|||
|
|
|||
|
;;; Check good-share on 10 dimensions at most. The trouble is,
|
|||
|
;;; the cost of this check is exponential in the number of dimensions.
|
|||
|
|
|||
|
(define (array:unchecked-share-depth? rank)
|
|||
|
(if (> rank 10)
|
|||
|
(begin
|
|||
|
(display `(warning: unchecked depth in share:
|
|||
|
,rank subdimensions))
|
|||
|
(newline)
|
|||
|
#t)
|
|||
|
#f))
|
|||
|
|
|||
|
;;; (array:check-indices caller indices shape-vector)
|
|||
|
;;; (array:check-indices.o caller indices shape-vector)
|
|||
|
;;; (array:check-index-vector caller index-vector shape-vector)
|
|||
|
;;; return if the index is in bounds, else signal error.
|
|||
|
;;;
|
|||
|
;;; Shape-vector is the internal representation, with
|
|||
|
;;; b and e for dimension k at 2k and 2k + 1.
|
|||
|
|
|||
|
(define (array:check-indices who ks shv)
|
|||
|
(or (array:good-indices? ks shv)
|
|||
|
(error (array:not-in who ks shv))))
|
|||
|
|
|||
|
(define (array:check-indices.o who ks shv)
|
|||
|
(or (array:good-indices.o? ks shv)
|
|||
|
(error (array:not-in who (reverse (cdr (reverse ks))) shv))))
|
|||
|
|
|||
|
(define (array:check-index-vector who ks shv)
|
|||
|
(or (array:good-index-vector? ks shv)
|
|||
|
(error (array:not-in who (vector->list ks) shv))))
|
|||
|
|
|||
|
(define (array:check-index-actor who ks shv)
|
|||
|
(let ((shape (array:shape ks)))
|
|||
|
(or (and (= (vector-length shape) 2)
|
|||
|
(= (vector-ref shape 0) 0))
|
|||
|
(error "not an actor"))
|
|||
|
(or (array:good-index-actor?
|
|||
|
(vector-ref shape 1)
|
|||
|
(array:vector ks)
|
|||
|
(array:index ks)
|
|||
|
shv)
|
|||
|
(array:not-in who (do ((k (vector-ref shape 1) (- k 1))
|
|||
|
(m '() (cons (vector-ref
|
|||
|
(array:vector ks)
|
|||
|
(array:actor-index
|
|||
|
(array:index ks)
|
|||
|
(- k 1)))
|
|||
|
m)))
|
|||
|
((= k 0) m))
|
|||
|
shv))))
|
|||
|
|
|||
|
(define (array:good-indices? ks shv)
|
|||
|
(let ((d2 (vector-length shv)))
|
|||
|
(do ((kp ks (if (pair? kp)
|
|||
|
(cdr kp)))
|
|||
|
(k 0 (+ k 2))
|
|||
|
(true #t (and true (pair? kp)
|
|||
|
(array:good-index? (car kp) shv k))))
|
|||
|
((= k d2)
|
|||
|
(and true (null? kp))))))
|
|||
|
|
|||
|
(define (array:good-indices.o? ks.o shv)
|
|||
|
(let ((d2 (vector-length shv)))
|
|||
|
(do ((kp ks.o (if (pair? kp)
|
|||
|
(cdr kp)))
|
|||
|
(k 0 (+ k 2))
|
|||
|
(true #t (and true (pair? kp)
|
|||
|
(array:good-index? (car kp) shv k))))
|
|||
|
((= k d2)
|
|||
|
(and true (pair? kp) (null? (cdr kp)))))))
|
|||
|
|
|||
|
(define (array:good-index-vector? ks shv)
|
|||
|
(let ((r2 (vector-length shv)))
|
|||
|
(and (= (* 2 (vector-length ks)) r2)
|
|||
|
(do ((j 0 (+ j 1))
|
|||
|
(k 0 (+ k 2))
|
|||
|
(true #t (and true
|
|||
|
(array:good-index? (vector-ref ks j) shv k))))
|
|||
|
((= k r2) true)))))
|
|||
|
|
|||
|
(define (array:good-index-actor? r v i shv)
|
|||
|
(and (= (* 2 r) (vector-length shv))
|
|||
|
(do ((j 0 (+ j 1))
|
|||
|
(k 0 (+ k 2))
|
|||
|
(true #t (and true
|
|||
|
(array:good-index? (vector-ref
|
|||
|
v
|
|||
|
(array:actor-index i j))
|
|||
|
shv
|
|||
|
k))))
|
|||
|
((= j r) true))))
|
|||
|
|
|||
|
;;; (array:good-index? index shape-vector 2d)
|
|||
|
;;; returns true if index is within bounds for dimension 2d/2.
|
|||
|
|
|||
|
(define (array:good-index? w shv k)
|
|||
|
(and (integer? w)
|
|||
|
(exact? w)
|
|||
|
(<= (vector-ref shv k) w)
|
|||
|
(< w (vector-ref shv (+ k 1)))))
|
|||
|
|
|||
|
(define (array:not-in who ks shv)
|
|||
|
(let ((index (array:list->string ks))
|
|||
|
(bounds (array:shape-vector->string shv)))
|
|||
|
(error (string-append who
|
|||
|
": index " index
|
|||
|
" not in bounds " bounds))))
|
|||
|
|
|||
|
(define (array:list->string ks)
|
|||
|
(do ((index "" (string-append index (array:thing->string (car ks)) " "))
|
|||
|
(ks ks (cdr ks)))
|
|||
|
((null? ks) index)))
|
|||
|
|
|||
|
(define (array:shape-vector->string shv)
|
|||
|
(do ((bounds "" (string-append bounds
|
|||
|
"["
|
|||
|
(number->string (vector-ref shv t))
|
|||
|
".."
|
|||
|
(number->string (vector-ref shv (+ t 1)))
|
|||
|
")"
|
|||
|
" "))
|
|||
|
(t 0 (+ t 2)))
|
|||
|
((= t (vector-length shv)) bounds)))
|
|||
|
|
|||
|
(define (array:thing->string thing)
|
|||
|
(cond
|
|||
|
((number? thing) (number->string thing))
|
|||
|
((symbol? thing) (string-append "#<symbol>" (symbol->string thing)))
|
|||
|
((char? thing) "#<char>")
|
|||
|
((string? thing) "#<string>")
|
|||
|
((list? thing) (string-append "#" (number->string (length thing))
|
|||
|
"<list>"))
|
|||
|
|
|||
|
((pair? thing) "#<pair>")
|
|||
|
((array? thing) "#<array>")
|
|||
|
((vector? thing) (string-append "#" (number->string
|
|||
|
(vector-length thing))
|
|||
|
"<vector>"))
|
|||
|
((procedure? thing) "#<procedure>")
|
|||
|
(else
|
|||
|
(case thing
|
|||
|
((()) "()")
|
|||
|
((#t) "#t")
|
|||
|
((#f) "#f")
|
|||
|
(else
|
|||
|
"#<whatsit>")))))
|
|||
|
|
|||
|
;;; And to grok an affine map, vector->vector type. Column k of arr
|
|||
|
;;; will contain coefficients n0 ... nm of 1 k1 ... km for kth value.
|
|||
|
;;;
|
|||
|
;;; These are for the error message when share fails.
|
|||
|
|
|||
|
(define (array:index-ref ind k)
|
|||
|
(if (vector? ind)
|
|||
|
(vector-ref ind k)
|
|||
|
(vector-ref
|
|||
|
(array:vector ind)
|
|||
|
(array:actor-index (array:index ind) k))))
|
|||
|
|
|||
|
(define (array:index-set! ind k o)
|
|||
|
(if (vector? ind)
|
|||
|
(vector-set! ind k o)
|
|||
|
(vector-set!
|
|||
|
(array:vector ind)
|
|||
|
(array:actor-index (array:index ind) k)
|
|||
|
o)))
|
|||
|
|
|||
|
(define (array:index-length ind)
|
|||
|
(if (vector? ind)
|
|||
|
(vector-length ind)
|
|||
|
(vector-ref (array:shape ind) 1)))
|
|||
|
|
|||
|
(define (array:map->string proc r)
|
|||
|
(let* ((m (array:grok/arguments proc r))
|
|||
|
(s (vector-ref (array:shape m) 3)))
|
|||
|
(do ((i "" (string-append i c "k" (number->string k)))
|
|||
|
(c "" ", ")
|
|||
|
(k 1 (+ k 1)))
|
|||
|
((< r k)
|
|||
|
(do ((o "" (string-append o c (array:map-column->string m r k)))
|
|||
|
(c "" ", ")
|
|||
|
(k 0 (+ k 1)))
|
|||
|
((= k s)
|
|||
|
(string-append i " => " o)))))))
|
|||
|
|
|||
|
(define (array:map-column->string m r k)
|
|||
|
(let ((v (array:vector m))
|
|||
|
(i (array:index m)))
|
|||
|
(let ((n0 (vector-ref v (array:vector-index i (list 0 k)))))
|
|||
|
(let wok ((j 1)
|
|||
|
(e (if (= n0 0) "" (number->string n0))))
|
|||
|
(if (<= j r)
|
|||
|
(let ((nj (vector-ref v (array:vector-index i (list j k)))))
|
|||
|
(if (= nj 0)
|
|||
|
(wok (+ j 1) e)
|
|||
|
(let* ((nj (if (= nj 1) ""
|
|||
|
(if (= nj -1) "-"
|
|||
|
(string-append (number->string nj)
|
|||
|
" "))))
|
|||
|
(njkj (string-append nj "k" (number->string j))))
|
|||
|
(if (string=? e "")
|
|||
|
(wok (+ j 1) njkj)
|
|||
|
(wok (+ j 1) (string-append e " + " njkj))))))
|
|||
|
(if (string=? e "") "0" e))))))
|
|||
|
|
|||
|
(define (array:grok/arguments proc r)
|
|||
|
(array:grok/index!
|
|||
|
(lambda (vec)
|
|||
|
(call-with-values
|
|||
|
(lambda ()
|
|||
|
(array:apply-to-vector r proc vec))
|
|||
|
vector))
|
|||
|
(make-vector r)))
|
|||
|
|
|||
|
(define (array:grok/index! proc in)
|
|||
|
(let ((m (array:index-length in)))
|
|||
|
(do ((k 0 (+ k 1)))
|
|||
|
((= k m))
|
|||
|
(array:index-set! in k 0))
|
|||
|
(let* ((n0 (proc in))
|
|||
|
(n (array:index-length n0)))
|
|||
|
(let ((arr (make-array (shape 0 (+ m 1) 0 n)))) ; (*)
|
|||
|
(do ((k 0 (+ k 1)))
|
|||
|
((= k n))
|
|||
|
(array-set! arr 0 k (array:index-ref n0 k))) ; (**)
|
|||
|
(do ((j 0 (+ j 1)))
|
|||
|
((= j m))
|
|||
|
(array:index-set! in j 1)
|
|||
|
(let ((nj (proc in)))
|
|||
|
(array:index-set! in j 0)
|
|||
|
(do ((k 0 (+ k 1)))
|
|||
|
((= k n))
|
|||
|
(array-set! arr (+ j 1) k (- (array:index-ref nj k) ; (**)
|
|||
|
(array:index-ref n0 k))))))
|
|||
|
arr))))
|
|||
|
;; (*) Should not use `make-array' and `shape' here
|
|||
|
;; (**) Should not use `array-set!' here
|
|||
|
;; Should use something internal to the library instead: either lower
|
|||
|
;; level code (preferable but complex) or alternative names to these same.
|
|||
|
;;; array as-srfi-9-record
|
|||
|
;;; 2001 Jussi Piitulainen
|
|||
|
|
|||
|
;;; Untested.
|
|||
|
|
|||
|
(define-record-type
|
|||
|
array:srfi-9-record-type-descriptor
|
|||
|
(array:make vec ind shp)
|
|||
|
array:array?
|
|||
|
(vec array:vector)
|
|||
|
(ind array:index)
|
|||
|
(shp array:shape))
|
|||
|
(define (array-ref a . xs)
|
|||
|
(or (array:array? a)
|
|||
|
(error "not an array"))
|
|||
|
(let ((shape (array:shape a)))
|
|||
|
(if (null? xs)
|
|||
|
(array:check-indices "array-ref" xs shape)
|
|||
|
(let ((x (car xs)))
|
|||
|
(if (vector? x)
|
|||
|
(array:check-index-vector "array-ref" x shape)
|
|||
|
(if (integer? x)
|
|||
|
(array:check-indices "array-ref" xs shape)
|
|||
|
(if (array:array? x)
|
|||
|
(array:check-index-actor "array-ref" x shape)
|
|||
|
(error "not an index object"))))))
|
|||
|
(vector-ref
|
|||
|
(array:vector a)
|
|||
|
(if (null? xs)
|
|||
|
(vector-ref (array:index a) 0)
|
|||
|
(let ((x (car xs)))
|
|||
|
(if (vector? x)
|
|||
|
(array:index/vector
|
|||
|
(quotient (vector-length shape) 2)
|
|||
|
(array:index a)
|
|||
|
x)
|
|||
|
(if (integer? x)
|
|||
|
(array:vector-index (array:index a) xs)
|
|||
|
(if (array:array? x)
|
|||
|
(array:index/array
|
|||
|
(quotient (vector-length shape) 2)
|
|||
|
(array:index a)
|
|||
|
(array:vector x)
|
|||
|
(array:index x))
|
|||
|
(error "array-ref: bad index object")))))))))
|
|||
|
|
|||
|
(define (array-set! a x . xs)
|
|||
|
(or (array:array? a)
|
|||
|
(error "array-set!: not an array"))
|
|||
|
(let ((shape (array:shape a)))
|
|||
|
(if (null? xs)
|
|||
|
(array:check-indices "array-set!" '() shape)
|
|||
|
(if (vector? x)
|
|||
|
(array:check-index-vector "array-set!" x shape)
|
|||
|
(if (integer? x)
|
|||
|
(array:check-indices.o "array-set!" (cons x xs) shape)
|
|||
|
(if (array:array? x)
|
|||
|
(array:check-index-actor "array-set!" x shape)
|
|||
|
(error "not an index object")))))
|
|||
|
(if (null? xs)
|
|||
|
(vector-set! (array:vector a) (vector-ref (array:index a) 0) x)
|
|||
|
(if (vector? x)
|
|||
|
(vector-set! (array:vector a)
|
|||
|
(array:index/vector
|
|||
|
(quotient (vector-length shape) 2)
|
|||
|
(array:index a)
|
|||
|
x)
|
|||
|
(car xs))
|
|||
|
(if (integer? x)
|
|||
|
(let ((v (array:vector a))
|
|||
|
(i (array:index a))
|
|||
|
(r (quotient (vector-length shape) 2)))
|
|||
|
(do ((sum (* (vector-ref i 0) x)
|
|||
|
(+ sum (* (vector-ref i k) (car ks))))
|
|||
|
(ks xs (cdr ks))
|
|||
|
(k 1 (+ k 1)))
|
|||
|
((= k r)
|
|||
|
(vector-set! v (+ sum (vector-ref i k)) (car ks)))))
|
|||
|
(if (array:array? x)
|
|||
|
(vector-set! (array:vector a)
|
|||
|
(array:index/array
|
|||
|
(quotient (vector-length shape) 2)
|
|||
|
(array:index a)
|
|||
|
(array:vector x)
|
|||
|
(array:index x))
|
|||
|
(car xs))
|
|||
|
(error (string-append
|
|||
|
"array-set!: bad index object: "
|
|||
|
(array:thing->string x)))))))))
|
|||
|
(begin
|
|||
|
(define array:opt-args '(ctor (4)))
|
|||
|
(define (array:optimize f r)
|
|||
|
(case r
|
|||
|
((0) (let ((n0 (f))) (array:0 n0)))
|
|||
|
((1) (let ((n0 (f 0))) (array:1 n0 (- (f 1) n0))))
|
|||
|
((2)
|
|||
|
(let ((n0 (f 0 0)))
|
|||
|
(array:2 n0 (- (f 1 0) n0) (- (f 0 1) n0))))
|
|||
|
((3)
|
|||
|
(let ((n0 (f 0 0 0)))
|
|||
|
(array:3
|
|||
|
n0
|
|||
|
(- (f 1 0 0) n0)
|
|||
|
(- (f 0 1 0) n0)
|
|||
|
(- (f 0 0 1) n0))))
|
|||
|
(else
|
|||
|
(let ((v
|
|||
|
(do ((k 0 (+ k 1)) (v '() (cons 0 v)))
|
|||
|
((= k r) v))))
|
|||
|
(let ((n0 (apply f v)))
|
|||
|
(apply
|
|||
|
array:n
|
|||
|
n0
|
|||
|
(array:coefficients f n0 v v)))))))
|
|||
|
(define (array:optimize-empty r)
|
|||
|
(let ((x (make-vector (+ r 1) 0)))
|
|||
|
(vector-set! x r -1)
|
|||
|
x))
|
|||
|
(define (array:coefficients f n0 vs vp)
|
|||
|
(case vp
|
|||
|
((()) '())
|
|||
|
(else
|
|||
|
(set-car! vp 1)
|
|||
|
(let ((n (- (apply f vs) n0)))
|
|||
|
(set-car! vp 0)
|
|||
|
(cons n (array:coefficients f n0 vs (cdr vp)))))))
|
|||
|
(define (array:vector-index x ks)
|
|||
|
(do ((sum 0 (+ sum (* (vector-ref x k) (car ks))))
|
|||
|
(ks ks (cdr ks))
|
|||
|
(k 0 (+ k 1)))
|
|||
|
((null? ks) (+ sum (vector-ref x k)))))
|
|||
|
(define (array:shape-index) '#(2 1 0))
|
|||
|
(define (array:empty-shape-index) '#(0 0 -1))
|
|||
|
(define (array:shape-vector-index x r k)
|
|||
|
(+
|
|||
|
(* (vector-ref x 0) r)
|
|||
|
(* (vector-ref x 1) k)
|
|||
|
(vector-ref x 2)))
|
|||
|
(define (array:actor-index x k)
|
|||
|
(+ (* (vector-ref x 0) k) (vector-ref x 1)))
|
|||
|
(define (array:0 n0) (vector n0))
|
|||
|
(define (array:1 n0 n1) (vector n1 n0))
|
|||
|
(define (array:2 n0 n1 n2) (vector n1 n2 n0))
|
|||
|
(define (array:3 n0 n1 n2 n3) (vector n1 n2 n3 n0))
|
|||
|
(define (array:n n0 n1 n2 n3 n4 . ns)
|
|||
|
(apply vector n1 n2 n3 n4 (append ns (list n0))))
|
|||
|
(define (array:maker r)
|
|||
|
(case r
|
|||
|
((0) array:0)
|
|||
|
((1) array:1)
|
|||
|
((2) array:2)
|
|||
|
((3) array:3)
|
|||
|
(else array:n)))
|
|||
|
(define array:indexer/vector
|
|||
|
(let ((em
|
|||
|
(vector
|
|||
|
(lambda (x i) (+ (vector-ref x 0)))
|
|||
|
(lambda (x i)
|
|||
|
(+
|
|||
|
(* (vector-ref x 0) (vector-ref i 0))
|
|||
|
(vector-ref x 1)))
|
|||
|
(lambda (x i)
|
|||
|
(+
|
|||
|
(* (vector-ref x 0) (vector-ref i 0))
|
|||
|
(* (vector-ref x 1) (vector-ref i 1))
|
|||
|
(vector-ref x 2)))
|
|||
|
(lambda (x i)
|
|||
|
(+
|
|||
|
(* (vector-ref x 0) (vector-ref i 0))
|
|||
|
(* (vector-ref x 1) (vector-ref i 1))
|
|||
|
(* (vector-ref x 2) (vector-ref i 2))
|
|||
|
(vector-ref x 3)))
|
|||
|
(lambda (x i)
|
|||
|
(+
|
|||
|
(* (vector-ref x 0) (vector-ref i 0))
|
|||
|
(* (vector-ref x 1) (vector-ref i 1))
|
|||
|
(* (vector-ref x 2) (vector-ref i 2))
|
|||
|
(* (vector-ref x 3) (vector-ref i 3))
|
|||
|
(vector-ref x 4)))
|
|||
|
(lambda (x i)
|
|||
|
(+
|
|||
|
(* (vector-ref x 0) (vector-ref i 0))
|
|||
|
(* (vector-ref x 1) (vector-ref i 1))
|
|||
|
(* (vector-ref x 2) (vector-ref i 2))
|
|||
|
(* (vector-ref x 3) (vector-ref i 3))
|
|||
|
(* (vector-ref x 4) (vector-ref i 4))
|
|||
|
(vector-ref x 5)))
|
|||
|
(lambda (x i)
|
|||
|
(+
|
|||
|
(* (vector-ref x 0) (vector-ref i 0))
|
|||
|
(* (vector-ref x 1) (vector-ref i 1))
|
|||
|
(* (vector-ref x 2) (vector-ref i 2))
|
|||
|
(* (vector-ref x 3) (vector-ref i 3))
|
|||
|
(* (vector-ref x 4) (vector-ref i 4))
|
|||
|
(* (vector-ref x 5) (vector-ref i 5))
|
|||
|
(vector-ref x 6)))
|
|||
|
(lambda (x i)
|
|||
|
(+
|
|||
|
(* (vector-ref x 0) (vector-ref i 0))
|
|||
|
(* (vector-ref x 1) (vector-ref i 1))
|
|||
|
(* (vector-ref x 2) (vector-ref i 2))
|
|||
|
(* (vector-ref x 3) (vector-ref i 3))
|
|||
|
(* (vector-ref x 4) (vector-ref i 4))
|
|||
|
(* (vector-ref x 5) (vector-ref i 5))
|
|||
|
(* (vector-ref x 6) (vector-ref i 6))
|
|||
|
(vector-ref x 7)))
|
|||
|
(lambda (x i)
|
|||
|
(+
|
|||
|
(* (vector-ref x 0) (vector-ref i 0))
|
|||
|
(* (vector-ref x 1) (vector-ref i 1))
|
|||
|
(* (vector-ref x 2) (vector-ref i 2))
|
|||
|
(* (vector-ref x 3) (vector-ref i 3))
|
|||
|
(* (vector-ref x 4) (vector-ref i 4))
|
|||
|
(* (vector-ref x 5) (vector-ref i 5))
|
|||
|
(* (vector-ref x 6) (vector-ref i 6))
|
|||
|
(* (vector-ref x 7) (vector-ref i 7))
|
|||
|
(vector-ref x 8)))
|
|||
|
(lambda (x i)
|
|||
|
(+
|
|||
|
(* (vector-ref x 0) (vector-ref i 0))
|
|||
|
(* (vector-ref x 1) (vector-ref i 1))
|
|||
|
(* (vector-ref x 2) (vector-ref i 2))
|
|||
|
(* (vector-ref x 3) (vector-ref i 3))
|
|||
|
(* (vector-ref x 4) (vector-ref i 4))
|
|||
|
(* (vector-ref x 5) (vector-ref i 5))
|
|||
|
(* (vector-ref x 6) (vector-ref i 6))
|
|||
|
(* (vector-ref x 7) (vector-ref i 7))
|
|||
|
(* (vector-ref x 8) (vector-ref i 8))
|
|||
|
(vector-ref x 9)))))
|
|||
|
(it
|
|||
|
(lambda (w)
|
|||
|
(lambda (x i)
|
|||
|
(+
|
|||
|
(* (vector-ref x 0) (vector-ref i 0))
|
|||
|
(* (vector-ref x 1) (vector-ref i 1))
|
|||
|
(* (vector-ref x 2) (vector-ref i 2))
|
|||
|
(* (vector-ref x 3) (vector-ref i 3))
|
|||
|
(* (vector-ref x 4) (vector-ref i 4))
|
|||
|
(* (vector-ref x 5) (vector-ref i 5))
|
|||
|
(* (vector-ref x 6) (vector-ref i 6))
|
|||
|
(* (vector-ref x 7) (vector-ref i 7))
|
|||
|
(* (vector-ref x 8) (vector-ref i 8))
|
|||
|
(* (vector-ref x 9) (vector-ref i 9))
|
|||
|
(do ((xi
|
|||
|
0
|
|||
|
(+
|
|||
|
(* (vector-ref x u) (vector-ref i u))
|
|||
|
xi))
|
|||
|
(u (- w 1) (- u 1)))
|
|||
|
((< u 10) xi))
|
|||
|
(vector-ref x w))))))
|
|||
|
(lambda (r) (if (< r 10) (vector-ref em r) (it r)))))
|
|||
|
(define array:indexer/array
|
|||
|
(let ((em
|
|||
|
(vector
|
|||
|
(lambda (x v i) (+ (vector-ref x 0)))
|
|||
|
(lambda (x v i)
|
|||
|
(+
|
|||
|
(*
|
|||
|
(vector-ref x 0)
|
|||
|
(vector-ref v (array:actor-index i 0)))
|
|||
|
(vector-ref x 1)))
|
|||
|
(lambda (x v i)
|
|||
|
(+
|
|||
|
(*
|
|||
|
(vector-ref x 0)
|
|||
|
(vector-ref v (array:actor-index i 0)))
|
|||
|
(*
|
|||
|
(vector-ref x 1)
|
|||
|
(vector-ref v (array:actor-index i 1)))
|
|||
|
(vector-ref x 2)))
|
|||
|
(lambda (x v i)
|
|||
|
(+
|
|||
|
(*
|
|||
|
(vector-ref x 0)
|
|||
|
(vector-ref v (array:actor-index i 0)))
|
|||
|
(*
|
|||
|
(vector-ref x 1)
|
|||
|
(vector-ref v (array:actor-index i 1)))
|
|||
|
(*
|
|||
|
(vector-ref x 2)
|
|||
|
(vector-ref v (array:actor-index i 2)))
|
|||
|
(vector-ref x 3)))
|
|||
|
(lambda (x v i)
|
|||
|
(+
|
|||
|
(*
|
|||
|
(vector-ref x 0)
|
|||
|
(vector-ref v (array:actor-index i 0)))
|
|||
|
(*
|
|||
|
(vector-ref x 1)
|
|||
|
(vector-ref v (array:actor-index i 1)))
|
|||
|
(*
|
|||
|
(vector-ref x 2)
|
|||
|
(vector-ref v (array:actor-index i 2)))
|
|||
|
(*
|
|||
|
(vector-ref x 3)
|
|||
|
(vector-ref v (array:actor-index i 3)))
|
|||
|
(vector-ref x 4)))
|
|||
|
(lambda (x v i)
|
|||
|
(+
|
|||
|
(*
|
|||
|
(vector-ref x 0)
|
|||
|
(vector-ref v (array:actor-index i 0)))
|
|||
|
(*
|
|||
|
(vector-ref x 1)
|
|||
|
(vector-ref v (array:actor-index i 1)))
|
|||
|
(*
|
|||
|
(vector-ref x 2)
|
|||
|
(vector-ref v (array:actor-index i 2)))
|
|||
|
(*
|
|||
|
(vector-ref x 3)
|
|||
|
(vector-ref v (array:actor-index i 3)))
|
|||
|
(*
|
|||
|
(vector-ref x 4)
|
|||
|
(vector-ref v (array:actor-index i 4)))
|
|||
|
(vector-ref x 5)))
|
|||
|
(lambda (x v i)
|
|||
|
(+
|
|||
|
(*
|
|||
|
(vector-ref x 0)
|
|||
|
(vector-ref v (array:actor-index i 0)))
|
|||
|
(*
|
|||
|
(vector-ref x 1)
|
|||
|
(vector-ref v (array:actor-index i 1)))
|
|||
|
(*
|
|||
|
(vector-ref x 2)
|
|||
|
(vector-ref v (array:actor-index i 2)))
|
|||
|
(*
|
|||
|
(vector-ref x 3)
|
|||
|
(vector-ref v (array:actor-index i 3)))
|
|||
|
(*
|
|||
|
(vector-ref x 4)
|
|||
|
(vector-ref v (array:actor-index i 4)))
|
|||
|
(*
|
|||
|
(vector-ref x 5)
|
|||
|
(vector-ref v (array:actor-index i 5)))
|
|||
|
(vector-ref x 6)))
|
|||
|
(lambda (x v i)
|
|||
|
(+
|
|||
|
(*
|
|||
|
(vector-ref x 0)
|
|||
|
(vector-ref v (array:actor-index i 0)))
|
|||
|
(*
|
|||
|
(vector-ref x 1)
|
|||
|
(vector-ref v (array:actor-index i 1)))
|
|||
|
(*
|
|||
|
(vector-ref x 2)
|
|||
|
(vector-ref v (array:actor-index i 2)))
|
|||
|
(*
|
|||
|
(vector-ref x 3)
|
|||
|
(vector-ref v (array:actor-index i 3)))
|
|||
|
(*
|
|||
|
(vector-ref x 4)
|
|||
|
(vector-ref v (array:actor-index i 4)))
|
|||
|
(*
|
|||
|
(vector-ref x 5)
|
|||
|
(vector-ref v (array:actor-index i 5)))
|
|||
|
(*
|
|||
|
(vector-ref x 6)
|
|||
|
(vector-ref v (array:actor-index i 6)))
|
|||
|
(vector-ref x 7)))
|
|||
|
(lambda (x v i)
|
|||
|
(+
|
|||
|
(*
|
|||
|
(vector-ref x 0)
|
|||
|
(vector-ref v (array:actor-index i 0)))
|
|||
|
(*
|
|||
|
(vector-ref x 1)
|
|||
|
(vector-ref v (array:actor-index i 1)))
|
|||
|
(*
|
|||
|
(vector-ref x 2)
|
|||
|
(vector-ref v (array:actor-index i 2)))
|
|||
|
(*
|
|||
|
(vector-ref x 3)
|
|||
|
(vector-ref v (array:actor-index i 3)))
|
|||
|
(*
|
|||
|
(vector-ref x 4)
|
|||
|
(vector-ref v (array:actor-index i 4)))
|
|||
|
(*
|
|||
|
(vector-ref x 5)
|
|||
|
(vector-ref v (array:actor-index i 5)))
|
|||
|
(*
|
|||
|
(vector-ref x 6)
|
|||
|
(vector-ref v (array:actor-index i 6)))
|
|||
|
(*
|
|||
|
(vector-ref x 7)
|
|||
|
(vector-ref v (array:actor-index i 7)))
|
|||
|
(vector-ref x 8)))
|
|||
|
(lambda (x v i)
|
|||
|
(+
|
|||
|
(*
|
|||
|
(vector-ref x 0)
|
|||
|
(vector-ref v (array:actor-index i 0)))
|
|||
|
(*
|
|||
|
(vector-ref x 1)
|
|||
|
(vector-ref v (array:actor-index i 1)))
|
|||
|
(*
|
|||
|
(vector-ref x 2)
|
|||
|
(vector-ref v (array:actor-index i 2)))
|
|||
|
(*
|
|||
|
(vector-ref x 3)
|
|||
|
(vector-ref v (array:actor-index i 3)))
|
|||
|
(*
|
|||
|
(vector-ref x 4)
|
|||
|
(vector-ref v (array:actor-index i 4)))
|
|||
|
(*
|
|||
|
(vector-ref x 5)
|
|||
|
(vector-ref v (array:actor-index i 5)))
|
|||
|
(*
|
|||
|
(vector-ref x 6)
|
|||
|
(vector-ref v (array:actor-index i 6)))
|
|||
|
(*
|
|||
|
(vector-ref x 7)
|
|||
|
(vector-ref v (array:actor-index i 7)))
|
|||
|
(*
|
|||
|
(vector-ref x 8)
|
|||
|
(vector-ref v (array:actor-index i 8)))
|
|||
|
(vector-ref x 9)))))
|
|||
|
(it
|
|||
|
(lambda (w)
|
|||
|
(lambda (x v i)
|
|||
|
(+
|
|||
|
(*
|
|||
|
(vector-ref x 0)
|
|||
|
(vector-ref v (array:actor-index i 0)))
|
|||
|
(*
|
|||
|
(vector-ref x 1)
|
|||
|
(vector-ref v (array:actor-index i 1)))
|
|||
|
(*
|
|||
|
(vector-ref x 2)
|
|||
|
(vector-ref v (array:actor-index i 2)))
|
|||
|
(*
|
|||
|
(vector-ref x 3)
|
|||
|
(vector-ref v (array:actor-index i 3)))
|
|||
|
(*
|
|||
|
(vector-ref x 4)
|
|||
|
(vector-ref v (array:actor-index i 4)))
|
|||
|
(*
|
|||
|
(vector-ref x 5)
|
|||
|
(vector-ref v (array:actor-index i 5)))
|
|||
|
(*
|
|||
|
(vector-ref x 6)
|
|||
|
(vector-ref v (array:actor-index i 6)))
|
|||
|
(*
|
|||
|
(vector-ref x 7)
|
|||
|
(vector-ref v (array:actor-index i 7)))
|
|||
|
(*
|
|||
|
(vector-ref x 8)
|
|||
|
(vector-ref v (array:actor-index i 8)))
|
|||
|
(*
|
|||
|
(vector-ref x 9)
|
|||
|
(vector-ref v (array:actor-index i 9)))
|
|||
|
(do ((xi
|
|||
|
0
|
|||
|
(+
|
|||
|
(*
|
|||
|
(vector-ref x u)
|
|||
|
(vector-ref
|
|||
|
v
|
|||
|
(array:actor-index i u)))
|
|||
|
xi))
|
|||
|
(u (- w 1) (- u 1)))
|
|||
|
((< u 10) xi))
|
|||
|
(vector-ref x w))))))
|
|||
|
(lambda (r) (if (< r 10) (vector-ref em r) (it r)))))
|
|||
|
(define array:applier-to-vector
|
|||
|
(let ((em
|
|||
|
(vector
|
|||
|
(lambda (p v) (p))
|
|||
|
(lambda (p v) (p (vector-ref v 0)))
|
|||
|
(lambda (p v)
|
|||
|
(p (vector-ref v 0) (vector-ref v 1)))
|
|||
|
(lambda (p v)
|
|||
|
(p
|
|||
|
(vector-ref v 0)
|
|||
|
(vector-ref v 1)
|
|||
|
(vector-ref v 2)))
|
|||
|
(lambda (p v)
|
|||
|
(p
|
|||
|
(vector-ref v 0)
|
|||
|
(vector-ref v 1)
|
|||
|
(vector-ref v 2)
|
|||
|
(vector-ref v 3)))
|
|||
|
(lambda (p v)
|
|||
|
(p
|
|||
|
(vector-ref v 0)
|
|||
|
(vector-ref v 1)
|
|||
|
(vector-ref v 2)
|
|||
|
(vector-ref v 3)
|
|||
|
(vector-ref v 4)))
|
|||
|
(lambda (p v)
|
|||
|
(p
|
|||
|
(vector-ref v 0)
|
|||
|
(vector-ref v 1)
|
|||
|
(vector-ref v 2)
|
|||
|
(vector-ref v 3)
|
|||
|
(vector-ref v 4)
|
|||
|
(vector-ref v 5)))
|
|||
|
(lambda (p v)
|
|||
|
(p
|
|||
|
(vector-ref v 0)
|
|||
|
(vector-ref v 1)
|
|||
|
(vector-ref v 2)
|
|||
|
(vector-ref v 3)
|
|||
|
(vector-ref v 4)
|
|||
|
(vector-ref v 5)
|
|||
|
(vector-ref v 6)))
|
|||
|
(lambda (p v)
|
|||
|
(p
|
|||
|
(vector-ref v 0)
|
|||
|
(vector-ref v 1)
|
|||
|
(vector-ref v 2)
|
|||
|
(vector-ref v 3)
|
|||
|
(vector-ref v 4)
|
|||
|
(vector-ref v 5)
|
|||
|
(vector-ref v 6)
|
|||
|
(vector-ref v 7)))
|
|||
|
(lambda (p v)
|
|||
|
(p
|
|||
|
(vector-ref v 0)
|
|||
|
(vector-ref v 1)
|
|||
|
(vector-ref v 2)
|
|||
|
(vector-ref v 3)
|
|||
|
(vector-ref v 4)
|
|||
|
(vector-ref v 5)
|
|||
|
(vector-ref v 6)
|
|||
|
(vector-ref v 7)
|
|||
|
(vector-ref v 8)))))
|
|||
|
(it
|
|||
|
(lambda (r)
|
|||
|
(lambda (p v)
|
|||
|
(apply
|
|||
|
p
|
|||
|
(vector-ref v 0)
|
|||
|
(vector-ref v 1)
|
|||
|
(vector-ref v 2)
|
|||
|
(vector-ref v 3)
|
|||
|
(vector-ref v 4)
|
|||
|
(vector-ref v 5)
|
|||
|
(vector-ref v 6)
|
|||
|
(vector-ref v 7)
|
|||
|
(vector-ref v 8)
|
|||
|
(vector-ref v 9)
|
|||
|
(do ((k r (- k 1))
|
|||
|
(r
|
|||
|
'()
|
|||
|
(cons (vector-ref v (- k 1)) r)))
|
|||
|
((= k 10) r)))))))
|
|||
|
(lambda (r) (if (< r 10) (vector-ref em r) (it r)))))
|
|||
|
(define array:applier-to-actor
|
|||
|
(let ((em
|
|||
|
(vector
|
|||
|
(lambda (p a) (p))
|
|||
|
(lambda (p a) (p (array-ref a 0)))
|
|||
|
(lambda (p a)
|
|||
|
(p (array-ref a 0) (array-ref a 1)))
|
|||
|
(lambda (p a)
|
|||
|
(p
|
|||
|
(array-ref a 0)
|
|||
|
(array-ref a 1)
|
|||
|
(array-ref a 2)))
|
|||
|
(lambda (p a)
|
|||
|
(p
|
|||
|
(array-ref a 0)
|
|||
|
(array-ref a 1)
|
|||
|
(array-ref a 2)
|
|||
|
(array-ref a 3)))
|
|||
|
(lambda (p a)
|
|||
|
(p
|
|||
|
(array-ref a 0)
|
|||
|
(array-ref a 1)
|
|||
|
(array-ref a 2)
|
|||
|
(array-ref a 3)
|
|||
|
(array-ref a 4)))
|
|||
|
(lambda (p a)
|
|||
|
(p
|
|||
|
(array-ref a 0)
|
|||
|
(array-ref a 1)
|
|||
|
(array-ref a 2)
|
|||
|
(array-ref a 3)
|
|||
|
(array-ref a 4)
|
|||
|
(array-ref a 5)))
|
|||
|
(lambda (p a)
|
|||
|
(p
|
|||
|
(array-ref a 0)
|
|||
|
(array-ref a 1)
|
|||
|
(array-ref a 2)
|
|||
|
(array-ref a 3)
|
|||
|
(array-ref a 4)
|
|||
|
(array-ref a 5)
|
|||
|
(array-ref a 6)))
|
|||
|
(lambda (p a)
|
|||
|
(p
|
|||
|
(array-ref a 0)
|
|||
|
(array-ref a 1)
|
|||
|
(array-ref a 2)
|
|||
|
(array-ref a 3)
|
|||
|
(array-ref a 4)
|
|||
|
(array-ref a 5)
|
|||
|
(array-ref a 6)
|
|||
|
(array-ref a 7)))
|
|||
|
(lambda (p a)
|
|||
|
(p
|
|||
|
(array-ref a 0)
|
|||
|
(array-ref a 1)
|
|||
|
(array-ref a 2)
|
|||
|
(array-ref a 3)
|
|||
|
(array-ref a 4)
|
|||
|
(array-ref a 5)
|
|||
|
(array-ref a 6)
|
|||
|
(array-ref a 7)
|
|||
|
(array-ref a 8)))))
|
|||
|
(it
|
|||
|
(lambda (r)
|
|||
|
(lambda (p a)
|
|||
|
(apply
|
|||
|
a
|
|||
|
(array-ref a 0)
|
|||
|
(array-ref a 1)
|
|||
|
(array-ref a 2)
|
|||
|
(array-ref a 3)
|
|||
|
(array-ref a 4)
|
|||
|
(array-ref a 5)
|
|||
|
(array-ref a 6)
|
|||
|
(array-ref a 7)
|
|||
|
(array-ref a 8)
|
|||
|
(array-ref a 9)
|
|||
|
(do ((k r (- k 1))
|
|||
|
(r '() (cons (array-ref a (- k 1)) r)))
|
|||
|
((= k 10) r)))))))
|
|||
|
(lambda (r)
|
|||
|
"These are high level, hiding implementation at call site."
|
|||
|
(if (< r 10) (vector-ref em r) (it r)))))
|
|||
|
(define array:applier-to-backing-vector
|
|||
|
(let ((em
|
|||
|
(vector
|
|||
|
(lambda (p ai av) (p))
|
|||
|
(lambda (p ai av)
|
|||
|
(p (vector-ref av (array:actor-index ai 0))))
|
|||
|
(lambda (p ai av)
|
|||
|
(p
|
|||
|
(vector-ref av (array:actor-index ai 0))
|
|||
|
(vector-ref av (array:actor-index ai 1))))
|
|||
|
(lambda (p ai av)
|
|||
|
(p
|
|||
|
(vector-ref av (array:actor-index ai 0))
|
|||
|
(vector-ref av (array:actor-index ai 1))
|
|||
|
(vector-ref av (array:actor-index ai 2))))
|
|||
|
(lambda (p ai av)
|
|||
|
(p
|
|||
|
(vector-ref av (array:actor-index ai 0))
|
|||
|
(vector-ref av (array:actor-index ai 1))
|
|||
|
(vector-ref av (array:actor-index ai 2))
|
|||
|
(vector-ref av (array:actor-index ai 3))))
|
|||
|
(lambda (p ai av)
|
|||
|
(p
|
|||
|
(vector-ref av (array:actor-index ai 0))
|
|||
|
(vector-ref av (array:actor-index ai 1))
|
|||
|
(vector-ref av (array:actor-index ai 2))
|
|||
|
(vector-ref av (array:actor-index ai 3))
|
|||
|
(vector-ref av (array:actor-index ai 4))))
|
|||
|
(lambda (p ai av)
|
|||
|
(p
|
|||
|
(vector-ref av (array:actor-index ai 0))
|
|||
|
(vector-ref av (array:actor-index ai 1))
|
|||
|
(vector-ref av (array:actor-index ai 2))
|
|||
|
(vector-ref av (array:actor-index ai 3))
|
|||
|
(vector-ref av (array:actor-index ai 4))
|
|||
|
(vector-ref av (array:actor-index ai 5))))
|
|||
|
(lambda (p ai av)
|
|||
|
(p
|
|||
|
(vector-ref av (array:actor-index ai 0))
|
|||
|
(vector-ref av (array:actor-index ai 1))
|
|||
|
(vector-ref av (array:actor-index ai 2))
|
|||
|
(vector-ref av (array:actor-index ai 3))
|
|||
|
(vector-ref av (array:actor-index ai 4))
|
|||
|
(vector-ref av (array:actor-index ai 5))
|
|||
|
(vector-ref av (array:actor-index ai 6))))
|
|||
|
(lambda (p ai av)
|
|||
|
(p
|
|||
|
(vector-ref av (array:actor-index ai 0))
|
|||
|
(vector-ref av (array:actor-index ai 1))
|
|||
|
(vector-ref av (array:actor-index ai 2))
|
|||
|
(vector-ref av (array:actor-index ai 3))
|
|||
|
(vector-ref av (array:actor-index ai 4))
|
|||
|
(vector-ref av (array:actor-index ai 5))
|
|||
|
(vector-ref av (array:actor-index ai 6))
|
|||
|
(vector-ref av (array:actor-index ai 7))))
|
|||
|
(lambda (p ai av)
|
|||
|
(p
|
|||
|
(vector-ref av (array:actor-index ai 0))
|
|||
|
(vector-ref av (array:actor-index ai 1))
|
|||
|
(vector-ref av (array:actor-index ai 2))
|
|||
|
(vector-ref av (array:actor-index ai 3))
|
|||
|
(vector-ref av (array:actor-index ai 4))
|
|||
|
(vector-ref av (array:actor-index ai 5))
|
|||
|
(vector-ref av (array:actor-index ai 6))
|
|||
|
(vector-ref av (array:actor-index ai 7))
|
|||
|
(vector-ref av (array:actor-index ai 8))))))
|
|||
|
(it
|
|||
|
(lambda (r)
|
|||
|
(lambda (p ai av)
|
|||
|
(apply
|
|||
|
p
|
|||
|
(vector-ref av (array:actor-index ai 0))
|
|||
|
(vector-ref av (array:actor-index ai 1))
|
|||
|
(vector-ref av (array:actor-index ai 2))
|
|||
|
(vector-ref av (array:actor-index ai 3))
|
|||
|
(vector-ref av (array:actor-index ai 4))
|
|||
|
(vector-ref av (array:actor-index ai 5))
|
|||
|
(vector-ref av (array:actor-index ai 6))
|
|||
|
(vector-ref av (array:actor-index ai 7))
|
|||
|
(vector-ref av (array:actor-index ai 8))
|
|||
|
(vector-ref av (array:actor-index ai 9))
|
|||
|
(do ((k r (- k 1))
|
|||
|
(r
|
|||
|
'()
|
|||
|
(cons
|
|||
|
(vector-ref
|
|||
|
av
|
|||
|
(array:actor-index ai (- k 1)))
|
|||
|
r)))
|
|||
|
((= k 10) r)))))))
|
|||
|
(lambda (r)
|
|||
|
"These are low level, exposing implementation at call site."
|
|||
|
(if (< r 10) (vector-ref em r) (it r)))))
|
|||
|
(define (array:index/vector r x v)
|
|||
|
((array:indexer/vector r) x v))
|
|||
|
(define (array:index/array r x av ai)
|
|||
|
((array:indexer/array r) x av ai))
|
|||
|
(define (array:apply-to-vector r p v)
|
|||
|
((array:applier-to-vector r) p v))
|
|||
|
(define (array:apply-to-actor r p a)
|
|||
|
((array:applier-to-actor r) p a)))
|