1: | | (declare (fixnum)) |
2: | | |
3: | | ;;; The following macro is used to determine whether certain keyword arguments |
4: | | ;;; were omitted. It is specific to Gambit-C's compiler; note that it's not defined |
5: | | ;;; in the Gambit-C interpreter. Redefine it for other schemes. |
6: | | |
7: | | (##define-macro (macro-absent-obj) |
8: | | (##namespace ("c#" absent-object)) |
9: | | `',absent-object) |
10: | | |
11: | | ;;; This is Gambit-specific to make it a bit faster |
12: | | |
13: | | (define (exact-integer? x) |
14: | 0% | (or (##fixnum? x) |
15: | | (##bignum? x))) |
16: | | |
17: | | ;;; We need a multi-argument every, but not something as fancy as in Olin Shivers |
18: | | ;;; list library. (Shiver's version works fine, though, for our purposes.) |
19: | | |
20: | | (define (every pred list . lists) |
21: | | (if (pair? lists) |
22: | | (let loop ((lists (cons list lists))) |
23: | | (or (null? (car lists)) |
24: | | (and (apply pred (map car lists)) |
25: | | (loop (map cdr lists))))) |
26: | | (let loop ((list list)) |
27: | | (or (null? list) |
28: | | (and (pred (car list)) |
29: | | (loop (cdr list))))))) |
30: | | |
31: | | ;;; An Interval is a cross product of multi-indices |
32: | | |
33: | | ;;; [l_0,u_0) x [l_1,u_1) x ... x [l_n-1,u_n-1) |
34: | | |
35: | | ;;; where l_i < u_i for 0 <= i < n, and n > 0 is the dimension of the Interval |
36: | | |
37: | .11% | (define-structure Interval |
38: | | lower-bounds ;; a vector of exact integers l_0,...,l_n-1 |
39: | | upper-bounds) ;; a vector of exact integers u_0,...,u_n-1 |
40: | | |
41: | | (define (build-Interval lower-bounds upper-bounds) |
42: | | (or (and (not (vector? lower-bounds)) |
43: | | (error "build-Interval: lower-bounds must be a vector: " lower-bounds)) |
44: | | (and (not (vector? upper-bounds)) |
45: | | (error "build-Interval: upper-bounds must be a vector: " upper-bounds)) |
46: | | (and (not (= (vector-length lower-bounds) (vector-length upper-bounds))) |
47: | | (error "build-Interval: lower-bounds and upper-bounds must be the same length: " lower-bounds upper-bounds)) |
48: | | (and (not (< 0 (vector-length lower-bounds))) |
49: | | (error "build-Interval: lower-bounds and upper-bounds must be nonempty vectors: " lower-bounds upper-bounds)) |
50: | | (let ((lower-bounds-list (vector->list lower-bounds)) |
51: | | (upper-bounds-list (vector->list upper-bounds))) |
52: | | (or (and (not (every exact-integer? lower-bounds-list)) |
53: | | (error "build-Interval: All lower-bounds must be exact integers: " lower-bounds)) |
54: | | (and (not (every exact-integer? upper-bounds-list)) |
55: | | (error "build-Interval: All upper-bounds must be exact integers: " upper-bounds)) |
56: | | (and (not (every (lambda (x y) (< x y)) lower-bounds-list upper-bounds-list)) |
57: | | (error "build-Interval: Each lower-bound must be less than the associated upper-bound: " lower-bounds upper-bounds)) |
58: | | (make-Interval lower-bounds upper-bounds))))) |
59: | | |
60: | | (define (##Interval-dimension interval) |
61: | .05% | (vector-length (Interval-lower-bounds interval))) |
62: | | |
63: | | (define (Interval-dimension interval) |
64: | | (or (and (not (Interval? interval)) |
65: | | (error "Interval-dimension: argument is not an interval: " interval)) |
66: | | (##Interval-dimension interval))) |
67: | | |
68: | | (define (##Interval-lower-bound interval i) |
69: | .02% | (vector-ref (Interval-lower-bounds interval) i)) |
70: | | |
71: | | (define (##Interval-upper-bound interval i) |
72: | .01% | (vector-ref (Interval-upper-bounds interval) i)) |
73: | | |
74: | | (define (Interval-lower-bound interval i) |
75: | | (or (and (not (Interval? interval)) |
76: | | (error "Interval-lower-bound: argument is not an interval: " interval i)) |
77: | | (and (not (exact-integer? i)) |
78: | | (error "Interval-lower-bound: argument is not a exact integer: " interval i)) |
79: | | (and (not (< -1 i (##Interval-dimension interval))) |
80: | | (error "Interval-lower-bound: index is not between 0 (inclusive) and (Interval-dimension interval) (exclusive): " interval i)) |
81: | | (vector-ref (Interval-lower-bounds interval) i))) |
82: | | |
83: | | (define (Interval-upper-bound interval i) |
84: | | (or (and (not (Interval? interval)) |
85: | | (error "Interval-upper-bound: argument is not an interval: " interval i)) |
86: | | (and (not (exact-integer? i)) |
87: | | (error "Interval-upper-bound: argument is not a exact integer: " interval i)) |
88: | | (and (not (< -1 i (##Interval-dimension interval))) |
89: | | (error "Interval-upper-bound: index is not between 0 (inclusive) and (Interval-dimension interval) (exclusive): " interval i)) |
90: | | (vector-ref (Interval-upper-bounds interval) i))) |
91: | | |
92: | | (define (##Interval-lower-bounds->list interval) |
93: | | (vector->list (Interval-lower-bounds interval))) |
94: | | |
95: | | (define (Interval-lower-bounds->list interval) |
96: | | (or (and (not (Interval? interval)) |
97: | | (error "Interval-lower-bounds->list: argument is not an interval: " interval)) |
98: | | (##Interval-lower-bounds->list interval))) |
99: | | |
100: | | (define (##Interval-upper-bounds->list interval) |
101: | | (vector->list (Interval-upper-bounds interval))) |
102: | | |
103: | | (define (Interval-upper-bounds->list interval) |
104: | | (or (and (not (Interval? interval)) |
105: | | (error "Interval-upper-bounds->list: argument is not an interval: " interval)) |
106: | | (##Interval-upper-bounds->list interval))) |
107: | | |
108: | | (define (Interval-curry interval left-dimension) |
109: | | (declare (fixnum)) |
110: | | (or (and (not (Interval? interval)) |
111: | | (error "Interval-curry argument is not an interval: " interval left-dimension)) |
112: | 0% | (and (not (exact-integer? left-dimension)) |
113: | | (error "Interval-curry argument is not a exact integer: " interval left-dimension)) |
114: | 0% | (and (not (< 0 left-dimension (##Interval-dimension interval))) |
115: | | (error "Interval-curry: argument is not between 0 and (Interval-dimension interval) (exclusive): " interval left-dimension)) |
116: | 0% | (let ((n (##Interval-dimension interval))) |
117: | 0% | (let ((lower-bounds (Interval-lower-bounds interval)) |
118: | 0% | (upper-bounds (Interval-upper-bounds interval)) |
119: | 0% | (left-lower-bounds (make-vector left-dimension)) |
120: | 0% | (left-upper-bounds (make-vector left-dimension)) |
121: | 0% | (right-lower-bounds (make-vector (- n left-dimension))) |
122: | | (right-upper-bounds (make-vector (- n left-dimension)))) |
123: | 0% | (do ((i 0 (+ i 1))) |
124: | 0% | ((= i left-dimension) |
125: | 0% | (do ((i i (+ i 1))) |
126: | 0% | ((= i n) |
127: | 0% | (values (make-Interval left-lower-bounds |
128: | 0% | left-upper-bounds) |
129: | | (make-Interval right-lower-bounds |
130: | | right-upper-bounds))) |
131: | 0% | (vector-set! right-lower-bounds (- i left-dimension) (vector-ref lower-bounds i)) |
132: | 0% | (vector-set! right-upper-bounds (- i left-dimension) (vector-ref upper-bounds i)))) |
133: | 0% | (vector-set! left-lower-bounds i (vector-ref lower-bounds i)) |
134: | 0% | (vector-set! left-upper-bounds i (vector-ref upper-bounds i))))))) |
135: | | |
136: | | (define (Interval-distinguish-one interval index) |
137: | | (or (and (not (Interval? interval)) |
138: | | (error "Interval-distinguish-one argument is not an interval: " interval index)) |
139: | | (and (not (exact-integer? index)) |
140: | | (error "Interval-distinguish-one argument is not a exact integer: " interval index)) |
141: | | (and (not (< 1 (##Interval-dimension interval))) |
142: | | (error "Interval-distinguish-one: The dimension of the argument is not greater than one: " interval index)) |
143: | | (and (not (< -1 index (##Interval-dimension interval))) |
144: | | (error "Interval-distinguish-one: argument is not between 0 (inclusive) and (Interval-dimension interval) (exclusive): " interval index)) |
145: | | (let ((n (##Interval-dimension interval))) |
146: | | (let* ((lower-bounds (Interval-lower-bounds interval)) |
147: | | (upper-bounds (Interval-upper-bounds interval)) |
148: | | (left-lower-bounds (make-vector (- n 1))) |
149: | | (left-upper-bounds (make-vector (- n 1)))) |
150: | | (let loop ((i 0) |
151: | | (j 0)) |
152: | | (cond ((= i n) |
153: | | (values (build-Interval left-lower-bounds |
154: | | left-upper-bounds) |
155: | | (build-Interval (vector (vector-ref lower-bounds index)) |
156: | | (vector (vector-ref upper-bounds index))))) |
157: | | ((= i index) |
158: | | (loop (+ i 1) |
159: | | j)) |
160: | | (else |
161: | | (vector-set! left-lower-bounds j (vector-ref lower-bounds i)) |
162: | | (vector-set! left-upper-bounds j (vector-ref upper-bounds i)) |
163: | | (loop (+ i 1) |
164: | | (+ j 1))))))))) |
165: | | |
166: | | (define (Interval-volume interval) |
167: | | (or (and (not (Interval? interval)) |
168: | | (error "Interval-volume: argument is not an interval: " interval)) |
169: | | (do ((i (- (##Interval-dimension interval) 1) (- i 1)) |
170: | | (result 1 (* result (- (##Interval-upper-bound interval i) |
171: | | (##Interval-lower-bound interval i))))) |
172: | | ((< i 0) result)))) |
173: | | |
174: | | (define (Interval= interval1 interval2) |
175: | | (or (and (not (and (Interval? interval1) (Interval? interval2))) |
176: | | (error "Interval=: Not all arguments are intervals: " interval1 interval2)) |
177: | | (and (= (##Interval-dimension interval1) (##Interval-dimension interval2)) |
178: | | (let loop ((i (- (##Interval-dimension interval1) 1))) |
179: | | (or (< i 0) |
180: | | (and (= (##Interval-upper-bound interval1 i) |
181: | | (##Interval-upper-bound interval2 i)) |
182: | | (= (##Interval-lower-bound interval1 i) |
183: | | (##Interval-lower-bound interval2 i)) |
184: | | (loop (- i 1)))))))) |
185: | | |
186: | | (define (Interval-subset? interval1 interval2) |
187: | | (or (and (not (and (Interval? interval1) (Interval? interval2))) |
188: | | (error "Interval-subset?: Not all arguments are intervals: " interval1 interval2)) |
189: | | (and (= (##Interval-dimension interval1) (##Interval-dimension interval2)) |
190: | | (let loop ((i (- (##Interval-dimension interval1) 1))) |
191: | | (or (< i 0) |
192: | | (and (>= (##Interval-lower-bound interval1 i) |
193: | | (##Interval-lower-bound interval2 i)) |
194: | | (<= (##Interval-upper-bound interval1 i) |
195: | | (##Interval-upper-bound interval2 i)) |
196: | | (loop (- i 1)))))))) |
197: | | |
198: | | (define (Interval-contains-multi-index? interval i |
199: | | #!optional |
200: | | (j (macro-absent-obj)) |
201: | | (k (macro-absent-obj)) |
202: | | (l (macro-absent-obj)) |
203: | | #!rest |
204: | | multi-index-tail) |
205: | | (or (and (not (Interval? interval)) |
206: | | (error "Interval-contains-multi-index?: argument is not an Interval: " interval)) |
207: | | (cond ((eq? j (macro-absent-obj)) |
208: | | (or (and (not (exact-integer? i)) |
209: | | (error "Interval-contains-multi-index?: multi-index component is not an exact integer: " i)) |
210: | | (and (not (= (##Interval-dimension interval) 1)) |
211: | | (error "Interval-contains-multi-index?: dimension of interval does not match number of arguments: " interval i)) |
212: | | (and (<= (##Interval-lower-bound interval 0) i) |
213: | | (< i (##Interval-upper-bound interval 0))))) |
214: | | ((eq? k (macro-absent-obj)) |
215: | | (or (and (not (and (exact-integer? i) |
216: | | (exact-integer? j))) |
217: | | (error "Interval-contains-multi-index?: at least one multi-index component is not an exact integer: " i j)) |
218: | | (and (not (= (##Interval-dimension interval) 2)) |
219: | | (error "Interval-contains-multi-index?: dimension of interval does not match number of arguments: " interval i j)) |
220: | | (and (<= (##Interval-lower-bound interval 0) i) |
221: | | (< i (##Interval-upper-bound interval 0)) |
222: | | (<= (##Interval-lower-bound interval 1) j) |
223: | | (< j (##Interval-upper-bound interval 1))))) |
224: | | ((eq? l (macro-absent-obj)) |
225: | | (or (and (not (and (exact-integer? i) |
226: | | (exact-integer? j) |
227: | | (exact-integer? k))) |
228: | | (error "Interval-contains-multi-index?: at least one multi-index component is not an exact integer: " i j k)) |
229: | | (and (not (= (##Interval-dimension interval) 3)) |
230: | | (error "Interval-contains-multi-index?: dimension of interval does not match number of arguments: " interval i j k)) |
231: | | (and (<= (##Interval-lower-bound interval 0) i) |
232: | | (< i (##Interval-upper-bound interval 0)) |
233: | | (<= (##Interval-lower-bound interval 1) j) |
234: | | (< j (##Interval-upper-bound interval 1)) |
235: | | (<= (##Interval-lower-bound interval 2) k) |
236: | | (< k (##Interval-upper-bound interval 2))))) |
237: | | ((null? multi-index-tail) |
238: | | (or (and (not (and (exact-integer? i) |
239: | | (exact-integer? j) |
240: | | (exact-integer? k) |
241: | | (exact-integer? l))) |
242: | | (error "Interval-contains-multi-index?: at least one multi-index component is not an exact integer: " i j k l)) |
243: | | (and (not (= (##Interval-dimension interval) 4)) |
244: | | (error "Interval-contains-multi-index?: dimension of interval does not match number of arguments: " interval i j k l)) |
245: | | (and (<= (##Interval-lower-bound interval 0) i) |
246: | | (< i (##Interval-upper-bound interval 0)) |
247: | | (<= (##Interval-lower-bound interval 1) j) |
248: | | (< j (##Interval-upper-bound interval 1)) |
249: | | (<= (##Interval-lower-bound interval 2) k) |
250: | | (< k (##Interval-upper-bound interval 2)) |
251: | | (<= (##Interval-lower-bound interval 3) l) |
252: | | (< l (##Interval-upper-bound interval 3))))) |
253: | | (else |
254: | | (let ((multi-index (cons (i (cons j (cons k (cons l multi-index-tail))))))) |
255: | | (or (and (not (every exact-integer? multi-index)) |
256: | | (apply error "Interval-contains-multi-index?: at least one multi-index component is not an exact integer: " multi-index)) |
257: | | (and (not (= (##Interval-dimension interval) (length multi-index))) |
258: | | (apply error "Interval-contains-multi-index?: dimension of interval does not match number of arguments: " interval multi-index)) |
259: | | (every (lambda (l i u) |
260: | | (and (<= l i) |
261: | | (< i u))) |
262: | | (Interval-lower-bounds->list interval) |
263: | | multi-index |
264: | | (Interval-upper-bounds->list interval)))))))) |
265: | | |
266: | | |
267: | | ;;; Applies f to every element of the domain, in lexicographical order |
268: | | |
269: | | (define (Interval-for-each f interval) |
270: | | (or (and (not (Interval? interval)) |
271: | | (error "Interval-for-each: Argument is not a interval: " interval)) |
272: | | (and (not (procedure? f)) |
273: | | (error "Interval-for-each: Argument is not a procedure: " f)) |
274: | | (case (##Interval-dimension interval) |
275: | | ((1) (let ((lower-i (##Interval-lower-bound interval 0)) |
276: | | (upper-i (##Interval-upper-bound interval 0))) |
277: | | (let i-loop ((i lower-i)) |
278: | | (if (< i upper-i) |
279: | | (begin |
280: | | (f i) |
281: | | (i-loop (+ i 1))))))) |
282: | | ((2) (let ((lower-i (##Interval-lower-bound interval 0)) |
283: | | (lower-j (##Interval-lower-bound interval 1)) |
284: | | (upper-i (##Interval-upper-bound interval 0)) |
285: | | (upper-j (##Interval-upper-bound interval 1))) |
286: | | (let i-loop ((i lower-i)) |
287: | 0% | (if (< i upper-i) |
288: | 0% | (let j-loop ((j lower-j)) |
289: | .08% | (if (< j upper-j) |
290: | | (begin |
291: | .07% | (f i j) |
292: | .1% | (j-loop (+ j 1))) |
293: | 0% | (i-loop (+ i 1)))))))) |
294: | | ((3) (let ((lower-i (##Interval-lower-bound interval 0)) |
295: | | (lower-j (##Interval-lower-bound interval 1)) |
296: | | (lower-k (##Interval-lower-bound interval 2)) |
297: | | (upper-i (##Interval-upper-bound interval 0)) |
298: | | (upper-j (##Interval-upper-bound interval 1)) |
299: | | (upper-k (##Interval-upper-bound interval 2))) |
300: | | (let i-loop ((i lower-i)) |
301: | | (if (< i upper-i) |
302: | 0% | (let j-loop ((j lower-j)) |
303: | .01% | (if (< j upper-j) |
304: | .03% | (let k-loop ((k lower-k)) |
305: | .8% | (if (< k upper-k) |
306: | | (begin |
307: | .97% | (f i j k) |
308: | 1.26% | (k-loop (+ k 1))) |
309: | .01% | (j-loop (+ j 1)))) |
310: | 0% | (i-loop (+ i 1)))))))) |
311: | | ((4) (let ((lower-i (##Interval-lower-bound interval 0)) |
312: | | (lower-j (##Interval-lower-bound interval 1)) |
313: | | (lower-k (##Interval-lower-bound interval 2)) |
314: | | (lower-l (##Interval-lower-bound interval 3)) |
315: | | (upper-i (##Interval-upper-bound interval 0)) |
316: | | (upper-j (##Interval-upper-bound interval 1)) |
317: | | (upper-k (##Interval-upper-bound interval 2)) |
318: | | (upper-l (##Interval-upper-bound interval 3))) |
319: | | (let i-loop ((i lower-i)) |
320: | | (if (< i upper-i) |
321: | | (let j-loop ((j lower-j)) |
322: | | (if (< j upper-j) |
323: | | (let k-loop ((k lower-k)) |
324: | .02% | (if (< k upper-k) |
325: | .03% | (let l-loop ((l lower-l)) |
326: | .88% | (if (< l upper-l) |
327: | | (begin |
328: | 1.26% | (f i j k l) |
329: | 1.29% | (l-loop (+ l 1))) |
330: | .02% | (k-loop (+ k 1)))) |
331: | 0% | (j-loop (+ j 1)))) |
332: | | (i-loop (+ i 1)))))))) |
333: | | (else |
334: | | (let ((lower-bounds (list->vector (##Interval-lower-bounds->list interval))) |
335: | | (upper-bounds (list->vector (##Interval-upper-bounds->list interval)))) |
336: | | |
337: | | (define (multi-index->args multi-index) |
338: | | (cdr multi-index)) |
339: | | |
340: | | (define (vector->multi-index arg) |
341: | | |
342: | | (define (tail-ref l i) |
343: | | (let loop ((l l) (i i)) |
344: | | (if (= i 0) |
345: | | l |
346: | | (loop (cdr l) (- i 1))))) |
347: | | |
348: | | (let ((l (vector->list arg)) |
349: | | (v (make-vector (vector-length arg)))) |
350: | | (do ((i (- (vector-length v) 1) (- i 1))) |
351: | | ((< i 0) (cons v l)) |
352: | | (vector-set! v i (tail-ref l i))))) |
353: | | |
354: | | (define (next-multi-index! multi-index lower-bounds upper-bounds) |
355: | | (let ((v (car multi-index))) |
356: | | (let loop ((i (- (vector-length v) 1))) |
357: | | (and (<= 0 i) |
358: | | (let* ((l-tail (vector-ref v i)) |
359: | | (next-index (+ (car l-tail) 1))) |
360: | | (if (< next-index (vector-ref upper-bounds i)) |
361: | | (begin |
362: | | (set-car! l-tail next-index) |
363: | | multi-index) |
364: | | (begin |
365: | | (set-car! l-tail (vector-ref lower-bounds i)) |
366: | | (loop (- i 1))))))))) |
367: | | |
368: | | (let loop ((multi-index (vector->multi-index lower-bounds))) |
369: | | (if multi-index |
370: | | (begin |
371: | | (apply f (multi-index->args multi-index)) |
372: | | (loop (next-multi-index! multi-index lower-bounds upper-bounds)))))))))) |
373: | | |
374: | | ;;; I defined this separately in the hope that it would be speeded up. |
375: | | ;;; Calculates (...(operator (operator (operator identity (f multi-index_1)) (f multi-index_2)) (f multi-index_3)) ...) |
376: | | ;;; again in lexicographical order |
377: | | |
378: | | (define (Interval-reduce f operator identity interval) |
379: | | (or (and (not (Interval? interval)) |
380: | | (error "Interval-reduce: Argument is not a interval: " interval)) |
381: | | (and (not (procedure? f)) |
382: | | (error "Interval-reduce: Argument is not a procedure: " f)) |
383: | | (and (not (procedure? operator)) |
384: | | (error "Interval-reduce: Operator is not a procedure: " operator)) |
385: | | (case (##Interval-dimension interval) |
386: | | ((1) (let ((lower-i (##Interval-lower-bound interval 0)) |
387: | | (upper-i (##Interval-upper-bound interval 0))) |
388: | | (let i-loop ((i lower-i) (result identity)) |
389: | | (if (= i upper-i) |
390: | | result |
391: | | (i-loop (+ i 1) (operator result (f i))))))) |
392: | | ((2) (let ((lower-i (##Interval-lower-bound interval 0)) |
393: | | (lower-j (##Interval-lower-bound interval 1)) |
394: | | (upper-i (##Interval-upper-bound interval 0)) |
395: | | (upper-j (##Interval-upper-bound interval 1))) |
396: | | (let i-loop ((i lower-i) (result identity)) |
397: | | (if (= i upper-i) |
398: | | result |
399: | | (let j-loop ((j lower-j) (result result)) |
400: | 0% | (if (= j upper-j) |
401: | | (i-loop (+ i 1) result) |
402: | .01% | (j-loop (+ j 1) (operator result (f i j))))))))) |
403: | | ((3) (let ((lower-i (##Interval-lower-bound interval 0)) |
404: | | (lower-j (##Interval-lower-bound interval 1)) |
405: | | (lower-k (##Interval-lower-bound interval 2)) |
406: | | (upper-i (##Interval-upper-bound interval 0)) |
407: | | (upper-j (##Interval-upper-bound interval 1)) |
408: | | (upper-k (##Interval-upper-bound interval 2))) |
409: | | (let i-loop ((i lower-i) (result identity)) |
410: | | (if (= i upper-i) |
411: | | result |
412: | | (let j-loop ((j lower-j) (result result)) |
413: | | (if (= j upper-j) |
414: | | (i-loop (+ i 1) result) |
415: | | (let k-loop ((k lower-k) (result result)) |
416: | | (if (= k upper-k) |
417: | | (j-loop (+ j 1) result) |
418: | | (k-loop (+ k 1) (operator result (f i j k))))))))))) |
419: | | ((4) (let ((lower-i (##Interval-lower-bound interval 0)) |
420: | | (lower-j (##Interval-lower-bound interval 1)) |
421: | | (lower-k (##Interval-lower-bound interval 2)) |
422: | | (lower-l (##Interval-lower-bound interval 3)) |
423: | | (upper-i (##Interval-upper-bound interval 0)) |
424: | | (upper-j (##Interval-upper-bound interval 1)) |
425: | | (upper-k (##Interval-upper-bound interval 2)) |
426: | | (upper-l (##Interval-upper-bound interval 3))) |
427: | | (let i-loop ((i lower-i) (result identity)) |
428: | | (if (= i upper-i) |
429: | | result |
430: | | (let j-loop ((j lower-j) (result result)) |
431: | | (if (= j upper-j) |
432: | | (i-loop (+ i 1) result) |
433: | | (let k-loop ((k lower-k) (result result)) |
434: | | (if (= k upper-k) |
435: | | (j-loop (+ j 1) result) |
436: | | (let l-loop ((l lower-l) (result result)) |
437: | | (if (= l upper-l) |
438: | | (k-loop (+ k 1) result) |
439: | | (l-loop (+ l 1) (operator result (f i j k l))))))))))))) |
440: | | (else |
441: | | (let ((lower-bounds (list->vector (##Interval-lower-bounds->list interval))) |
442: | | (upper-bounds (list->vector (##Interval-upper-bounds->list interval)))) |
443: | | |
444: | | (define (tail-ref l i) |
445: | | (let loop ((l l) (i i)) |
446: | | (if (= i 0) |
447: | | l |
448: | | (loop (cdr l) (- i 1))))) |
449: | | |
450: | | (define (vector->multi-index arg) |
451: | | (let ((l (vector->list arg)) |
452: | | (v (make-vector (vector-length arg)))) |
453: | | (do ((i (- (vector-length v) 1) (- i 1))) |
454: | | ((< i 0) (cons v l)) |
455: | | (vector-set! v i (tail-ref l i))))) |
456: | | |
457: | | (define (multi-index->args multi-index) |
458: | | (cdr multi-index)) |
459: | | |
460: | | (define (next-multi-index! multi-index lower-bounds upper-bounds) |
461: | | (let ((v (car multi-index))) |
462: | | (let loop ((i (- (vector-length v) 1))) |
463: | | (and (<= 0 i) |
464: | | (let* ((l-tail (vector-ref v i)) |
465: | | (next-index (+ (car l-tail) 1))) |
466: | | (if (< next-index (vector-ref upper-bounds i)) |
467: | | (begin |
468: | | (set-car! l-tail next-index) |
469: | | multi-index) |
470: | | (begin |
471: | | (set-car! l-tail (vector-ref lower-bounds i)) |
472: | | (loop (- i 1))))))))) |
473: | | |
474: | | (let loop ((multi-index (vector->multi-index lower-bounds)) |
475: | | (result identity)) |
476: | | (if multi-index |
477: | | (let ((next-result (operator result (apply f (multi-index->args multi-index))))) |
478: | | (loop (next-multi-index! multi-index lower-bounds upper-bounds) |
479: | | next-result)) |
480: | | result))))))) |
481: | | |
482: | | ;; We'll use the same basic container for all types of arrays. |
483: | | |
484: | .45% | (define-structure Array-base |
485: | | ;; Part of all arrays |
486: | | domain ;; an Interval |
487: | | accessor ;; (lambda (i_0 ... i_n-1) ...) returns a value for (i_0,...,i_n-1) in (Array-domain a) |
488: | | ;; Part of mutable arrays |
489: | | setter ;; (lambda (v i_0 ... i_n-1) ...) sets a value for (i_0,...,i_n-1) in (Array-domain a) |
490: | | ;; Part of Fixed arrays |
491: | | manipulators ;; a Fixed-array-manipulator |
492: | | body ;; the backing store for this array |
493: | | indexer ;; see below |
494: | | affine? ;; whether the indexer is an affine map |
495: | | ) |
496: | | |
497: | | ;; An array has a domain (which is an interval) and an accessor that maps that domain into some type of |
498: | | ;; Scheme objects |
499: | | |
500: | | (define (build-Array domain accessor) |
501: | 0% | (or (and (not (Interval? domain)) |
502: | | (error "build-Array: domain is not an interval: " domain)) |
503: | 0% | (and (not (procedure? accessor)) |
504: | | (error "build-Array: accessor is not a procedure: " accessor)) |
505: | 0% | (make-Array-base domain |
506: | | accessor |
507: | | #f ; setter |
508: | | #f ; manipulators |
509: | | #f ; body |
510: | | #f ; indexer |
511: | | #f ; affine? |
512: | | ))) |
513: | | |
514: | | (define (Array? obj) |
515: | .07% | (Array-base? obj)) |
516: | | |
517: | | (define (Array-domain obj) |
518: | .02% | (or (and (not (Array? obj)) |
519: | | (error "Array-domain: object is not an array: " obj)) |
520: | .02% | (Array-base-domain obj))) |
521: | | |
522: | | (define (Array-accessor obj) |
523: | 0% | (or (and (not (Array? obj)) |
524: | | (error "Array-accessor: object is not an array: " obj)) |
525: | 0% | (Array-base-accessor obj))) |
526: | | |
527: | | (define (Array-lazy-curry array left-dimension) |
528: | | (or (and (not (Array? array)) |
529: | | (error "Array-lazy-curry: argument is not an array: " array left-dimension)) |
530: | | (and (not (exact-integer? left-dimension)) |
531: | | (error "Array-lazy-curry: argument is not an exact integer: " array left-dimension)) |
532: | | (and (not (< 0 left-dimension (##Interval-dimension (Array-domain array)))) |
533: | | (error "Array-lazy-curry: argument is not between 0 and (Interval-dimension (Array-domain array)) (exclusive): " array left-dimension)) |
534: | | (call-with-values |
535: | | (lambda () (Interval-curry (Array-domain array) left-dimension)) |
536: | | (lambda (left-interval right-interval) |
537: | | (let ((accessor (Array-accessor array))) |
538: | | (case (##Interval-dimension left-interval) |
539: | | ((1) (case (##Interval-dimension right-interval) |
540: | | ((1) (build-Array left-interval |
541: | | (lambda (i) (build-Array right-interval (lambda (j) (accessor i j)))))) |
542: | | ((2) (build-Array left-interval |
543: | | (lambda (i) (build-Array right-interval (lambda (j k) (accessor i j k)))))) |
544: | | ((3) (build-Array left-interval |
545: | | (lambda (i) (build-Array right-interval (lambda (j k l) (accessor i j k l)))))) |
546: | | (else (build-Array left-interval |
547: | | (lambda (i) (build-Array right-interval (lambda multi-index (apply accessor i multi-index)))))))) |
548: | | ((2) (case (##Interval-dimension right-interval) |
549: | | ((1) (build-Array left-interval |
550: | | (lambda (i j) (build-Array right-interval (lambda (k) (accessor i j k)))))) |
551: | | ((2) (build-Array left-interval |
552: | | (lambda (i j) (build-Array right-interval (lambda (k l) (accessor i j k l)))))) |
553: | | (else (build-Array left-interval |
554: | | (lambda (i j) (build-Array right-interval (lambda multi-index (apply accessor i j multi-index)))))))) |
555: | | ((3) (case (##Interval-dimension right-interval) |
556: | | ((1) (build-Array left-interval |
557: | | (lambda (i j k) (build-Array right-interval (lambda (l) (accessor i j k l)))))) |
558: | | (else (build-Array left-interval |
559: | | (lambda (i j k) (build-Array right-interval (lambda multi-index (apply accessor i j k multi-index)))))))) |
560: | | (else (build-Array left-interval |
561: | | (lambda (#!rest left-multi-index) |
562: | | (build-Array right-interval |
563: | | (lambda (#!rest right-multi-index) |
564: | | (apply accessor (append left-multi-index right-multi-index))))))))))))) |
565: | | |
566: | | (define (insert-arg-into-arg-list arg arg-list index) |
567: | | (define (helper arg-list i) |
568: | | (if (= i 0) |
569: | | (cons arg arg-list) |
570: | | (cons arg (helper (cdr arg-list) (- i 1))))) |
571: | | (helper arg-list index)) |
572: | | |
573: | | (define (Array-lazy-distinguish-one array index) |
574: | | (or (and (not (Array? array)) |
575: | | (error "Array-lazy-distinguish-one: argument is not an array: " array index)) |
576: | | (and (not (exact-integer? index)) |
577: | | (error "Array-lazy-distinguish-one: argument is not an exact integer: " array index)) |
578: | | (and (not (< 1 (##Interval-dimension (Array-domain array)))) |
579: | | (error "Array-lazy-distinguish-one: (Interval-dimension (Array-domain array)) is not greater than 1 : " array index)) |
580: | | (and (not (< -1 index (##Interval-dimension (Array-domain array)))) |
581: | | (error "Array-lazy-distinguish-one: argument is not between 0 (inclusive) and (Interval-dimension (Array-domain array)) (exclusive): " array index)) |
582: | | (call-with-values |
583: | | (lambda () (Interval-distinguish-one (Array-domain array) index)) |
584: | | (lambda (outer-interval inner-interval) |
585: | | (let ((accessor (Array-accessor array))) |
586: | | (case (##Interval-dimension outer-interval) |
587: | | ((1) (case index |
588: | | ((0) (build-Array outer-interval |
589: | | (lambda (j) (build-Array inner-interval (lambda (i) (accessor i j)))))) |
590: | | ((1) (build-Array outer-interval |
591: | | (lambda (i) (build-Array inner-interval (lambda (j) (accessor i j)))))))) |
592: | | ((2) (case index |
593: | | ((0) (build-Array outer-interval |
594: | | (lambda (j k) (build-Array inner-interval (lambda (i) (accessor i j k)))))) |
595: | | ((1) (build-Array outer-interval |
596: | | (lambda (i k) (build-Array inner-interval (lambda (j) (accessor i j k)))))) |
597: | | ((2) (build-Array outer-interval |
598: | | (lambda (i j) (build-Array inner-interval (lambda (k) (accessor i j k)))))))) |
599: | | ((3) (case index |
600: | | ((0) (build-Array outer-interval |
601: | | (lambda (j k l) (build-Array inner-interval (lambda (i) (accessor i j k l)))))) |
602: | | ((1) (build-Array outer-interval |
603: | | (lambda (i k l) (build-Array inner-interval (lambda (j) (accessor i j k l)))))) |
604: | | ((2) (build-Array outer-interval |
605: | | (lambda (i j l) (build-Array inner-interval (lambda (k) (accessor i j k l)))))) |
606: | | ((3) (build-Array outer-interval |
607: | | (lambda (i j k) (build-Array inner-interval (lambda (l) (accessor i j k l)))))))) |
608: | | (else (build-Array outer-interval |
609: | | (lambda (#!rest outer-index) |
610: | | (build-Array inner-interval |
611: | | (lambda (m) |
612: | | (apply accessor (insert-arg-into-arg-list m outer-index index))))))))))))) |
613: | | |
614: | | |
615: | | #| |
616: | | |
617: | | A Mutable array has, in addition a setter, that satisfies, roughly |
618: | | |
619: | | If (i_1, ..., i_n)\neq (j_1, ..., j_n) \in (Array-domain a) |
620: | | |
621: | | and |
622: | | |
623: | | ((Array-accessor a) j_1 ... j_n) => x |
624: | | |
625: | | then "after" |
626: | | |
627: | | ((Array-setter a) v i_1 ... i_n) |
628: | | |
629: | | we have |
630: | | |
631: | | ((Array-accessor a) j_1 ... j_n) => x |
632: | | |
633: | | and |
634: | | |
635: | | ((Array-accessor a) i_1 ... i_n) => v |
636: | | |
637: | | |# |
638: | | |
639: | | (define (build-Mutable-array domain accessor setter) |
640: | | (or (and (not (Interval? domain)) |
641: | | (error "build-Mutable-array: domain is not an interval: " domain)) |
642: | | (and (not (procedure? accessor)) |
643: | | (error "build-Mutable-array: accessor is not a procedure: " accessor)) |
644: | | (and (not (procedure? setter)) |
645: | | (error "build-Mutable-array: setter is not a procedure: " setter)) |
646: | | (make-Array-base domain |
647: | | accessor |
648: | | setter |
649: | | #f ; manipulators |
650: | | #f ; body |
651: | | #f ; indexer |
652: | | #f ; affine? |
653: | | ))) |
654: | | |
655: | | (define (Mutable-array? obj) |
656: | .06% | (and (Array? obj) |
657: | .17% | (not (eq? (Array-base-setter obj) #f)))) |
658: | | |
659: | | (define (Mutable-array-domain obj) |
660: | | (or (and (not (Mutable-array? obj)) |
661: | | (error "Mutable-array-domain: object is not an mutable array: " obj)) |
662: | | (Array-base-domain obj))) |
663: | | |
664: | | (define (Mutable-array-accessor obj) |
665: | | (or (and (not (Mutable-array? obj)) |
666: | | (error "Mutable-array-accessor: object is not an mutable array: " obj)) |
667: | | (Array-base-accessor obj))) |
668: | | |
669: | | (define (Mutable-array-setter obj) |
670: | .02% | (or (and (not (Mutable-array? obj)) |
671: | | (error "Mutable-array-setter: object is not an mutable array: " obj)) |
672: | .02% | (Array-base-setter obj))) |
673: | | |
674: | | (define (Mutable-array-lazy-curry array left-dimension) |
675: | | (declare (fixnum)) |
676: | | (or (and (not (Array? array)) |
677: | | (error "Mutable-array-lazy-curry: argument is not a Mutable-array: " array left-dimension)) |
678: | | (and (not (exact-integer? left-dimension)) |
679: | | (error "Mutable-array-lazy-curry: argument is not an exact integer: " array left-dimension)) |
680: | | (and (not (< 0 left-dimension (##Interval-dimension (Mutable-array-domain array)))) |
681: | | (error "Mutable-array-lazy-curry: argument is not between 0 and (Interval-dimension (Mutable-array-domain array)) (exclusive): " array left-dimension)) |
682: | | (call-with-values |
683: | | (lambda () (Interval-curry (Mutable-array-domain array) left-dimension)) |
684: | | (lambda (left-interval right-interval) |
685: | | (let ((accessor (Mutable-array-accessor array)) |
686: | | (setter (Mutable-array-setter array))) |
687: | | (case (##Interval-dimension left-interval) |
688: | | ((1) (case (##Interval-dimension right-interval) |
689: | | ((1) (build-Array left-interval |
690: | | (lambda (i) |
691: | | (build-Mutable-array right-interval |
692: | | (lambda (j) |
693: | | (accessor i j)) |
694: | | (lambda (v j) |
695: | | (setter v i j)))))) |
696: | | ((2) (build-Array left-interval |
697: | | (lambda (i) |
698: | | (build-Mutable-array right-interval |
699: | | (lambda (j k) |
700: | | (accessor i j k)) |
701: | | (lambda (v j k) |
702: | | (setter v i j k)))))) |
703: | | ((3) (build-Array left-interval |
704: | | (lambda (i) |
705: | | (build-Mutable-array right-interval |
706: | | (lambda (j k l) |
707: | | (accessor i j k l)) |
708: | | (lambda (v j k l) |
709: | | (setter v i j k l)))))) |
710: | | (else (build-Array left-interval |
711: | | (lambda (i) |
712: | | (build-Mutable-array right-interval |
713: | | (lambda (#!rest multi-index) |
714: | | (apply accessor i multi-index)) |
715: | | (lambda (v #!rest multi-index) |
716: | | (apply setter v i multi-index)))))))) |
717: | | ((2) (case (##Interval-dimension right-interval) |
718: | | ((1) (build-Array left-interval |
719: | | (lambda (i j) |
720: | | (build-Mutable-array right-interval |
721: | | (lambda (k) |
722: | | (accessor i j k)) |
723: | | (lambda (v k) |
724: | | (setter v i j k)))))) |
725: | | ((2) (build-Array left-interval |
726: | | (lambda (i j) |
727: | | (build-Mutable-array right-interval |
728: | | (lambda (k l) |
729: | | (accessor i j k l)) |
730: | | (lambda (v k l) |
731: | | (setter v i j k l)))))) |
732: | | (else (build-Array left-interval |
733: | | (lambda (i j) |
734: | | (build-Mutable-array right-interval |
735: | | (lambda (#!rest multi-index) |
736: | | (apply accessor i j multi-index)) |
737: | | (lambda (v #!rest multi-index) |
738: | | (apply setter v i j multi-index)))))))) |
739: | | ((3) (case (##Interval-dimension right-interval) |
740: | | ((1) (build-Array left-interval |
741: | | (lambda (i j k) |
742: | | (build-Mutable-array right-interval |
743: | | (lambda (l) |
744: | | (accessor i j k l)) |
745: | | (lambda (v l) |
746: | | (setter v i j k l)))))) |
747: | | (else (build-Array left-interval |
748: | | (lambda (i j k) |
749: | | (build-Mutable-array right-interval |
750: | | (lambda (#!rest multi-index) |
751: | | (apply accessor i j k multi-index)) |
752: | | (lambda (v #!rest multi-index) |
753: | | (apply setter v i j k multi-index)))))))) |
754: | | (else (build-Array left-interval |
755: | | (lambda (#!rest left-multi-index) |
756: | | (build-Mutable-array right-interval |
757: | | (lambda (#!rest right-multi-index) |
758: | | (apply accessor (append left-multi-index right-multi-index))) |
759: | | (lambda (v #!rest right-multi-index) |
760: | | (apply setter v (append left-multi-index right-multi-index))))))))))))) |
761: | | |
762: | | (define (Mutable-array-lazy-distinguish-one array index) |
763: | | (or (and (not (Mutable-array? array)) |
764: | | (error "Mutable-array-lazy-distinguish-one: argument is not an array: " array index)) |
765: | | (and (not (exact-integer? index)) |
766: | | (error "Mutable-array-lazy-distinguish-one: argument is not an exact integer: " array index)) |
767: | | (and (not (< 1 (##Interval-dimension (Array-domain array)))) |
768: | | (error "Mutable-array-lazy-distinguish-one: (Interval-dimension (Array-domain array)) is not greater than 1 : " array index)) |
769: | | (and (not (< -1 index (##Interval-dimension (Array-domain array)))) |
770: | | (error "Mutable-array-lazy-distinguish-one: argument is not between 0 (inclusive) and (Interval-dimension (Array-domain array)) (exclusive): " array index)) |
771: | | (call-with-values |
772: | | (lambda () (Interval-distinguish-one (Array-domain array) index)) |
773: | | (lambda (outer-interval inner-interval) |
774: | | (let ((accessor (Mutable-array-accessor array)) |
775: | | (setter (Mutable-array-setter array))) |
776: | | (case (##Interval-dimension outer-interval) |
777: | | ((1) (case index |
778: | | ((0) (build-Array outer-interval |
779: | | (lambda (j) (build-Mutable-array inner-interval |
780: | | (lambda ( i) (accessor i j)) |
781: | | (lambda (v i) (setter v i j)))))) |
782: | | ((1) (build-Array outer-interval |
783: | | (lambda (i) (build-Mutable-array inner-interval |
784: | | (lambda ( j) (accessor i j)) |
785: | | (lambda (v j) (setter v i j)))))))) |
786: | | ((2) (case index |
787: | | ((0) (build-Array outer-interval |
788: | | (lambda (j k) (build-Mutable-array inner-interval |
789: | | (lambda ( i) (accessor i j k)) |
790: | | (lambda (v i) (setter v i j k)))))) |
791: | | ((1) (build-Array outer-interval |
792: | | (lambda (i k) (build-Mutable-array inner-interval |
793: | | (lambda ( j) (accessor i j k)) |
794: | | (lambda (v j) (setter v i j k)))))) |
795: | | ((2) (build-Array outer-interval |
796: | | (lambda (i j) (build-Mutable-array inner-interval |
797: | | (lambda ( k) (accessor i j k)) |
798: | | (lambda (v k) (setter v i j k)))))))) |
799: | | ((3) (case index |
800: | | ((0) (build-Array outer-interval |
801: | | (lambda (j k l) (build-Mutable-array inner-interval |
802: | | (lambda ( i) (accessor i j k l)) |
803: | | (lambda (v i) (setter v i j k l)))))) |
804: | | ((1) (build-Array outer-interval |
805: | | (lambda (i k l) (build-Mutable-array inner-interval |
806: | | (lambda ( j) (accessor i j k l)) |
807: | | (lambda (v j) (setter v i j k l)))))) |
808: | | ((2) (build-Array outer-interval |
809: | | (lambda (i j l) (build-Mutable-array inner-interval |
810: | | (lambda ( k) (accessor i j k l)) |
811: | | (lambda (v k) (setter v i j k l)))))) |
812: | | ((3) (build-Array outer-interval |
813: | | (lambda (i j k) (build-Mutable-array inner-interval |
814: | | (lambda ( l) (accessor i j k l)) |
815: | | (lambda (v l) (setter v i j k l)))))))) |
816: | | (else (build-Array outer-interval |
817: | | (lambda (#!rest outer-index) |
818: | | (build-Array inner-interval |
819: | | (lambda ( m) |
820: | | (apply accessor (insert-arg-into-arg-list m outer-index index))) |
821: | | (lambda (v m) |
822: | | (apply setter v (insert-arg-into-arg-list m outer-index index))))))))))))) |
823: | | |
824: | | |
825: | | #| |
826: | | |
827: | | Fixed-array-manipulators contains functions and objects to manipulate the |
828: | | backing store of a Fixed-array. |
829: | | |
830: | | accessor: (lambda (body i) ...) returns the value of body at index i |
831: | | setter: (lambda (body i v) ...) sets the value of body at index i to v |
832: | | maker: (lambda (n) ...) makes a body of length n |
833: | | length: (lambda (body) ...) returns the number of objects in body |
834: | | default: object is the default value with which to fill body |
835: | | |
836: | | |# |
837: | | |
838: | .03% | (define-structure Fixed-array-manipulators accessor setter maker length default) |
839: | | |
840: | | #| |
841: | | We define specialized array manipulators for: |
842: | | |
843: | | 32- and 64-bit floating-point numbers, |
844: | | 8-, 16-, 32-, and 64-bit signed integers, |
845: | | 8-, 16-, 32-, and 64-bit unsigned integers, and |
846: | | 1-bit unsigned integers |
847: | | |
848: | | as well as generic objects. |
849: | | |# |
850: | | |
851: | | (define-macro (make-array-manipulators) |
852: | | |
853: | | (define (symbol-concatenate . symbols) |
854: | | (string->symbol (apply string-append (map (lambda (s) |
855: | | (if (string? s) |
856: | | s |
857: | | (symbol->string s))) |
858: | | symbols)))) |
859: | | |
860: | | `(begin |
861: | | ,@(map (lambda (name prefix default) |
862: | | `(define ,(symbol-concatenate name '-array-manipulators) |
863: | | (make-Fixed-array-manipulators |
864: | | ;; accessor: |
865: | | (lambda (v i) |
866: | | (,(symbol-concatenate prefix 'vector-ref) v i)) |
867: | | ;; setter: |
868: | | (lambda (v i val) |
869: | | (,(symbol-concatenate prefix 'vector-set!) v i val)) |
870: | | ;; maker: |
871: | | ,(symbol-concatenate 'make- prefix 'vector) |
872: | | ;; length: |
873: | | ,(symbol-concatenate prefix 'vector-length) |
874: | | ;; default: |
875: | | ,default))) |
876: | | '(generic s8 u8 s16 u16 s32 u32 s64 u64 f32 f64) |
877: | | '("" s8 u8 s16 u16 s32 u32 s64 u64 f32 f64) |
878: | | '(#f 0 0 0 0 0 0 0 0 0.0 0.0)))) |
879: | | |
880: | 6.86% | (make-array-manipulators) |
881: | | |
882: | | ;;; for bit-arrays, body is a vector, the first element of which is the actual number of elements, |
883: | | ;;; the second element of which is a u16vector that contains the bit string |
884: | | |
885: | | (define u1-array-manipulators |
886: | | (make-Fixed-array-manipulators |
887: | | ;; accessor: |
888: | | (lambda (v i) |
889: | | (let ((index (##fixnum.arithmetic-shift-right i 4)) |
890: | | (shift (##fixnum.bitwise-and i 15)) |
891: | | (bodyv (vector-ref v 1))) |
892: | | (##fixnum.bitwise-and |
893: | | (##fixnum.arithmetic-shift-right |
894: | | (u16vector-ref bodyv index) |
895: | | shift) |
896: | | 1))) |
897: | | ;; setter: |
898: | | (lambda (v i val) |
899: | | (let ((index (##fixnum.arithmetic-shift-right i 4)) |
900: | | (shift (##fixnum.bitwise-and i 15)) |
901: | | (bodyv (vector-ref v 1))) |
902: | | (u16vector-set! bodyv index (##fixnum.bitwise-ior |
903: | | (##fixnum.arithmetic-shift-left val shift) |
904: | | (##fixnum.bitwise-and |
905: | | (u16vector-ref bodyv index) |
906: | | (##fixnum.bitwise-not |
907: | | (##fixnum.arithmetic-shift-left 1 shift))))))) |
908: | | ;; maker: |
909: | | (lambda (size initializer) |
910: | | (let ((u16-size (##fixnum.arithmetic-shift-right (+ size 15) 4))) |
911: | | (vector size (make-u16vector u16-size (if (zero? initializer) 0 65535))))) |
912: | | ;; length: |
913: | | (lambda (v) |
914: | | (vector-ref v 0)) |
915: | | ;; default: |
916: | | 0)) |
917: | | |
918: | | #| |
919: | | |
920: | | Conceptually, an indexer is itself a 1-1 Array that maps one interval to another; thus, it is |
921: | | an example of an array that can return multiple values. |
922: | | |
923: | | Rather than trying to formalize this idea, and trying to get it to work with Array-map, |
924: | | Array-reduce, ..., we'll just manipulate the accessor functions of these conceptual Arrays. |
925: | | |
926: | | Affine indexers are 1-1 affine maps from one interval to another. |
927: | | |
928: | | The indexer field of a Fixed-array obj is a 1-1 mapping from |
929: | | |
930: | | (Array-domain obj) |
931: | | |
932: | | to [0, top), where top is |
933: | | |
934: | | ((Fixed-array-manipulators-length (Fixed-array-manipulators obj)) (Fixed-array-body obj)) |
935: | | |
936: | | |# |
937: | | |
938: | | #| |
939: | | |
940: | | build-affine-indexer specializes |
941: | | |
942: | | (define (my-build-indexer base lower-bounds increments) |
943: | | (lambda multi-index |
944: | | (apply + base (map * increments (map - multi-index lower-bounds))))) |
945: | | |
946: | | |# |
947: | | |
948: | | (define (build-affine-indexer base lower-bounds increments) |
949: | | (case (length lower-bounds) |
950: | | ((1) (build-indexer-1 base |
951: | | (car lower-bounds) |
952: | | (car increments))) |
953: | | ((2) (build-indexer-2 base |
954: | | (car lower-bounds) (cadr lower-bounds) |
955: | | (car increments) (cadr increments))) |
956: | | ((3) (build-indexer-3 base |
957: | | (car lower-bounds) (cadr lower-bounds) (caddr lower-bounds) |
958: | | (car increments) (cadr increments) (caddr increments))) |
959: | | ((4) (build-indexer-4 base |
960: | | (car lower-bounds) (cadr lower-bounds) (caddr lower-bounds) (cadddr lower-bounds) |
961: | | (car increments) (cadr increments) (caddr increments) (cadddr increments))) |
962: | | (else (build-indexer-generic base lower-bounds increments)))) |
963: | | |
964: | | ;; unfortunately, the next two functions were written by hand, so beware of bugs. |
965: | | |
966: | | (define (build-indexer-1 base |
967: | | low-0 |
968: | | increment-0) |
969: | .02% | (if (zero? base) |
970: | | (if (zero? low-0) |
971: | | (cond ((= 1 increment-0) (lambda (i) i)) |
972: | | ((= -1 increment-0) (lambda (i) (- i))) |
973: | | (else (lambda (i) (* i increment-0)))) |
974: | | (cond ((= 1 increment-0) (lambda (i) (- i low-0))) |
975: | | ((= -1 increment-0) (lambda (i) (- low-0 i))) |
976: | | (else (lambda (i) (* increment-0 (- i low-0)))))) |
977: | .01% | (if (zero? low-0) |
978: | .73% | (cond ((= 1 increment-0) (lambda (i) (+ base i))) |
979: | | ((= -1 increment-0) (lambda (i) (- base i))) |
980: | | (else (lambda (i) (+ base (* increment-0 i))))) |
981: | | (cond ((= 1 increment-0) (lambda (i) (+ base (- i low-0)))) |
982: | | ((= -1 increment-0) (lambda (i) (+ base (- low-0 i)))) |
983: | | (else (lambda (i) (+ base (* increment-0 (- i low-0))))))))) |
984: | | |
985: | | (define (build-indexer-2 base |
986: | | low-0 low-1 |
987: | | increment-0 increment-1) |
988: | 0% | (if (zero? base) |
989: | | (if (zero? low-0) |
990: | | (cond ((= 1 increment-0) |
991: | | (if (zero? low-1) |
992: | | (cond ((= 1 increment-1) (lambda (i j) (+ i j))) |
993: | | ((= -1 increment-1) (lambda (i j) (+ i (- j)))) |
994: | | (else (lambda (i j) (+ i (* increment-1 j))))) |
995: | | (cond ((= 1 increment-1) (lambda (i j) (+ i (- j low-1)))) |
996: | | ((= -1 increment-1) (lambda (i j) (+ i (- low-1 j)))) |
997: | | (else (lambda (i j) (+ i (* increment-1 (- j low-1)))))))) |
998: | | ((= -1 increment-0) |
999: | | (if (zero? low-1) |
1000: | | (cond ((= 1 increment-1) (lambda (i j) (- j i))) |
1001: | | ((= -1 increment-1) (lambda (i j) (- (- j) i))) |
1002: | | (else (lambda (i j) (- (* increment-1 j) i)))) |
1003: | | (cond ((= 1 increment-1) (lambda (i j) (- (- j low-1) i))) |
1004: | | ((= -1 increment-1) (lambda (i j) (- (- low-1 j) i))) |
1005: | | (else (lambda (i j) (- (* increment-1 (- j low-1)) i)))))) |
1006: | | (else |
1007: | | (if (zero? low-1) |
1008: | .05% | (cond ((= 1 increment-1) (lambda (i j) (+ (* increment-0 i) j))) |
1009: | | ((= -1 increment-1) (lambda (i j) (+ (* increment-0 i) (- j)))) |
1010: | | (else (lambda (i j) (+ (* increment-0 i) (* increment-1 j))))) |
1011: | | (cond ((= 1 increment-1) (lambda (i j) (+ (* increment-0 i) (- j low-1)))) |
1012: | | ((= -1 increment-1) (lambda (i j) (+ (* increment-0 i) (- low-1 j)))) |
1013: | | (else (lambda (i j) (+ (* increment-0 i) (* increment-1 (- j low-1))))))))) |
1014: | | (cond ((= 1 increment-0) |
1015: | | (if (zero? low-1) |
1016: | | (cond ((= 1 increment-1) (lambda (i j) (+ (- i low-0) j))) |
1017: | | ((= -1 increment-1) (lambda (i j) (+ (- i low-0) (- j)))) |
1018: | | (else (lambda (i j) (+ (- i low-0) (* increment-1 j))))) |
1019: | | (cond ((= 1 increment-1) (lambda (i j) (+ (- i low-0) (- j low-1)))) |
1020: | | ((= -1 increment-1) (lambda (i j) (+ (- i low-0) (- low-1 j)))) |
1021: | | (else (lambda (i j) (+ (- i low-0) (* increment-1 (- j low-1)))))))) |
1022: | | ((= -1 increment-0) |
1023: | | (if (zero? low-1) |
1024: | | (cond ((= 1 increment-1) (lambda (i j) (- j (- i low-0)))) |
1025: | | ((= -1 increment-1) (lambda (i j) (- (- j) (- i low-0)))) |
1026: | | (else (lambda (i j) (- (* increment-1 j) (- i low-0))))) |
1027: | | (cond ((= 1 increment-1) (lambda (i j) (- (- j low-1) (- i low-0)))) |
1028: | | ((= -1 increment-1) (lambda (i j) (- (- low-1 j) (- i low-0)))) |
1029: | | (else (lambda (i j) (- (* increment-1 (- j low-1)) (- i low-0))))))) |
1030: | | (else |
1031: | | (if (zero? low-1) |
1032: | | (cond ((= 1 increment-1) (lambda (i j) (+ (* increment-0 (- i low-0)) j))) |
1033: | | ((= -1 increment-1) (lambda (i j) (+ (* increment-0 (- i low-0)) (- j)))) |
1034: | | (else (lambda (i j) (+ (* increment-0 (- i low-0)) (* increment-1 j))))) |
1035: | | (cond ((= 1 increment-1) (lambda (i j) (+ (* increment-0 (- i low-0)) (- j low-1)))) |
1036: | | ((= -1 increment-1) (lambda (i j) (+ (* increment-0 (- i low-0)) (- low-1 j)))) |
1037: | | (else (lambda (i j) (+ (* increment-0 (- i low-0)) (* increment-1 (- j low-1)))))))))) |
1038: | 0% | (if (zero? low-0) |
1039: | 0% | (cond ((= 1 increment-0) |
1040: | | (if (zero? low-1) |
1041: | | (cond ((= 1 increment-1) (lambda (i j) (+ base i j))) |
1042: | | ((= -1 increment-1) (lambda (i j) (+ base i (- j)))) |
1043: | | (else (lambda (i j) (+ base i (* increment-1 j))))) |
1044: | | (cond ((= 1 increment-1) (lambda (i j) (+ base i (- j low-1)))) |
1045: | | ((= -1 increment-1) (lambda (i j) (+ base i (- low-1 j)))) |
1046: | | (else (lambda (i j) (+ base i (* increment-1 (- j low-1)))))))) |
1047: | 0% | ((= -1 increment-0) |
1048: | | (if (zero? low-1) |
1049: | | (cond ((= 1 increment-1) (lambda (i j) (- (+ base j) i))) |
1050: | | ((= -1 increment-1) (lambda (i j) (- (- base j) i))) |
1051: | | (else (lambda (i j) (- (+ base (* increment-1 j)) i)))) |
1052: | | (cond ((= 1 increment-1) (lambda (i j) (- (+ base (- j low-1)) i))) |
1053: | | ((= -1 increment-1) (lambda (i j) (- (+ base (- low-1 j)) i))) |
1054: | | (else (lambda (i j) (- (+ base (* increment-1 (- j low-1))) i)))))) |
1055: | | (else |
1056: | 0% | (if (zero? low-1) |
1057: | 2.93% | (cond ((= 1 increment-1) (lambda (i j) (+ base (* increment-0 i) j))) |
1058: | | ((= -1 increment-1) (lambda (i j) (+ base (* increment-0 i) (- j)))) |
1059: | | (else (lambda (i j) (+ base (* increment-0 i) (* increment-1 j))))) |
1060: | | (cond ((= 1 increment-1) (lambda (i j) (+ base (* increment-0 i) (- j low-1)))) |
1061: | | ((= -1 increment-1) (lambda (i j) (+ base (* increment-0 i) (- low-1 j)))) |
1062: | | (else (lambda (i j) (+ base (* increment-0 i) (* increment-1 (- j low-1))))))))) |
1063: | | (cond ((= 1 increment-0) |
1064: | | (if (zero? low-1) |
1065: | | (cond ((= 1 increment-1) (lambda (i j) (+ base (- i low-0) j))) |
1066: | | ((= -1 increment-1) (lambda (i j) (+ base (- i low-0) (- j)))) |
1067: | | (else (lambda (i j) (+ base (- i low-0) (* increment-1 j))))) |
1068: | | (cond ((= 1 increment-1) (lambda (i j) (+ base (- i low-0) (- j low-1)))) |
1069: | | ((= -1 increment-1) (lambda (i j) (+ base (- i low-0) (- low-1 j)))) |
1070: | | (else (lambda (i j) (+ base (- i low-0) (* increment-1 (- j low-1)))))))) |
1071: | | ((= -1 increment-0) |
1072: | | (if (zero? low-1) |
1073: | | (cond ((= 1 increment-1) (lambda (i j) (- (+ base j) (- i low-0)))) |
1074: | | ((= -1 increment-1) (lambda (i j) (- (- base j) (- i low-0)))) |
1075: | | (else (lambda (i j) (- (+ base (* increment-1 j)) (- i low-0))))) |
1076: | | (cond ((= 1 increment-1) (lambda (i j) (- (+ base (- j low-1)) (- i low-0)))) |
1077: | | ((= -1 increment-1) (lambda (i j) (- (+ base (- low-1 j)) (- i low-0)))) |
1078: | | (else (lambda (i j) (- (+ base (* increment-1 (- j low-1))) (- i low-0))))))) |
1079: | | (else |
1080: | | (if (zero? low-1) |
1081: | | (cond ((= 1 increment-1) (lambda (i j) (+ base (* increment-0 (- i low-0)) j))) |
1082: | | ((= -1 increment-1) (lambda (i j) (+ base (* increment-0 (- i low-0)) (- j)))) |
1083: | | (else (lambda (i j) (+ base (* increment-0 (- i low-0)) (* increment-1 j))))) |
1084: | | (cond ((= 1 increment-1) (lambda (i j) (+ base (* increment-0 (- i low-0)) (- j low-1)))) |
1085: | | ((= -1 increment-1) (lambda (i j) (+ base (* increment-0 (- i low-0)) (- low-1 j)))) |
1086: | | (else (lambda (i j) (+ base (* increment-0 (- i low-0)) (* increment-1 (- j low-1)))))))))))) |
1087: | | |
1088: | | ;;; after this we basically punt |
1089: | | |
1090: | | (define (build-indexer-3 base |
1091: | | low-0 low-1 low-2 |
1092: | | increment-0 increment-1 increment-2) |
1093: | 0% | (if (= 0 low-0 low-1 low-2) |
1094: | | (if (= base 0) |
1095: | | (if (= increment-2 1) |
1096: | | (lambda (i j k) |
1097: | 1.04% | (+ (* increment-0 i) |
1098: | .61% | (* increment-1 j) |
1099: | .25% | k)) |
1100: | | (lambda (i j k) |
1101: | | (+ (* increment-0 i) |
1102: | | (* increment-1 j) |
1103: | | (* increment-2 k)))) |
1104: | | (if (= increment-2 1) |
1105: | | (lambda (i j k) |
1106: | .55% | (+ base |
1107: | .48% | (* increment-0 i) |
1108: | .57% | (* increment-1 j) |
1109: | .22% | k)) |
1110: | | (lambda (i j k) |
1111: | | (+ base |
1112: | | (* increment-0 i) |
1113: | | (* increment-1 j) |
1114: | | (* increment-2 k))))) |
1115: | | (if (= base 0) |
1116: | | (if (= increment-2 1) |
1117: | | (lambda (i j k) |
1118: | | (+ (* increment-0 (- i low-0)) |
1119: | | (* increment-1 (- j low-1)) |
1120: | | (- k low-2))) |
1121: | | (lambda (i j k) |
1122: | | (+ (* increment-0 (- i low-0)) |
1123: | | (* increment-1 (- j low-1)) |
1124: | | (* increment-2 (- k low-2))))) |
1125: | | (if (= increment-2 1) |
1126: | | (lambda (i j k) |
1127: | | (+ base |
1128: | | (* increment-0 (- i low-0)) |
1129: | | (* increment-1 (- j low-1)) |
1130: | | (- k low-2))) |
1131: | | (lambda (i j k) |
1132: | | (+ base |
1133: | | (* increment-0 (- i low-0)) |
1134: | | (* increment-1 (- j low-1)) |
1135: | | (* increment-2 (- k low-2)))))))) |
1136: | | |
1137: | | (define (build-indexer-4 base |
1138: | | low-0 low-1 low-2 low-3 |
1139: | | increment-0 increment-1 increment-2 increment-3) |
1140: | | (if (= 0 low-0 low-1 low-2 low-3) |
1141: | | (if (= base 0) |
1142: | | (if (= increment-3 1) |
1143: | | (lambda (i j k l) |
1144: | 3.86% | (+ (* increment-0 i) |
1145: | 1.23% | (* increment-1 j) |
1146: | 1.19% | (* increment-2 k) |
1147: | .46% | l)) |
1148: | | (lambda (i j k l) |
1149: | | (+ (* increment-0 i) |
1150: | | (* increment-1 j) |
1151: | | (* increment-2 k) |
1152: | | (* increment-3 l)))) |
1153: | | (if (= increment-3 1) |
1154: | | (lambda (i j k l) |
1155: | | (+ base |
1156: | | (* increment-0 i) |
1157: | | (* increment-1 j) |
1158: | | (* increment-2 k) |
1159: | | l)) |
1160: | | (lambda (i j k l) |
1161: | | (+ base |
1162: | | (* increment-0 i) |
1163: | | (* increment-1 j) |
1164: | | (* increment-2 k) |
1165: | | (* increment-3 l))))) |
1166: | | (if (= base 0) |
1167: | | (if (= increment-3 1) |
1168: | | (lambda (i j k l) |
1169: | | (+ (* increment-0 (- i low-0)) |
1170: | | (* increment-1 (- j low-1)) |
1171: | | (* increment-2 (- k low-2)) |
1172: | | (- l low-3))) |
1173: | | (lambda (i j k l) |
1174: | | (+ (* increment-0 (- i low-0)) |
1175: | | (* increment-1 (- j low-1)) |
1176: | | (* increment-2 (- k low-2)) |
1177: | | (* increment-3 (- l low-3))))) |
1178: | | (if (= increment-3 1) |
1179: | | (lambda (i j k l) |
1180: | | (+ base |
1181: | | (* increment-0 (- i low-0)) |
1182: | | (* increment-1 (- j low-1)) |
1183: | | (* increment-2 (- k low-2)) |
1184: | | (- l low-3))) |
1185: | | (lambda (i j k l) |
1186: | | (+ base |
1187: | | (* increment-0 (- i low-0)) |
1188: | | (* increment-1 (- j low-1)) |
1189: | | (* increment-2 (- k low-2)) |
1190: | | (* increment-3 (- l low-3)))))))) |
1191: | | |
1192: | | (define (build-indexer-generic base lower-bounds increments) |
1193: | | (lambda multi-index |
1194: | | (do ((multi-index multi-index (cdr multi-index)) |
1195: | | (lower-bounds lower-bounds (cdr lower-bounds)) |
1196: | | (increments increments (cdr increments)) |
1197: | | (result base (+ result (* (car increments) |
1198: | | (- (car multi-index) |
1199: | | (car lower-bounds)))))) |
1200: | | ((null? multi-index) result)))) |
1201: | | |
1202: | | |
1203: | | (define (affine-indexer= indexer1 indexer2 interval) |
1204: | | (or (and (not (Interval? interval)) |
1205: | | (error "affine-indexer=: argument is not an interval " interval)) |
1206: | | (and (not (procedure? indexer1)) |
1207: | | (error "affine-indexer=: argument is not a procedure " indexer1)) |
1208: | | (and (not (procedure? indexer2)) |
1209: | | (error "affine-indexer=: argument is not a procedure " indexer2)) |
1210: | | (let ((lower-bounds (Interval-lower-bounds->list interval)) |
1211: | | (upper-bounds (Interval-upper-bounds->list interval))) |
1212: | | (let ((multi-index (map (lambda (x) x) lower-bounds))) |
1213: | | (let outer ((i multi-index) |
1214: | | (l lower-bounds) |
1215: | | (u upper-bounds)) |
1216: | | (and (= (apply indexer1 multi-index) |
1217: | | (apply indexer2 multi-index)) |
1218: | | (or (null? i) |
1219: | | (begin |
1220: | | (if (< (+ 1 (car l)) (car u)) |
1221: | | (set-car! i (+ (car i) 1))) |
1222: | | (outer (cdr i) (cdr l) (cdr u)))))))))) |
1223: | | |
1224: | | (define (generic-indexer= indexer1 indexer2 interval) |
1225: | | (or (and (not (Interval? interval)) |
1226: | | (error "generic-indexer=: argument is not an interval " interval)) |
1227: | | (and (not (procedure? indexer1)) |
1228: | | (error "generic-indexer=: argument is not a procedure " indexer1)) |
1229: | | (and (not (procedure? indexer2)) |
1230: | | (error "generic-indexer=: argument is not a procedure " indexer2)) |
1231: | | (Interval-reduce (lambda multi-index |
1232: | | (= (apply indexer1 multi-index) |
1233: | | (apply indexer2 multi-index))) |
1234: | | (lambda (x y) (and x y)) |
1235: | | #t |
1236: | | interval))) |
1237: | | |
1238: | | #| |
1239: | | |
1240: | | The default accessor and the setter of a Fixed-array a are given by |
1241: | | |
1242: | | (lambda (i_0 ... i_n-1) |
1243: | | ((Fixed-array-manipulators-accessor a) |
1244: | | (Fixed-array-body a) |
1245: | | ((Fixed-array-indexer a) i_0 ... i_n-1))) |
1246: | | |
1247: | | (lambda (v i_0 ... i_n-1) |
1248: | | ((Fixed-array-manipulators-setter a) |
1249: | | (Fixed-array-body a) |
1250: | | ((Fixed-array-indexer a) i_0 ... i_n-1) |
1251: | | v)) |
1252: | | |
1253: | | The default initializer-value is |
1254: | | |
1255: | | (Fixed-array-manipulators-default manipulators) |
1256: | | |
1257: | | The default body is |
1258: | | |
1259: | | ((Fixed-array-manipulators-maker manipulators) |
1260: | | (Interval-volume domain) |
1261: | | initializer-value) |
1262: | | |
1263: | | The default indexer is the mapping of |
1264: | | the domain to the natural numbers in lexicographical order. |
1265: | | |
1266: | | |# |
1267: | | |
1268: | | (define (Fixed-array? obj) |
1269: | .05% | (and (Mutable-array? obj) |
1270: | .13% | (not (eq? (Array-base-body obj) #f)))) |
1271: | | |
1272: | | (define (Fixed-array-domain obj) |
1273: | | (or (and (not (Fixed-array? obj)) |
1274: | | (error "Fixed-array-domain: object is not an mutable array: " obj)) |
1275: | | (Array-base-domain obj))) |
1276: | | |
1277: | | (define (Fixed-array-accessor obj) |
1278: | | (or (and (not (Fixed-array? obj)) |
1279: | | (error "Fixed-array-accessor: object is not an mutable array: " obj)) |
1280: | | (Array-base-accessor obj))) |
1281: | | |
1282: | | (define (Fixed-array-setter obj) |
1283: | | (or (and (not (Fixed-array? obj)) |
1284: | | (error "Fixed-array-setter: object is not an mutable array: " obj)) |
1285: | | (Array-base-setter obj))) |
1286: | | |
1287: | | (define (Fixed-array-body obj) |
1288: | .02% | (or (and (not (Fixed-array? obj)) |
1289: | | (error "Fixed-array-body: argument is not a fixed array: " obj)) |
1290: | .02% | (Array-base-body obj))) |
1291: | | |
1292: | | (define (Fixed-array-indexer obj) |
1293: | .02% | (or (and (not (Fixed-array? obj)) |
1294: | | (error "Fixed-array-indexer: argument is not a fixed array: " obj)) |
1295: | .02% | (Array-base-indexer obj))) |
1296: | | |
1297: | | (define (Fixed-array-manipulators obj) |
1298: | .01% | (or (and (not (Fixed-array? obj)) |
1299: | | (error "Fixed-array-manipulators: argument is not a fixed array: " obj)) |
1300: | .02% | (Array-base-manipulators obj))) |
1301: | | |
1302: | | (define (Fixed-array-affine? obj) |
1303: | .02% | (or (and (not (Fixed-array? obj)) |
1304: | | (error "Fixed-array-affine?: argument is not a fixed array: " obj)) |
1305: | .02% | (Array-base-affine? obj))) |
1306: | | |
1307: | | (define (##finish-Fixed-array domain manipulators body indexer affine?) |
1308: | .04% | (let ((accessor (let ((manipulator-accessor (Fixed-array-manipulators-accessor manipulators)) |
1309: | 0% | (indexer indexer) |
1310: | 0% | (body body)) |
1311: | .02% | (case (##Interval-dimension domain) |
1312: | .01% | ((1) (lambda (i) (manipulator-accessor body (indexer i)))) |
1313: | 1.07% | ((2) (lambda (i j) (manipulator-accessor body (indexer i j)))) |
1314: | 2.24% | ((3) (lambda (i j k) (manipulator-accessor body (indexer i j k)))) |
1315: | 2.19% | ((4) (lambda (i j k l) (manipulator-accessor body (indexer i j k l)))) |
1316: | | (else (lambda multi-index (manipulator-accessor body (apply indexer multi-index))))))) |
1317: | .02% | (setter (let ((manipulator-setter (Fixed-array-manipulators-setter manipulators)) |
1318: | 0% | (indexer indexer) |
1319: | 0% | (body body)) |
1320: | .02% | (case (##Interval-dimension domain) |
1321: | 1.35% | ((1) (lambda (value i) (manipulator-setter body (indexer i) value))) |
1322: | 1.53% | ((2) (lambda (value i j) (manipulator-setter body (indexer i j) value))) |
1323: | .06% | ((3) (lambda (value i j k) (manipulator-setter body (indexer i j k) value))) |
1324: | 2.87% | ((4) (lambda (value i j k l) (manipulator-setter body (indexer i j k l) value))) |
1325: | | (else (lambda (value . multi-index) (manipulator-setter body (apply indexer multi-index) value))))))) |
1326: | .02% | (make-Array-base domain |
1327: | 0% | accessor |
1328: | 0% | setter |
1329: | 0% | manipulators |
1330: | 0% | body |
1331: | 0% | indexer |
1332: | 0% | affine?))) |
1333: | | |
1334: | | |
1335: | | (define (build-Fixed-array #!key |
1336: | | (domain (macro-absent-obj)) |
1337: | | (manipulators (macro-absent-obj)) |
1338: | | (body (macro-absent-obj)) |
1339: | | (indexer (macro-absent-obj)) |
1340: | | (initializer-value (macro-absent-obj)) |
1341: | | (affine? (macro-absent-obj))) |
1342: | | |
1343: | | (or (and (eq? (macro-absent-obj) domain) |
1344: | | (error "build-Fixed-array: the domain must be given: " domain)) |
1345: | | (and (not (Interval? domain)) |
1346: | | (error "build-Fixed-array: domain is not an interval: " domain)) |
1347: | | (and (eq? (macro-absent-obj) manipulators) |
1348: | | (error "build-Fixed-array: the manipulators must be given: " manipulators)) |
1349: | | (and (not (Fixed-array-manipulators? manipulators)) |
1350: | | (error "build-Fixed-array: manipulators are not fixed-array-manipulators: " manipulators)) |
1351: | | (and (not (eq? (macro-absent-obj) indexer)) |
1352: | | (not (procedure? indexer)) |
1353: | | (error "build-Fixed-array: indexer is not a procedure: " indexer)) |
1354: | | (and (and (not (eq? affine? (macro-absent-obj))) |
1355: | | (not (boolean? affine?))) |
1356: | | (error "build-Fixed-array: affine? must be a boolean: " affine?)) |
1357: | | (and (and (not (eq? body (macro-absent-obj))) |
1358: | | (not (eq? initializer-value (macro-absent-obj)))) |
1359: | | (error "build-Fixed-array: you can not pass both body and initializer-value as arguments " body initializer-value)) |
1360: | 0% | (let* ((affine? (if (boolean? affine?) |
1361: | | affine? |
1362: | | (eq? indexer (macro-absent-obj)))) |
1363: | | (initializer-value (if (eq? initializer-value (macro-absent-obj)) |
1364: | | (Fixed-array-manipulators-default manipulators) |
1365: | | initializer-value)) |
1366: | | (body (if (eq? body (macro-absent-obj)) |
1367: | | ((Fixed-array-manipulators-maker manipulators) (Interval-volume domain) initializer-value) |
1368: | | body)) |
1369: | | (indexer (if (eq? indexer (macro-absent-obj)) |
1370: | | (case (Interval-dimension domain) |
1371: | | ((1) (let ((low-0 (Interval-lower-bound domain 0)) |
1372: | | (increment-0 1)) |
1373: | | (build-indexer-1 0 low-0 increment-0))) |
1374: | | ((2) (let* ((low-0 (##Interval-lower-bound domain 0)) |
1375: | | (low-1 (##Interval-lower-bound domain 1)) |
1376: | | (increment-1 1) |
1377: | | (increment-0 (* increment-1 |
1378: | | (- (##Interval-upper-bound domain 1) |
1379: | | (##Interval-lower-bound domain 1))))) |
1380: | | (build-indexer-2 0 |
1381: | | low-0 low-1 |
1382: | | increment-0 increment-1))) |
1383: | | ((3) (let* ((low-0 (##Interval-lower-bound domain 0)) |
1384: | | (low-1 (##Interval-lower-bound domain 1)) |
1385: | | (low-2 (##Interval-lower-bound domain 2)) |
1386: | | (increment-2 1) |
1387: | | (increment-1 (* increment-2 |
1388: | | (- (##Interval-upper-bound domain 2) |
1389: | | (##Interval-lower-bound domain 2)))) |
1390: | | (increment-0 (* increment-1 |
1391: | | (- (##Interval-upper-bound domain 1) |
1392: | | (##Interval-lower-bound domain 1))))) |
1393: | | (build-indexer-3 0 |
1394: | | low-0 low-1 low-2 |
1395: | | increment-0 increment-1 increment-2))) |
1396: | | ((4) (let* ((low-0 (##Interval-lower-bound domain 0)) |
1397: | | (low-1 (##Interval-lower-bound domain 1)) |
1398: | | (low-2 (##Interval-lower-bound domain 2)) |
1399: | | (low-3 (##Interval-lower-bound domain 3)) |
1400: | | (increment-3 1) |
1401: | | (increment-2 (* increment-3 |
1402: | | (- (##Interval-upper-bound domain 3) |
1403: | | (##Interval-lower-bound domain 3)))) |
1404: | | (increment-1 (* increment-2 |
1405: | | (- (##Interval-upper-bound domain 2) |
1406: | | (##Interval-lower-bound domain 2)))) |
1407: | | (increment-0 (* increment-1 |
1408: | | (- (##Interval-upper-bound domain 1) |
1409: | | (##Interval-lower-bound domain 1))))) |
1410: | | (build-indexer-4 0 |
1411: | | low-0 low-1 low-2 low-3 |
1412: | | increment-0 increment-1 increment-2 increment-3))) |
1413: | | (else |
1414: | | (let ((lower-bounds (##Interval-lower-bounds->list domain)) |
1415: | | (upper-bounds (##Interval-upper-bounds->list domain))) |
1416: | | (let ((ranges (map (lambda (u l) (- u l)) upper-bounds lower-bounds))) |
1417: | | (do ((ranges (reverse ranges) (cdr ranges)) |
1418: | | (increments (list 1) (cons (* (car increments) (car ranges)) |
1419: | | increments))) |
1420: | | ((null? (cdr ranges)) (build-indexer-generic 0 lower-bounds increments))))))) |
1421: | | indexer))) |
1422: | | (##finish-Fixed-array domain |
1423: | | manipulators |
1424: | | body |
1425: | | indexer |
1426: | | affine?)))) |
1427: | | |
1428: | | #| |
1429: | | |
1430: | | The domain of the result is the same as the domain of the argument. |
1431: | | |
1432: | | Builds a new Fixed-array and populates the body of the result in |
1433: | | lexicographical order of the domain. |
1434: | | |
1435: | | |# |
1436: | | |
1437: | | (define (Array->Fixed-array result-manipulators array) |
1438: | | (or (and (not (Array? array)) |
1439: | | (error "Array->Fixed-array: Argument is not an array: " array)) |
1440: | | (and (not (Fixed-array-manipulators? result-manipulators)) |
1441: | | (error "Array->Fixed-array: Argument is not a set of fixed-array-manipulators: " result-manipulators)) |
1442: | | (let ((domain (Array-domain array))) |
1443: | | (let ((result (build-Fixed-array |
1444: | | domain: domain |
1445: | | manipulators: result-manipulators))) |
1446: | | (let ((range-setter (Mutable-array-setter result)) |
1447: | | (domain-accessor (Array-accessor array))) |
1448: | | (Interval-for-each (case (##Interval-dimension domain) |
1449: | | ((1) (lambda (i) (range-setter (domain-accessor i) i))) |
1450: | .02% | ((2) (lambda (i j) (range-setter (domain-accessor i j) i j))) |
1451: | .03% | ((3) (lambda (i j k) (range-setter (domain-accessor i j k) i j k))) |
1452: | 3.28% | ((4) (lambda (i j k l) (range-setter (domain-accessor i j k l) i j k l))) |
1453: | | (else (lambda multi-index |
1454: | | (apply range-setter (apply domain-accessor multi-index) multi-index)))) |
1455: | | domain) |
1456: | | result))))) |
1457: | | |
1458: | | #| |
1459: | | |
1460: | | In the next function, old-indexer is an affine 1-1 mapping from an interval to [0,N), for some N. |
1461: | | |
1462: | | new-domain->old-domain is an affine 1-1 mapping from new-domain to the domain of old-indexer. |
1463: | | |
1464: | | |# |
1465: | | |
1466: | | (define (compose-affine-indexers old-indexer new-domain new-domain->old-domain) |
1467: | .02% | (case (##Interval-dimension new-domain) |
1468: | .07% | ((1) (let* ((lower-0 (##Interval-lower-bound new-domain 0)) |
1469: | .01% | (upper-0 (##Interval-upper-bound new-domain 0)) |
1470: | 0% | (base (call-with-values |
1471: | .02% | (lambda () (new-domain->old-domain lower-0)) |
1472: | 0% | old-indexer)) |
1473: | .02% | (increment-0 (if (< (+ lower-0 1) upper-0) |
1474: | .01% | (- (call-with-values |
1475: | .03% | (lambda () (new-domain->old-domain (+ lower-0 1))) |
1476: | 0% | old-indexer) |
1477: | 0% | base) |
1478: | | 0))) |
1479: | .03% | (build-indexer-1 base lower-0 increment-0))) |
1480: | | |
1481: | .01% | ((2) (let* ((lower-0 (##Interval-lower-bound new-domain 0)) |
1482: | 0% | (lower-1 (##Interval-lower-bound new-domain 1)) |
1483: | 0% | (upper-0 (##Interval-upper-bound new-domain 0)) |
1484: | 0% | (upper-1 (##Interval-upper-bound new-domain 1)) |
1485: | 0% | (base (call-with-values |
1486: | 0% | (lambda () (new-domain->old-domain lower-0 lower-1)) |
1487: | | old-indexer)) |
1488: | 0% | (increment-0 (if (< (+ lower-0 1) upper-0) |
1489: | 0% | (- (call-with-values |
1490: | 0% | (lambda () (new-domain->old-domain (+ lower-0 1) lower-1)) |
1491: | | old-indexer) |
1492: | 0% | base) |
1493: | | 0)) |
1494: | 0% | (increment-1 (if (< (+ lower-1 1) upper-1) |
1495: | 0% | (- (call-with-values |
1496: | 0% | (lambda () (new-domain->old-domain lower-0 (+ lower-1 1))) |
1497: | | old-indexer) |
1498: | | base) |
1499: | | 0))) |
1500: | 0% | (build-indexer-2 base lower-0 lower-1 increment-0 increment-1))) |
1501: | | ((3) (let* ((lower-0 (##Interval-lower-bound new-domain 0)) |
1502: | | (lower-1 (##Interval-lower-bound new-domain 1)) |
1503: | | (lower-2 (##Interval-lower-bound new-domain 2)) |
1504: | | (upper-0 (##Interval-upper-bound new-domain 0)) |
1505: | | (upper-1 (##Interval-upper-bound new-domain 1)) |
1506: | | (upper-2 (##Interval-upper-bound new-domain 2)) |
1507: | | (base (call-with-values |
1508: | | (lambda () (new-domain->old-domain lower-0 lower-1 lower-2)) |
1509: | | old-indexer)) |
1510: | 0% | (increment-0 (if (< (+ lower-0 1) upper-0) |
1511: | | (- (call-with-values |
1512: | | (lambda () (new-domain->old-domain (+ lower-0 1) lower-1 lower-2)) |
1513: | | old-indexer) |
1514: | | base) |
1515: | | 0)) |
1516: | 0% | (increment-1 (if (< (+ lower-1 1) upper-1) |
1517: | | (- (call-with-values |
1518: | 0% | (lambda () (new-domain->old-domain lower-0 (+ lower-1 1) lower-2)) |
1519: | | old-indexer) |
1520: | | base) |
1521: | | 0)) |
1522: | | (increment-2 (if (< (+ lower-2 1) upper-2) |
1523: | | (- (call-with-values |
1524: | 0% | (lambda () (new-domain->old-domain lower-0 lower-1 (+ lower-2 1))) |
1525: | | old-indexer) |
1526: | | base) |
1527: | | 0))) |
1528: | 0% | (build-indexer-3 base lower-0 lower-1 lower-2 increment-0 increment-1 increment-2))) |
1529: | | ((4) (let* ((lower-0 (##Interval-lower-bound new-domain 0)) |
1530: | | (lower-1 (##Interval-lower-bound new-domain 1)) |
1531: | | (lower-2 (##Interval-lower-bound new-domain 2)) |
1532: | | (lower-3 (##Interval-lower-bound new-domain 3)) |
1533: | | (upper-0 (##Interval-upper-bound new-domain 0)) |
1534: | | (upper-1 (##Interval-upper-bound new-domain 1)) |
1535: | | (upper-2 (##Interval-upper-bound new-domain 2)) |
1536: | | (upper-3 (##Interval-upper-bound new-domain 3)) |
1537: | | (base (call-with-values |
1538: | | (lambda () (new-domain->old-domain lower-0 lower-1 lower-2 lower-3)) |
1539: | | old-indexer)) |
1540: | | (increment-0 (if (< (+ lower-0 1) upper-0) |
1541: | | (- (call-with-values |
1542: | | (lambda () (new-domain->old-domain (+ lower-0 1) lower-1 lower-2 lower-3)) |
1543: | | old-indexer) |
1544: | | base) |
1545: | | 0)) |
1546: | | (increment-1 (if (< (+ lower-1 1) upper-1) |
1547: | | (- (call-with-values |
1548: | | (lambda () (new-domain->old-domain lower-0 (+ lower-1 1) lower-2 lower-3)) |
1549: | | old-indexer) |
1550: | | base) |
1551: | | 0)) |
1552: | | (increment-2 (if (< (+ lower-2 1) upper-2) |
1553: | | (- (call-with-values |
1554: | | (lambda () (new-domain->old-domain lower-0 lower-1 (+ lower-2 1) lower-3)) |
1555: | | old-indexer) |
1556: | | base) |
1557: | | 0)) |
1558: | | (increment-3 (if (< (+ lower-3 1) upper-3) |
1559: | | (- (call-with-values |
1560: | | (lambda () (new-domain->old-domain lower-0 lower-1 lower-2 (+ lower-3 1))) |
1561: | | old-indexer) |
1562: | | base) |
1563: | | 0))) |
1564: | | (build-indexer-4 base lower-0 lower-1 lower-2 lower-3 increment-0 increment-1 increment-2 increment-3))) |
1565: | | (else |
1566: | | (let* ((lower-bounds (##Interval-lower-bounds->list new-domain)) |
1567: | | (upper-bounds (##Interval-upper-bounds->list new-domain)) |
1568: | | (base (call-with-values |
1569: | | (lambda () (apply new-domain->old-domain lower-bounds)) |
1570: | | old-indexer)) |
1571: | | (increments (let ((increments (map (lambda (x) 0) lower-bounds)) |
1572: | | (lower-bounds (map (lambda (x) x) lower-bounds))) |
1573: | | (let loop ((l lower-bounds) |
1574: | | (u upper-bounds) |
1575: | | (i increments) |
1576: | | (base base)) |
1577: | | (if (null? l) |
1578: | | increments |
1579: | | (let ((new-base |
1580: | | (if (< (+ (car l) 1) |
1581: | | (car u)) |
1582: | | (begin |
1583: | | (set-car! l (+ (car l) 1)) |
1584: | | (let ((new-base (call-with-values |
1585: | | (lambda () (apply new-domain->old-domain lower-bounds)) |
1586: | | old-indexer))) |
1587: | | (set-car! i (- new-base base)) |
1588: | | new-base)) |
1589: | | base))) |
1590: | | (loop (cdr l) |
1591: | | (cdr u) |
1592: | | (cdr i) |
1593: | | new-base))))))) |
1594: | | (build-indexer-generic base lower-bounds increments))))) |
1595: | | |
1596: | | #| |
1597: | | |
1598: | | In the next function old-indexer is a 1-1 mapping from old-domain to [0,N) for some N. |
1599: | | |
1600: | | new-domain->old-domain is a 1-1 mapping from new-domain to old-domain. |
1601: | | |
1602: | | |# |
1603: | | |
1604: | | (define (compose-generic-indexers old-indexer new-domain new-domain->old-domain old-domain) |
1605: | | (if (= (##Interval-dimension old-domain) 1) |
1606: | | (case (##Interval-dimension new-domain) |
1607: | | ((1) (lambda (i) (old-indexer (new-domain->old-domain i)))) |
1608: | | ((2) (lambda (i j) (old-indexer (new-domain->old-domain i j)))) |
1609: | | ((3) (lambda (i j k) (old-indexer (new-domain->old-domain i j k)))) |
1610: | | ((4) (lambda (i j k l) (old-indexer (new-domain->old-domain i j k l)))) |
1611: | | (else (lambda multi-index (old-indexer (apply new-domain->old-domain multi-index))))) |
1612: | | (case (##Interval-dimension new-domain) |
1613: | | ((1) (lambda (i) (call-with-values (lambda () (new-domain->old-domain i)) old-indexer))) |
1614: | | ((2) (lambda (i j) (call-with-values (lambda () (new-domain->old-domain i j)) old-indexer))) |
1615: | | ((3) (lambda (i j k) (call-with-values (lambda () (new-domain->old-domain i j k)) old-indexer))) |
1616: | | ((4) (lambda (i j k l) (call-with-values (lambda () (new-domain->old-domain i j k l)) old-indexer))) |
1617: | | (else (lambda multi-index (call-with-values (lambda () (apply new-domain->old-domain multi-index)) old-indexer)))))) |
1618: | | |
1619: | | #| |
1620: | | |
1621: | | You want to share the backing store of array. (I'm thinking more and more that this is |
1622: | | an uninteresting thing to do.) |
1623: | | |
1624: | | So you specify a new domain, a 1-1 mapping from the new-domain to the old-domain, and |
1625: | | say whether this mapping is affine. |
1626: | | |
1627: | | If the mapping and the original indexer of array are both affine, build a fast |
1628: | | composition, otherwise build a general one. |
1629: | | |
1630: | | |# |
1631: | | |
1632: | | |
1633: | | (define (Fixed-array-share! array |
1634: | | new-domain |
1635: | | new-domain->old-domain |
1636: | | #!optional |
1637: | .03% | (new-domain->old-domain-is-affine #t)) |
1638: | .02% | (or (and (not (Fixed-array? array)) |
1639: | | (error "Fixed-array-share!: array is not a Fixed-array: " array)) |
1640: | .03% | (and (not (Interval? new-domain)) |
1641: | | (error "Fixed-array-share!: new-domain is not an Interval: " new-domain)) |
1642: | .03% | (and (not (procedure? new-domain->old-domain)) |
1643: | | (error "Fixed-array-share!: new-domain->old-domain is not a procedure: " new-domain->old-domain)) |
1644: | .03% | (and (not (boolean? new-domain->old-domain-is-affine)) |
1645: | | (error "Fixed-array-share!: new-domain->old-domain-is-affine is not boolean: " new-domain->old-domain-is-affine)) |
1646: | .02% | (let ((old-domain (Array-domain array)) |
1647: | .01% | (old-indexer (Fixed-array-indexer array)) |
1648: | .01% | (body (Fixed-array-body array)) |
1649: | .01% | (manipulators (Fixed-array-manipulators array)) |
1650: | .01% | (affine? (Fixed-array-affine? array))) |
1651: | .02% | (##finish-Fixed-array new-domain |
1652: | 0% | manipulators |
1653: | 0% | body |
1654: | .01% | (if (and affine? new-domain->old-domain-is-affine) |
1655: | .02% | (compose-affine-indexers old-indexer new-domain new-domain->old-domain) |
1656: | | (compose-generic-indexers old-indexer new-domain new-domain->old-domain old-domain)) |
1657: | .01% | (and affine? new-domain->old-domain-is-affine))))) |
1658: | | |
1659: | | (define (Fixed-array-lazy-curry array left-dimension) |
1660: | | (declare (fixnum)) |
1661: | 0% | (or (and (not (Fixed-array? array)) |
1662: | | (error "Fixed-array-lazy-curry: argument is not a Fixed-array: " array left-dimension)) |
1663: | 0% | (and (not (exact-integer? left-dimension)) |
1664: | | (error "Fixed-array-lazy-curry: argument is not an exact integer: " array left-dimension)) |
1665: | 0% | (and (not (< 0 left-dimension (##Interval-dimension (Array-domain array)))) |
1666: | | (error "Fixed-array-lazy-curry: argument is not between 0 and (Interval-dimension (Array-domain array)) (exclusive): " array left-dimension)) |
1667: | 0% | (if (Fixed-array-affine? array) |
1668: | | (call-with-values |
1669: | 0% | (lambda () (Interval-curry (Array-domain array) left-dimension)) |
1670: | 0% | (lambda (left-interval right-interval) |
1671: | 0% | (build-Array left-interval |
1672: | 0% | (case (##Interval-dimension left-interval) |
1673: | 0% | ((1) (case (##Interval-dimension right-interval) |
1674: | | ((1) (lambda (i) |
1675: | .05% | (Fixed-array-share! array right-interval (lambda (j) (values i j ))))) |
1676: | | ((2) (lambda (i) |
1677: | 0% | (Fixed-array-share! array right-interval (lambda (j k) (values i j k ))))) |
1678: | | ((3) (lambda (i) |
1679: | 0% | (Fixed-array-share! array right-interval (lambda (j k l) (values i j k l))))) |
1680: | | (else (lambda (i) |
1681: | | (Fixed-array-share! array right-interval (lambda (#!rest multi-index) (apply values i multi-index))))))) |
1682: | | ((2) (case (##Interval-dimension right-interval) |
1683: | | ((1) (lambda (i j) |
1684: | | (Fixed-array-share! array right-interval (lambda (k) (values i j k ))))) |
1685: | | ((2) (lambda (i j) |
1686: | 0% | (Fixed-array-share! array right-interval (lambda (k l) (values i j k l))))) |
1687: | | (else (lambda (i j) |
1688: | | (Fixed-array-share! array right-interval (lambda (#!rest multi-index) (apply values i j multi-index))))))) |
1689: | | ((3) (case (##Interval-dimension right-interval) |
1690: | | ((1) (lambda (i j k) |
1691: | | (Fixed-array-share! array right-interval (lambda (l) (values i j k l))))) |
1692: | | (else (lambda (i j k) |
1693: | | (Fixed-array-share! array right-interval (lambda (#!rest multi-index) (apply values i j k multi-index))))))) |
1694: | | (else (lambda (#!rest left-multi-index) |
1695: | | (Fixed-array-share! array |
1696: | | right-interval |
1697: | | (lambda (#!rest right-multi-index) |
1698: | | (apply values (append left-multi-index right-multi-index)))))))))) |
1699: | | (Mutable-array-lazy-curry array left-dimension)))) |
1700: | | |
1701: | | (define (Fixed-array-lazy-distinguish-one array index) |
1702: | | (or (and (not (Fixed-array? array)) |
1703: | | (error "Fixed-array-lazy-distinguish-one: argument is not an Fixed-array: " array index)) |
1704: | | (and (not (exact-integer? index)) |
1705: | | (error "Fixed-array-lazy-distinguish-one: argument is not an exact integer: " array index)) |
1706: | | (and (not (< 1 (##Interval-dimension (Array-domain array)))) |
1707: | | (error "Fixed-array-lazy-distinguish-one: (Interval-dimension (Array-domain array)) is not greater than 1 : " array index)) |
1708: | | (and (not (< -1 index (##Interval-dimension (Array-domain array)))) |
1709: | | (error "Fixed-array-lazy-distinguish-one: argument is not between 0 (inclusive) and (Interval-dimension (Array-domain array)) (exclusive): " array index)) |
1710: | | (if (Fixed-array-affine? array) |
1711: | | (call-with-values |
1712: | | (lambda () (Interval-distinguish-one (Array-domain array) index)) |
1713: | | (lambda (outer-interval inner-interval) |
1714: | | (let ((accessor (Mutable-array-accessor array)) |
1715: | | (setter (Mutable-array-setter array))) |
1716: | | (case (##Interval-dimension outer-interval) |
1717: | | ((1) (case index |
1718: | | ((0) (build-Array outer-interval |
1719: | | (lambda (j) (Fixed-array-share! array inner-interval (lambda (i) (values i j)))))) |
1720: | | ((1) (build-Array outer-interval |
1721: | | (lambda (i) (Fixed-array-share! array inner-interval (lambda (j) (values i j)))))))) |
1722: | | ((2) (case index |
1723: | | ((0) (build-Array outer-interval |
1724: | | (lambda (j k) (Fixed-array-share! array inner-interval (lambda (i) (values i j k)))))) |
1725: | | ((1) (build-Array outer-interval |
1726: | | (lambda (i k) (Fixed-array-share! array inner-interval (lambda (j) (values i j k)))))) |
1727: | | ((2) (build-Array outer-interval |
1728: | | (lambda (i j) (Fixed-array-share! array inner-interval (lambda (k) (values i j k)))))))) |
1729: | | ((3) (case index |
1730: | | ((0) (build-Array outer-interval |
1731: | | (lambda (j k l) (Fixed-array-share! array inner-interval (lambda (i) (values i j k l)))))) |
1732: | | ((1) (build-Array outer-interval |
1733: | | (lambda (i k l) (Fixed-array-share! array inner-interval (lambda (j) (values i j k l)))))) |
1734: | | ((2) (build-Array outer-interval |
1735: | | (lambda (i j l) (Fixed-array-share! array inner-interval (lambda (k) (values i j k l)))))) |
1736: | | ((3) (build-Array outer-interval |
1737: | | (lambda (i j k) (Fixed-array-share! array inner-interval (lambda (l) (values i j k l)))))))) |
1738: | | (else (build-Array outer-interval |
1739: | | (lambda (#!rest outer-index) |
1740: | | (Fixed-array-share! array inner-interval (lambda (m) (apply values (insert-arg-into-arg-list m outer-index index))))))))))) |
1741: | | (Mutable-array-lazy-distinguish-one array index)))) |
1742: | | #| |
1743: | | |
1744: | | Array-lazy-map eturns an array whose domain is the same as the common domain of (cons array arrays) |
1745: | | and whose accessor is |
1746: | | |
1747: | | (lambda multi-index |
1748: | | (apply f (map (lambda (g) (apply g multi-index)) (map Array-accessor (cons array arrays))))) |
1749: | | |
1750: | | This function is also used in Array-for-each, so we try to specialize the this |
1751: | | function to speed things up a bit. |
1752: | | |
1753: | | |# |
1754: | | |
1755: | | (define (specialize-function-applied-to-array-accessors f array arrays) |
1756: | | (let ((domain (Array-domain array)) |
1757: | | (accessor-0 (Array-accessor array))) |
1758: | | (case (length arrays) |
1759: | | ((0) (case (##Interval-dimension domain) |
1760: | | ((1) (lambda (i) (f (accessor-0 i)))) |
1761: | .05% | ((2) (lambda (i j) (f (accessor-0 i j)))) |
1762: | .01% | ((3) (lambda (i j k) (f (accessor-0 i j k)))) |
1763: | 2.41% | ((4) (lambda (i j k l) (f (accessor-0 i j k l)))) |
1764: | | (else (lambda multi-index (f (apply accessor-0 multi-index)))))) |
1765: | | |
1766: | 0% | ((1) (let ((accessor-1 (Array-accessor (car arrays)))) |
1767: | | (case (##Interval-dimension domain) |
1768: | | ((1) (lambda (i) (f (accessor-0 i) |
1769: | | (accessor-1 i)))) |
1770: | .01% | ((2) (lambda (i j) (f (accessor-0 i j) |
1771: | .01% | (accessor-1 i j)))) |
1772: | 1.19% | ((3) (lambda (i j k) (f (accessor-0 i j k) |
1773: | 1.04% | (accessor-1 i j k)))) |
1774: | | ((4) (lambda (i j k l) (f (accessor-0 i j k l) |
1775: | | (accessor-1 i j k l)))) |
1776: | | (else (lambda multi-index (f (apply accessor-0 multi-index) |
1777: | | (apply accessor-1 multi-index))))))) |
1778: | | ((2) (let ((accessor-1 (Array-accessor (car arrays))) |
1779: | | (accessor-2 (Array-accessor (cadr arrays)))) |
1780: | | (case (##Interval-dimension domain) |
1781: | | ((1) (lambda (i) (f (accessor-0 i) |
1782: | | (accessor-1 i) |
1783: | | (accessor-2 i)))) |
1784: | | ((2) (lambda (i j) (f (accessor-0 i j) |
1785: | | (accessor-1 i j) |
1786: | | (accessor-2 i j)))) |
1787: | | ((3) (lambda (i j k) (f (accessor-0 i j k) |
1788: | | (accessor-1 i j k) |
1789: | | (accessor-2 i j k)))) |
1790: | | ((4) (lambda (i j k l) (f (accessor-0 i j k l) |
1791: | | (accessor-1 i j k l) |
1792: | | (accessor-2 i j k l)))) |
1793: | | (else (lambda multi-index (f (apply accessor-0 multi-index) |
1794: | | (apply accessor-1 multi-index) |
1795: | | (apply accessor-2 multi-index))))))) |
1796: | | (else |
1797: | | (let ((accessors (cons accessor-0 (map Array-accessor arrays)))) |
1798: | | (case (##Interval-dimension domain) |
1799: | | ((1) (lambda (i) (apply f (map (lambda (g) (g i)) accessors)))) |
1800: | | ((2) (lambda (i j) (apply f (map (lambda (g) (g i j)) accessors)))) |
1801: | | ((3) (lambda (i j k) (apply f (map (lambda (g) (g i j k)) accessors)))) |
1802: | | ((4) (lambda (i j k l) (apply f (map (lambda (g) (g i j k l)) accessors)))) |
1803: | | (else (lambda multi-index (apply f (map (lambda (g) (apply g multi-index)) accessors)))))))))) |
1804: | | |
1805: | | (define (Array-lazy-map f array . arrays) |
1806: | | (or (and (not (procedure? f)) |
1807: | | (error "Array-lazy-map: Argument is not a procedure: " f)) |
1808: | | (and (not (every Array? (cons array arrays))) |
1809: | | (apply error "Array-lazy-map: Not all arguments are arrays: " array arrays)) |
1810: | | (and (not (every (lambda (d) (Interval= d (Array-domain array))) (map Array-domain arrays))) |
1811: | | (apply error "Array-lazy-map: Not all arrays have the same domain: " array arrays)) |
1812: | | (build-Array (Array-domain array) |
1813: | | (specialize-function-applied-to-array-accessors f array arrays)))) |
1814: | | |
1815: | | ;;; applies f to the elements of the arrays in lexicographical order. |
1816: | | |
1817: | | (define (Array-for-each f array . arrays) |
1818: | 0% | (or (and (not (procedure? f)) |
1819: | | (error "Array-for-each: Argument is not a procedure: " f)) |
1820: | | (and (not (every Array? (cons array arrays))) |
1821: | | (apply error "Array-for-each: Not all arguments are arrays: " array arrays)) |
1822: | 0% | (and (not (every (lambda (d) (Interval= d (Array-domain array))) (map Array-domain arrays))) |
1823: | | (apply error "Array-for-each: Not all arrays have the same domain: " array arrays)) |
1824: | | (Interval-for-each (specialize-function-applied-to-array-accessors f array arrays) (Array-domain array)))) |
1825: | | |
1826: | | #| |
1827: | | |
1828: | | Returns a Fixed-array whose domain is the same as the common domain of (cons array arrays) |
1829: | | and whose backing store is filled with the values of |
1830: | | |
1831: | | (lambda multi-index |
1832: | | (apply f (map (lambda (g) (apply g multi-index)) (map Array-accessor (cons array arrays))))) |
1833: | | |
1834: | | calculated in no particular order. |
1835: | | |
1836: | | If all arrays are Fixed arrays with the same indexer and domain, and they completely |
1837: | | occupty the body of the first array, then f is just called on the values of the |
1838: | | corresponding Fixed-array-bodies, in order. |
1839: | | |
1840: | | The default is to just call Array->Fixed array on the result of Array-lazy-map. |
1841: | | |
1842: | | We do not specify the order that the elements of the resulting Fixed-array |
1843: | | are calculated in. If you want to ensure things evaluated in a specific order, call |
1844: | | Array->Fixed-array on the result of Array-lazy-map. |
1845: | | |
1846: | | |# |
1847: | | |
1848: | | (define (Array-map result-manipulators f array . arrays) |
1849: | | (or (and (not (procedure? f)) |
1850: | | (error "Array-map: Argument is not a procedure: " f)) |
1851: | | (and (not (every Array? (cons array arrays))) |
1852: | | (apply error "Array-map: Not all arguments are arrays: " array arrays)) |
1853: | | (and (not (every (lambda (d) (Interval= d (Array-domain array))) (map Array-domain arrays))) |
1854: | | (apply error "Array-map: Not all arrays have the same domain: " array arrays)) |
1855: | | (and (not (Fixed-array-manipulators? result-manipulators)) |
1856: | | (error "Array-map: result-manipulators are not Fixed-array-manipulators: " result-manipulators)) |
1857: | | (Array->Fixed-array result-manipulators |
1858: | | (build-Array (Array-domain array) |
1859: | | (specialize-function-applied-to-array-accessors f array arrays))))) |
1860: | | |
1861: | | (define (Array-reduce op id a) |
1862: | | (or (and (not (procedure? op)) |
1863: | | (error "Array-reduce: operator is not a procedure: " op)) |
1864: | | (and (not (Array? a)) |
1865: | | (error "Array-reduce: argument is not an array: " a)) |
1866: | | (Interval-reduce (Array-accessor a) op id (Array-domain a)))) |
1867: | | |
1868: | | (declare (generic)) |