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))