25.main.upstream.scm 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. ;;; array
  2. ;;; 1997 - 2001 Jussi Piitulainen
  3. ;;; --- Intro ---
  4. ;;; This interface to arrays is based on Alan Bawden's array.scm of
  5. ;;; 1993 (earlier version in the Internet Repository and another
  6. ;;; version in SLIB). This is a complete rewrite, to be consistent
  7. ;;; with the rest of Scheme and to make arrays independent of lists.
  8. ;;; Some modifications are due to discussion in srfi-25 mailing list.
  9. ;;; (array? obj)
  10. ;;; (make-array shape [obj]) changed arguments
  11. ;;; (shape bound ...) new
  12. ;;; (array shape obj ...) new
  13. ;;; (array-rank array) changed name back
  14. ;;; (array-start array dimension) new
  15. ;;; (array-end array dimension) new
  16. ;;; (array-ref array k ...)
  17. ;;; (array-ref array index) new variant
  18. ;;; (array-set! array k ... obj) changed argument order
  19. ;;; (array-set! array index obj) new variant
  20. ;;; (share-array array shape proc) changed arguments
  21. ;;; All other variables in this file have names in "array:".
  22. ;;; Should there be a way to make arrays with initial values mapped
  23. ;;; from indices? Sure. The current "initial object" is lame.
  24. ;;;
  25. ;;; Removed (array-shape array) from here. There is a new version
  26. ;;; in arlib though.
  27. ;;; --- Representation type dependencies ---
  28. ;;; The mapping from array indices to the index to the underlying vector
  29. ;;; is whatever array:optimize returns. The file "opt" provides three
  30. ;;; representations:
  31. ;;;
  32. ;;; mbda) mapping is a procedure that allows an optional argument
  33. ;;; tter) mapping is two procedures that takes exactly the indices
  34. ;;; ctor) mapping is a vector of a constant term and coefficients
  35. ;;;
  36. ;;; Choose one in "opt" to make the optimizer. Then choose the matching
  37. ;;; implementation of array-ref and array-set!.
  38. ;;;
  39. ;;; These should be made macros to inline them. Or have a good compiler
  40. ;;; and plant the package as a module.
  41. ;;; 1. Pick an optimizer.
  42. ;;; 2. Pick matching index representation.
  43. ;;; 3. Pick a record implementation; as-procedure is generic; syntax inlines.
  44. ;;; 3. This file is otherwise portable.
  45. ;;; --- Portable R5RS (R4RS and multiple values) ---
  46. ;;; (array? obj)
  47. ;;; returns #t if `obj' is an array and #t or #f otherwise.
  48. (define (array? obj)
  49. (array:array? obj))
  50. ;;; (make-array shape)
  51. ;;; (make-array shape obj)
  52. ;;; makes array of `shape' with each cell containing `obj' initially.
  53. (define (make-array shape . rest)
  54. (or (array:good-shape? shape)
  55. (error "make-array: shape is not a shape"))
  56. (apply array:make-array shape rest))
  57. (define (array:make-array shape . rest)
  58. (let ((size (array:size shape)))
  59. (array:make
  60. (if (pair? rest)
  61. (apply (lambda (o) (make-vector size o)) rest)
  62. (make-vector size))
  63. (if (= size 0)
  64. (array:optimize-empty
  65. (vector-ref (array:shape shape) 1))
  66. (array:optimize
  67. (array:make-index shape)
  68. (vector-ref (array:shape shape) 1)))
  69. (array:shape->vector shape))))
  70. ;;; (shape bound ...)
  71. ;;; makes a shape. Bounds must be an even number of exact, pairwise
  72. ;;; non-decreasing integers. Note that any such array can be a shape.
  73. (define (shape . bounds)
  74. (let ((v (list->vector bounds)))
  75. (or (even? (vector-length v))
  76. (error (string-append "shape: uneven number of bounds: "
  77. (array:list->string bounds))))
  78. (let ((shp (array:make
  79. v
  80. (if (pair? bounds)
  81. (array:shape-index)
  82. (array:empty-shape-index))
  83. (vector 0 (quotient (vector-length v) 2)
  84. 0 2))))
  85. (or (array:good-shape? shp)
  86. (error (string-append "shape: bounds are not pairwise "
  87. "non-decreasing exact integers: "
  88. (array:list->string bounds))))
  89. shp)))
  90. ;;; (array shape obj ...)
  91. ;;; is analogous to `vector'.
  92. (define (array shape . elts)
  93. (or (array:good-shape? shape)
  94. (error (string-append "array: shape " (array:thing->string shape)
  95. " is not a shape")))
  96. (let ((size (array:size shape)))
  97. (let ((vector (list->vector elts)))
  98. (or (= (vector-length vector) size)
  99. (error (string-append "array: an array of shape "
  100. (array:shape-vector->string
  101. (array:vector shape))
  102. " has "
  103. (number->string size)
  104. " elements but got "
  105. (number->string (vector-length vector))
  106. " values: "
  107. (array:list->string elts))))
  108. (array:make
  109. vector
  110. (if (= size 0)
  111. (array:optimize-empty
  112. (vector-ref (array:shape shape) 1))
  113. (array:optimize
  114. (array:make-index shape)
  115. (vector-ref (array:shape shape) 1)))
  116. (array:shape->vector shape)))))
  117. ;;; (array-rank array)
  118. ;;; returns the number of dimensions of `array'.
  119. (define (array-rank array)
  120. (quotient (vector-length (array:shape array)) 2))
  121. ;;; (array-start array k)
  122. ;;; returns the lower bound index of array along dimension k. This is
  123. ;;; the least valid index along that dimension if the dimension is not
  124. ;;; empty.
  125. (define (array-start array d)
  126. (vector-ref (array:shape array) (+ d d)))
  127. ;;; (array-end array k)
  128. ;;; returns the upper bound index of array along dimension k. This is
  129. ;;; not a valid index. If the dimension is empty, this is the same as
  130. ;;; the lower bound along it.
  131. (define (array-end array d)
  132. (vector-ref (array:shape array) (+ d d 1)))
  133. ;;; (share-array array shape proc)
  134. ;;; makes an array that shares elements of `array' at shape `shape'.
  135. ;;; The arguments to `proc' are indices of the result. The values of
  136. ;;; `proc' are indices of `array'.
  137. ;;; Todo: in the error message, should recognise the mapping and show it.
  138. (define (share-array array subshape f)
  139. (or (array:good-shape? subshape)
  140. (error (string-append "share-array: shape "
  141. (array:thing->string subshape)
  142. " is not a shape")))
  143. (let ((subsize (array:size subshape)))
  144. (or (array:good-share? subshape subsize f (array:shape array))
  145. (error (string-append "share-array: subshape "
  146. (array:shape-vector->string
  147. (array:vector subshape))
  148. " does not map into supershape "
  149. (array:shape-vector->string
  150. (array:shape array))
  151. " under mapping "
  152. (array:map->string
  153. f
  154. (vector-ref (array:shape subshape) 1)))))
  155. (let ((g (array:index array)))
  156. (array:make
  157. (array:vector array)
  158. (if (= subsize 0)
  159. (array:optimize-empty
  160. (vector-ref (array:shape subshape) 1))
  161. (array:optimize
  162. (lambda ks
  163. (call-with-values
  164. (lambda () (apply f ks))
  165. (lambda ks (array:vector-index g ks))))
  166. (vector-ref (array:shape subshape) 1)))
  167. (array:shape->vector subshape)))))
  168. ;;; --- Hrmph ---
  169. ;;; (array:share/index! ...)
  170. ;;; reuses a user supplied index object when recognising the
  171. ;;; mapping. The mind balks at the very nasty side effect that
  172. ;;; exposes the implementation. So this is not in the spec.
  173. ;;; But letting index objects in at all creates a pressure
  174. ;;; to go the whole hog. Arf.
  175. ;;; Use array:optimize-empty for an empty array to get a
  176. ;;; clearly invalid vector index.
  177. ;;; Surely it's perverse to use an actor for index here? But
  178. ;;; the possibility is provided for completeness.
  179. (define (array:share/index! array subshape proc index)
  180. (array:make
  181. (array:vector array)
  182. (if (= (array:size subshape) 0)
  183. (array:optimize-empty
  184. (quotient (vector-length (array:shape array)) 2))
  185. ((if (vector? index)
  186. array:optimize/vector
  187. array:optimize/actor)
  188. (lambda (subindex)
  189. (let ((superindex (proc subindex)))
  190. (if (vector? superindex)
  191. (array:index/vector
  192. (quotient (vector-length (array:shape array)) 2)
  193. (array:index array)
  194. superindex)
  195. (array:index/array
  196. (quotient (vector-length (array:shape array)) 2)
  197. (array:index array)
  198. (array:vector superindex)
  199. (array:index superindex)))))
  200. index))
  201. (array:shape->vector subshape)))
  202. (define (array:optimize/vector f v)
  203. (let ((r (vector-length v)))
  204. (do ((k 0 (+ k 1)))
  205. ((= k r))
  206. (vector-set! v k 0))
  207. (let ((n0 (f v))
  208. (cs (make-vector (+ r 1)))
  209. (apply (array:applier-to-vector (+ r 1))))
  210. (vector-set! cs 0 n0)
  211. (let wok ((k 0))
  212. (if (< k r)
  213. (let ((k1 (+ k 1)))
  214. (vector-set! v k 1)
  215. (let ((nk (- (f v) n0)))
  216. (vector-set! v k 0)
  217. (vector-set! cs k1 nk)
  218. (wok k1)))))
  219. (apply (array:maker r) cs))))
  220. (define (array:optimize/actor f a)
  221. (let ((r (array-end a 0))
  222. (v (array:vector a))
  223. (i (array:index a)))
  224. (do ((k 0 (+ k 1)))
  225. ((= k r))
  226. (vector-set! v (array:actor-index i k) 0))
  227. (let ((n0 (f a))
  228. (cs (make-vector (+ r 1)))
  229. (apply (array:applier-to-vector (+ r 1))))
  230. (vector-set! cs 0 n0)
  231. (let wok ((k 0))
  232. (if (< k r)
  233. (let ((k1 (+ k 1))
  234. (t (array:actor-index i k)))
  235. (vector-set! v t 1)
  236. (let ((nk (- (f a) n0)))
  237. (vector-set! v t 0)
  238. (vector-set! cs k1 nk)
  239. (wok k1)))))
  240. (apply (array:maker r) cs))))
  241. ;;; --- Internals ---
  242. (define (array:shape->vector shape)
  243. (let ((idx (array:index shape))
  244. (shv (array:vector shape))
  245. (rnk (vector-ref (array:shape shape) 1)))
  246. (let ((vec (make-vector (* rnk 2))))
  247. (do ((k 0 (+ k 1)))
  248. ((= k rnk)
  249. vec)
  250. (vector-set! vec (+ k k)
  251. (vector-ref shv (array:shape-vector-index idx k 0)))
  252. (vector-set! vec (+ k k 1)
  253. (vector-ref shv (array:shape-vector-index idx k 1)))))))
  254. ;;; (array:size shape)
  255. ;;; returns the number of elements in arrays of shape `shape'.
  256. (define (array:size shape)
  257. (let ((idx (array:index shape))
  258. (shv (array:vector shape))
  259. (rnk (vector-ref (array:shape shape) 1)))
  260. (do ((k 0 (+ k 1))
  261. (s 1 (* s
  262. (- (vector-ref shv (array:shape-vector-index idx k 1))
  263. (vector-ref shv (array:shape-vector-index idx k 0))))))
  264. ((= k rnk) s))))
  265. ;;; (array:make-index shape)
  266. ;;; returns an index function for arrays of shape `shape'. This is a
  267. ;;; runtime composition of several variable arity procedures, to be
  268. ;;; passed to array:optimize for recognition as an affine function of
  269. ;;; as many variables as there are dimensions in arrays of this shape.
  270. (define (array:make-index shape)
  271. (let ((idx (array:index shape))
  272. (shv (array:vector shape))
  273. (rnk (vector-ref (array:shape shape) 1)))
  274. (do ((f (lambda () 0)
  275. (lambda (k . ks)
  276. (+ (* s (- k (vector-ref
  277. shv
  278. (array:shape-vector-index idx (- j 1) 0))))
  279. (apply f ks))))
  280. (s 1 (* s (- (vector-ref
  281. shv
  282. (array:shape-vector-index idx (- j 1) 1))
  283. (vector-ref
  284. shv
  285. (array:shape-vector-index idx (- j 1) 0)))))
  286. (j rnk (- j 1)))
  287. ((= j 0)
  288. f))))
  289. ;;; --- Error checking ---
  290. ;;; (array:good-shape? shape)
  291. ;;; returns true if `shape' is an array of the right shape and its
  292. ;;; elements are exact integers that pairwise bound intervals `[lo..hi)´.
  293. (define (array:good-shape? shape)
  294. (and (array:array? shape)
  295. (let ((u (array:shape shape))
  296. (v (array:vector shape))
  297. (x (array:index shape)))
  298. (and (= (vector-length u) 4)
  299. (= (vector-ref u 0) 0)
  300. (= (vector-ref u 2) 0)
  301. (= (vector-ref u 3) 2))
  302. (let ((p (vector-ref u 1)))
  303. (do ((k 0 (+ k 1))
  304. (true #t (let ((lo (vector-ref
  305. v
  306. (array:shape-vector-index x k 0)))
  307. (hi (vector-ref
  308. v
  309. (array:shape-vector-index x k 1))))
  310. (and true
  311. (integer? lo)
  312. (exact? lo)
  313. (integer? hi)
  314. (exact? hi)
  315. (<= lo hi)))))
  316. ((= k p) true))))))
  317. ;;; (array:good-share? subv subsize mapping superv)
  318. ;;; returns true if the extreme indices in the subshape vector map
  319. ;;; into the bounds in the supershape vector.
  320. ;;; If some interval in `subv' is empty, then `subv' is empty and its
  321. ;;; image under `f' is empty and it is trivially alright. One must
  322. ;;; not call `f', though.
  323. (define (array:good-share? subshape subsize f super)
  324. (or (zero? subsize)
  325. (letrec
  326. ((sub (array:vector subshape))
  327. (dex (array:index subshape))
  328. (ck (lambda (k ks)
  329. (if (zero? k)
  330. (call-with-values
  331. (lambda () (apply f ks))
  332. (lambda qs (array:good-indices? qs super)))
  333. (and (ck (- k 1)
  334. (cons (vector-ref
  335. sub
  336. (array:shape-vector-index
  337. dex
  338. (- k 1)
  339. 0))
  340. ks))
  341. (ck (- k 1)
  342. (cons (- (vector-ref
  343. sub
  344. (array:shape-vector-index
  345. dex
  346. (- k 1)
  347. 1))
  348. 1)
  349. ks)))))))
  350. (let ((rnk (vector-ref (array:shape subshape) 1)))
  351. (or (array:unchecked-share-depth? rnk)
  352. (ck rnk '()))))))
  353. ;;; Check good-share on 10 dimensions at most. The trouble is,
  354. ;;; the cost of this check is exponential in the number of dimensions.
  355. (define (array:unchecked-share-depth? rank)
  356. (if (> rank 10)
  357. (begin
  358. (display `(warning: unchecked depth in share:
  359. ,rank subdimensions))
  360. (newline)
  361. #t)
  362. #f))
  363. ;;; (array:check-indices caller indices shape-vector)
  364. ;;; (array:check-indices.o caller indices shape-vector)
  365. ;;; (array:check-index-vector caller index-vector shape-vector)
  366. ;;; return if the index is in bounds, else signal error.
  367. ;;;
  368. ;;; Shape-vector is the internal representation, with
  369. ;;; b and e for dimension k at 2k and 2k + 1.
  370. (define (array:check-indices who ks shv)
  371. (or (array:good-indices? ks shv)
  372. (error (array:not-in who ks shv))))
  373. (define (array:check-indices.o who ks shv)
  374. (or (array:good-indices.o? ks shv)
  375. (error (array:not-in who (reverse (cdr (reverse ks))) shv))))
  376. (define (array:check-index-vector who ks shv)
  377. (or (array:good-index-vector? ks shv)
  378. (error (array:not-in who (vector->list ks) shv))))
  379. (define (array:check-index-actor who ks shv)
  380. (let ((shape (array:shape ks)))
  381. (or (and (= (vector-length shape) 2)
  382. (= (vector-ref shape 0) 0))
  383. (error "not an actor"))
  384. (or (array:good-index-actor?
  385. (vector-ref shape 1)
  386. (array:vector ks)
  387. (array:index ks)
  388. shv)
  389. (array:not-in who (do ((k (vector-ref shape 1) (- k 1))
  390. (m '() (cons (vector-ref
  391. (array:vector ks)
  392. (array:actor-index
  393. (array:index ks)
  394. (- k 1)))
  395. m)))
  396. ((= k 0) m))
  397. shv))))
  398. (define (array:good-indices? ks shv)
  399. (let ((d2 (vector-length shv)))
  400. (do ((kp ks (if (pair? kp)
  401. (cdr kp)))
  402. (k 0 (+ k 2))
  403. (true #t (and true (pair? kp)
  404. (array:good-index? (car kp) shv k))))
  405. ((= k d2)
  406. (and true (null? kp))))))
  407. (define (array:good-indices.o? ks.o shv)
  408. (let ((d2 (vector-length shv)))
  409. (do ((kp ks.o (if (pair? kp)
  410. (cdr kp)))
  411. (k 0 (+ k 2))
  412. (true #t (and true (pair? kp)
  413. (array:good-index? (car kp) shv k))))
  414. ((= k d2)
  415. (and true (pair? kp) (null? (cdr kp)))))))
  416. (define (array:good-index-vector? ks shv)
  417. (let ((r2 (vector-length shv)))
  418. (and (= (* 2 (vector-length ks)) r2)
  419. (do ((j 0 (+ j 1))
  420. (k 0 (+ k 2))
  421. (true #t (and true
  422. (array:good-index? (vector-ref ks j) shv k))))
  423. ((= k r2) true)))))
  424. (define (array:good-index-actor? r v i shv)
  425. (and (= (* 2 r) (vector-length shv))
  426. (do ((j 0 (+ j 1))
  427. (k 0 (+ k 2))
  428. (true #t (and true
  429. (array:good-index? (vector-ref
  430. v
  431. (array:actor-index i j))
  432. shv
  433. k))))
  434. ((= j r) true))))
  435. ;;; (array:good-index? index shape-vector 2d)
  436. ;;; returns true if index is within bounds for dimension 2d/2.
  437. (define (array:good-index? w shv k)
  438. (and (integer? w)
  439. (exact? w)
  440. (<= (vector-ref shv k) w)
  441. (< w (vector-ref shv (+ k 1)))))
  442. (define (array:not-in who ks shv)
  443. (let ((index (array:list->string ks))
  444. (bounds (array:shape-vector->string shv)))
  445. (error (string-append who
  446. ": index " index
  447. " not in bounds " bounds))))
  448. (define (array:list->string ks)
  449. (do ((index "" (string-append index (array:thing->string (car ks)) " "))
  450. (ks ks (cdr ks)))
  451. ((null? ks) index)))
  452. (define (array:shape-vector->string shv)
  453. (do ((bounds "" (string-append bounds
  454. "["
  455. (number->string (vector-ref shv t))
  456. ".."
  457. (number->string (vector-ref shv (+ t 1)))
  458. ")"
  459. " "))
  460. (t 0 (+ t 2)))
  461. ((= t (vector-length shv)) bounds)))
  462. (define (array:thing->string thing)
  463. (cond
  464. ((number? thing) (number->string thing))
  465. ((symbol? thing) (string-append "#<symbol>" (symbol->string thing)))
  466. ((char? thing) "#<char>")
  467. ((string? thing) "#<string>")
  468. ((list? thing) (string-append "#" (number->string (length thing))
  469. "<list>"))
  470. ((pair? thing) "#<pair>")
  471. ((array? thing) "#<array>")
  472. ((vector? thing) (string-append "#" (number->string
  473. (vector-length thing))
  474. "<vector>"))
  475. ((procedure? thing) "#<procedure>")
  476. (else
  477. (case thing
  478. ((()) "()")
  479. ((#t) "#t")
  480. ((#f) "#f")
  481. (else
  482. "#<whatsit>")))))
  483. ;;; And to grok an affine map, vector->vector type. Column k of arr
  484. ;;; will contain coefficients n0 ... nm of 1 k1 ... km for kth value.
  485. ;;;
  486. ;;; These are for the error message when share fails.
  487. (define (array:index-ref ind k)
  488. (if (vector? ind)
  489. (vector-ref ind k)
  490. (vector-ref
  491. (array:vector ind)
  492. (array:actor-index (array:index ind) k))))
  493. (define (array:index-set! ind k o)
  494. (if (vector? ind)
  495. (vector-set! ind k o)
  496. (vector-set!
  497. (array:vector ind)
  498. (array:actor-index (array:index ind) k)
  499. o)))
  500. (define (array:index-length ind)
  501. (if (vector? ind)
  502. (vector-length ind)
  503. (vector-ref (array:shape ind) 1)))
  504. (define (array:map->string proc r)
  505. (let* ((m (array:grok/arguments proc r))
  506. (s (vector-ref (array:shape m) 3)))
  507. (do ((i "" (string-append i c "k" (number->string k)))
  508. (c "" ", ")
  509. (k 1 (+ k 1)))
  510. ((< r k)
  511. (do ((o "" (string-append o c (array:map-column->string m r k)))
  512. (c "" ", ")
  513. (k 0 (+ k 1)))
  514. ((= k s)
  515. (string-append i " => " o)))))))
  516. (define (array:map-column->string m r k)
  517. (let ((v (array:vector m))
  518. (i (array:index m)))
  519. (let ((n0 (vector-ref v (array:vector-index i (list 0 k)))))
  520. (let wok ((j 1)
  521. (e (if (= n0 0) "" (number->string n0))))
  522. (if (<= j r)
  523. (let ((nj (vector-ref v (array:vector-index i (list j k)))))
  524. (if (= nj 0)
  525. (wok (+ j 1) e)
  526. (let* ((nj (if (= nj 1) ""
  527. (if (= nj -1) "-"
  528. (string-append (number->string nj)
  529. " "))))
  530. (njkj (string-append nj "k" (number->string j))))
  531. (if (string=? e "")
  532. (wok (+ j 1) njkj)
  533. (wok (+ j 1) (string-append e " + " njkj))))))
  534. (if (string=? e "") "0" e))))))
  535. (define (array:grok/arguments proc r)
  536. (array:grok/index!
  537. (lambda (vec)
  538. (call-with-values
  539. (lambda ()
  540. (array:apply-to-vector r proc vec))
  541. vector))
  542. (make-vector r)))
  543. (define (array:grok/index! proc in)
  544. (let ((m (array:index-length in)))
  545. (do ((k 0 (+ k 1)))
  546. ((= k m))
  547. (array:index-set! in k 0))
  548. (let* ((n0 (proc in))
  549. (n (array:index-length n0)))
  550. (let ((arr (make-array (shape 0 (+ m 1) 0 n)))) ; (*)
  551. (do ((k 0 (+ k 1)))
  552. ((= k n))
  553. (array-set! arr 0 k (array:index-ref n0 k))) ; (**)
  554. (do ((j 0 (+ j 1)))
  555. ((= j m))
  556. (array:index-set! in j 1)
  557. (let ((nj (proc in)))
  558. (array:index-set! in j 0)
  559. (do ((k 0 (+ k 1)))
  560. ((= k n))
  561. (array-set! arr (+ j 1) k (- (array:index-ref nj k) ; (**)
  562. (array:index-ref n0 k))))))
  563. arr))))
  564. ;; (*) Should not use `make-array' and `shape' here
  565. ;; (**) Should not use `array-set!' here
  566. ;; Should use something internal to the library instead: either lower
  567. ;; level code (preferable but complex) or alternative names to these same.