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