array-map.test 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. ;;;; array-map.test --- test array mapping functions -*- scheme -*-
  2. ;;;;
  3. ;;;; Copyright (C) 2004, 2005, 2006, 2009, 2013 Free Software Foundation, Inc.
  4. ;;;;
  5. ;;;; This library is free software; you can redistribute it and/or
  6. ;;;; modify it under the terms of the GNU Lesser General Public
  7. ;;;; License as published by the Free Software Foundation; either
  8. ;;;; version 3 of the License, or (at your option) any later version.
  9. ;;;;
  10. ;;;; This library is distributed in the hope that it will be useful,
  11. ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. ;;;; Lesser General Public License for more details.
  14. ;;;;
  15. ;;;; You should have received a copy of the GNU Lesser General Public
  16. ;;;; License along with this library; if not, write to the Free Software
  17. ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  18. (define-module (test-suite test-array-map)
  19. #:use-module (test-suite lib))
  20. (define exception:shape-mismatch
  21. (cons 'misc-error ".*shape mismatch.*"))
  22. (define (array-row a i)
  23. (make-shared-array a (lambda (j) (list i j))
  24. (cadr (array-dimensions a))))
  25. (define (array-col a j)
  26. (make-shared-array a (lambda (i) (list i j))
  27. (car (array-dimensions a))))
  28. ;;;
  29. ;;; array-index-map!
  30. ;;;
  31. (with-test-prefix "array-index-map!"
  32. (pass-if "basic test"
  33. (let ((nlst '()))
  34. (array-index-map! (make-array #f '(1 1))
  35. (lambda (n)
  36. (set! nlst (cons n nlst))))
  37. (equal? nlst '(1))))
  38. (with-test-prefix "empty arrays"
  39. (pass-if "all axes empty"
  40. (array-index-map! (make-typed-array 'f64 0 0 0) (const 0))
  41. (array-index-map! (make-typed-array 'b #t 0 0) (const #t))
  42. (array-index-map! (make-typed-array #t 0 0 0) (const 0))
  43. #t)
  44. (pass-if "last axis empty"
  45. (array-index-map! (make-typed-array 'f64 0 2 0) (const 0))
  46. (array-index-map! (make-typed-array 'b #t 2 0) (const #t))
  47. (array-index-map! (make-typed-array #t 0 2 0) (const 0))
  48. #t)
  49. ; the 'f64 cases fail in 2.0.9 with out-of-range.
  50. (pass-if "axis empty, other than last"
  51. (array-index-map! (make-typed-array 'f64 0 0 2) (const 0))
  52. (array-index-map! (make-typed-array 'b #t 0 2) (const #t))
  53. (array-index-map! (make-typed-array #t 0 0 2) (const 0))
  54. #t))
  55. (pass-if "rank 2"
  56. (let ((a (make-array 0 2 2))
  57. (b (make-array 0 2 2)))
  58. (array-index-map! a (lambda (i j) i))
  59. (array-index-map! b (lambda (i j) j))
  60. (and (array-equal? a #2((0 0) (1 1)))
  61. (array-equal? b #2((0 1) (0 1)))))))
  62. ;;;
  63. ;;; array-copy!
  64. ;;;
  65. (with-test-prefix "array-copy!"
  66. (with-test-prefix "empty arrays"
  67. (pass-if "empty other than last, #t"
  68. (let* ((b (make-array 0 2 2))
  69. (c (make-shared-array b (lambda (i j) (list i j)) 0 2)))
  70. (array-copy! #2:0:2() c)
  71. (array-equal? #2:0:2() c)))
  72. (pass-if "empty other than last, 'f64"
  73. (let* ((b (make-typed-array 'f64 0 2 2))
  74. (c (make-shared-array b (lambda (i j) (list i j)) 0 2)))
  75. (array-copy! #2:0:2() c)
  76. (array-equal? #2f64:0:2() c)))
  77. (pass-if "empty/immutable vector"
  78. (array-copy! #() (vector))
  79. #t)
  80. ;; FIXME add empty, type 'b cases.
  81. )
  82. ;; note that it is the opposite of array-map!. This is, unfortunately,
  83. ;; documented in the manual.
  84. (pass-if "matching behavior I"
  85. (let ((a #(1 2))
  86. (b (make-array 0 3)))
  87. (array-copy! a b)
  88. (equal? b #(1 2 0))))
  89. (pass-if-exception "matching behavior II" exception:shape-mismatch
  90. (let ((a #(1 2 3))
  91. (b (make-array 0 2)))
  92. (array-copy! a b)
  93. (equal? b #(1 2))))
  94. ;; here both a & b are are unrollable down to the first axis, but the
  95. ;; size mismatch limits unrolling to the last axis only.
  96. (pass-if "matching behavior III"
  97. (let ((a #3(((1 2) (3 4)) ((5 6) (7 8))))
  98. (b (make-array 0 2 3 2)))
  99. (array-copy! a b)
  100. (array-equal? b #3(((1 2) (3 4) (0 0)) ((5 6) (7 8) (0 0))))))
  101. (pass-if "rank 0"
  102. (let ((a #0(99))
  103. (b (make-array 0)))
  104. (array-copy! a b)
  105. (equal? b #0(99))))
  106. (pass-if "rank 1"
  107. (let* ((a #2((1 2) (3 4)))
  108. (b (make-shared-array a (lambda (j) (list 1 j)) 2))
  109. (c (make-shared-array a (lambda (i) (list (- 1 i) 1)) 2))
  110. (d (make-array 0 2))
  111. (e (make-array 0 2)))
  112. (array-copy! b d)
  113. (array-copy! c e)
  114. (and (equal? d #(3 4))
  115. (equal? e #(4 2)))))
  116. (pass-if "rank 2"
  117. (let ((a #2((1 2) (3 4)))
  118. (b (make-array 0 2 2))
  119. (c (make-array 0 2 2))
  120. (d (make-array 0 2 2))
  121. (e (make-array 0 2 2)))
  122. (array-copy! a b)
  123. (array-copy! a (transpose-array c 1 0))
  124. (array-copy! (transpose-array a 1 0) d)
  125. (array-copy! (transpose-array a 1 0) (transpose-array e 1 0))
  126. (and (equal? a #2((1 2) (3 4)))
  127. (equal? b #2((1 2) (3 4)))
  128. (equal? c #2((1 3) (2 4)))
  129. (equal? d #2((1 3) (2 4)))
  130. (equal? e #2((1 2) (3 4))))))
  131. (pass-if "rank 2, discontinuous"
  132. (let ((A #2((0 1) (2 3) (4 5)))
  133. (B #2((10 11) (12 13) (14 15)))
  134. (C #2((20) (21) (22)))
  135. (X (make-array 0 3 5))
  136. (piece (lambda (X w s)
  137. (make-shared-array
  138. X (lambda (i j) (list i (+ j s))) 3 w))))
  139. (array-copy! A (piece X 2 0))
  140. (array-copy! B (piece X 2 2))
  141. (array-copy! C (piece X 1 4))
  142. (and (array-equal? X #2((0 1 10 11 20) (2 3 12 13 21) (4 5 14 15 22))))))
  143. (pass-if "null increments, not empty"
  144. (let ((a (make-array 0 2 2)))
  145. (array-copy! (make-shared-array #0(1) (lambda x '()) 2 2) a)
  146. (array-equal? #2((1 1) (1 1))))))
  147. ;;;
  148. ;;; array-map!
  149. ;;;
  150. (with-test-prefix "array-map!"
  151. (pass-if-exception "no args" exception:wrong-num-args
  152. (array-map!))
  153. (pass-if-exception "one arg" exception:wrong-num-args
  154. (array-map! (make-array #f 5)))
  155. (with-test-prefix "no sources"
  156. (pass-if "closure 0"
  157. (array-map! (make-array #f 5) (lambda () #f))
  158. #t)
  159. (pass-if-exception "closure 1" exception:wrong-num-args
  160. (array-map! (make-array #f 5) (lambda (x) #f)))
  161. (pass-if-exception "closure 2" exception:wrong-num-args
  162. (array-map! (make-array #f 5) (lambda (x y) #f)))
  163. (pass-if-exception "subr_1" exception:wrong-num-args
  164. (array-map! (make-array #f 5) length))
  165. (pass-if-exception "subr_2" exception:wrong-num-args
  166. (array-map! (make-array #f 5) logtest))
  167. (pass-if-exception "subr_2o" exception:wrong-num-args
  168. (array-map! (make-array #f 5) number->string))
  169. (pass-if-exception "dsubr" exception:wrong-num-args
  170. (array-map! (make-array #f 5) sqrt))
  171. (pass-if "rpsubr"
  172. (let ((a (make-array 'foo 5)))
  173. (array-map! a =)
  174. (equal? a (make-array #t 5))))
  175. (pass-if "asubr"
  176. (let ((a (make-array 'foo 5)))
  177. (array-map! a +)
  178. (equal? a (make-array 0 5))))
  179. ;; in Guile 1.6.4 and earlier this resulted in a segv
  180. (pass-if "noop"
  181. (array-map! (make-array #f 5) noop)
  182. #t))
  183. (with-test-prefix "one source"
  184. (pass-if-exception "closure 0" exception:wrong-num-args
  185. (array-map! (make-array #f 5) (lambda () #f)
  186. (make-array #f 5)))
  187. (pass-if "closure 1"
  188. (let ((a (make-array #f 5)))
  189. (array-map! a (lambda (x) 'foo) (make-array #f 5))
  190. (equal? a (make-array 'foo 5))))
  191. (pass-if-exception "closure 2" exception:wrong-num-args
  192. (array-map! (make-array #f 5) (lambda (x y) #f)
  193. (make-array #f 5)))
  194. (pass-if "subr_1"
  195. (let ((a (make-array #f 5)))
  196. (array-map! a length (make-array '(x y z) 5))
  197. (equal? a (make-array 3 5))))
  198. (pass-if-exception "subr_2" exception:wrong-num-args
  199. (array-map! (make-array #f 5) logtest
  200. (make-array 999 5)))
  201. (pass-if "subr_2o"
  202. (let ((a (make-array #f 5)))
  203. (array-map! a number->string (make-array 99 5))
  204. (equal? a (make-array "99" 5))))
  205. (pass-if "dsubr"
  206. (let ((a (make-array #f 5)))
  207. (array-map! a sqrt (make-array 16.0 5))
  208. (equal? a (make-array 4.0 5))))
  209. (pass-if "rpsubr"
  210. (let ((a (make-array 'foo 5)))
  211. (array-map! a = (make-array 0 5))
  212. (equal? a (make-array #t 5))))
  213. (pass-if "asubr"
  214. (let ((a (make-array 'foo 5)))
  215. (array-map! a - (make-array 99 5))
  216. (equal? a (make-array -99 5))))
  217. ;; in Guile 1.6.5 and 1.6.6 this was an error
  218. (pass-if "1+"
  219. (let ((a (make-array #f 5)))
  220. (array-map! a 1+ (make-array 123 5))
  221. (equal? a (make-array 124 5))))
  222. (pass-if "rank 0"
  223. (let ((a #0(99))
  224. (b (make-array 0)))
  225. (array-map! b values a)
  226. (equal? b #0(99))))
  227. (pass-if "rank 2, discontinuous"
  228. (let ((A #2((0 1) (2 3) (4 5)))
  229. (B #2((10 11) (12 13) (14 15)))
  230. (C #2((20) (21) (22)))
  231. (X (make-array 0 3 5))
  232. (piece (lambda (X w s)
  233. (make-shared-array
  234. X (lambda (i j) (list i (+ j s))) 3 w))))
  235. (array-map! (piece X 2 0) values A)
  236. (array-map! (piece X 2 2) values B)
  237. (array-map! (piece X 1 4) values C)
  238. (and (array-equal? X #2((0 1 10 11 20) (2 3 12 13 21) (4 5 14 15 22))))))
  239. (pass-if "null increments, not empty"
  240. (let ((a (make-array 0 2 2)))
  241. (array-map! a values (make-shared-array #0(1) (lambda x '()) 2 2))
  242. (array-equal? a #2((1 1) (1 1))))))
  243. (with-test-prefix "two sources"
  244. (pass-if-exception "closure 0" exception:wrong-num-args
  245. (array-map! (make-array #f 5) (lambda () #f)
  246. (make-array #f 5) (make-array #f 5)))
  247. (pass-if-exception "closure 1" exception:wrong-num-args
  248. (array-map! (make-array #f 5) (lambda (x) #f)
  249. (make-array #f 5) (make-array #f 5)))
  250. (pass-if "closure 2"
  251. (let ((a (make-array #f 5)))
  252. (array-map! a (lambda (x y) 'foo)
  253. (make-array #f 5) (make-array #f 5))
  254. (equal? a (make-array 'foo 5))))
  255. (pass-if-exception "subr_1" exception:wrong-num-args
  256. (array-map! (make-array #f 5) length
  257. (make-array #f 5) (make-array #f 5)))
  258. (pass-if "subr_2"
  259. (let ((a (make-array 'foo 5)))
  260. (array-map! a logtest
  261. (make-array 999 5) (make-array 999 5))
  262. (equal? a (make-array #t 5))))
  263. (pass-if "subr_2o"
  264. (let ((a (make-array #f 5)))
  265. (array-map! a number->string
  266. (make-array 32 5) (make-array 16 5))
  267. (equal? a (make-array "20" 5))))
  268. (pass-if-exception "dsubr" exception:wrong-num-args
  269. (let ((a (make-array #f 5)))
  270. (array-map! a sqrt
  271. (make-array 16.0 5) (make-array 16.0 5))
  272. (equal? a (make-array 4.0 5))))
  273. (pass-if "rpsubr"
  274. (let ((a (make-array 'foo 5)))
  275. (array-map! a = (make-array 99 5) (make-array 77 5))
  276. (equal? a (make-array #f 5))))
  277. (pass-if "asubr"
  278. (let ((a (make-array 'foo 5)))
  279. (array-map! a - (make-array 99 5) (make-array 11 5))
  280. (equal? a (make-array 88 5))))
  281. (pass-if "+"
  282. (let ((a (make-array #f 4)))
  283. (array-map! a + #(1 2 3 4) #(5 6 7 8))
  284. (equal? a #(6 8 10 12))))
  285. (pass-if "noncompact arrays 1"
  286. (let ((a #2((0 1) (2 3)))
  287. (c (make-array 0 2)))
  288. (begin
  289. (array-map! c + (array-row a 1) (array-row a 1))
  290. (array-equal? c #(4 6)))))
  291. (pass-if "noncompact arrays 2"
  292. (let ((a #2((0 1) (2 3)))
  293. (c (make-array 0 2)))
  294. (begin
  295. (array-map! c + (array-col a 1) (array-col a 1))
  296. (array-equal? c #(2 6)))))
  297. (pass-if "noncompact arrays 3"
  298. (let ((a #2((0 1) (2 3)))
  299. (c (make-array 0 2)))
  300. (begin
  301. (array-map! c + (array-col a 1) (array-row a 1))
  302. (array-equal? c #(3 6)))))
  303. (pass-if "noncompact arrays 4"
  304. (let ((a #2((0 1) (2 3)))
  305. (c (make-array 0 2)))
  306. (begin
  307. (array-map! c + (array-col a 1) (array-row a 1))
  308. (array-equal? c #(3 6)))))
  309. (pass-if "offset arrays 1"
  310. (let ((a #2@1@-3((0 1) (2 3)))
  311. (c (make-array 0 '(1 2) '(-3 -2))))
  312. (begin
  313. (array-map! c + a a)
  314. (array-equal? c #2@1@-3((0 2) (4 6)))))))
  315. ;; note that array-copy! has the opposite behavior.
  316. (pass-if-exception "matching behavior I" exception:shape-mismatch
  317. (let ((a #(1 2))
  318. (b (make-array 0 3)))
  319. (array-map! b values a)
  320. (equal? b #(1 2 0))))
  321. (pass-if "matching behavior II"
  322. (let ((a #(1 2 3))
  323. (b (make-array 0 2)))
  324. (array-map! b values a)
  325. (equal? b #(1 2))))
  326. ;; here both a & b are are unrollable down to the first axis, but the
  327. ;; size mismatch limits unrolling to the last axis only.
  328. (pass-if "matching behavior III"
  329. (let ((a #3(((1 2) (3 4) (5 6)) ((7 8) (9 10) (11 12))))
  330. (b (make-array 0 2 2 2)))
  331. (array-map! b values a)
  332. (array-equal? b #3(((1 2) (3 4)) ((7 8) (9 10)))))))
  333. ;;;
  334. ;;; array-for-each
  335. ;;;
  336. (with-test-prefix "array-for-each"
  337. (with-test-prefix "1 source"
  338. (pass-if-equal "rank 0"
  339. '(99)
  340. (let* ((a #0(99))
  341. (l '())
  342. (p (lambda (x) (set! l (cons x l)))))
  343. (array-for-each p a)
  344. l))
  345. (pass-if-equal "noncompact array"
  346. '(3 2 1 0)
  347. (let* ((a #2((0 1) (2 3)))
  348. (l '())
  349. (p (lambda (x) (set! l (cons x l)))))
  350. (array-for-each p a)
  351. l))
  352. (pass-if-equal "vector"
  353. '(3 2 1 0)
  354. (let* ((a #(0 1 2 3))
  355. (l '())
  356. (p (lambda (x) (set! l (cons x l)))))
  357. (array-for-each p a)
  358. l))
  359. (pass-if-equal "shared array"
  360. '(3 2 1 0)
  361. (let* ((a #2((0 1) (2 3)))
  362. (a' (make-shared-array a
  363. (lambda (x)
  364. (list (quotient x 4)
  365. (modulo x 4)))
  366. 4))
  367. (l '())
  368. (p (lambda (x) (set! l (cons x l)))))
  369. (array-for-each p a')
  370. l)))
  371. (with-test-prefix "3 sources"
  372. (pass-if-equal "noncompact arrays 1"
  373. '((3 1 3) (2 0 2))
  374. (let* ((a #2((0 1) (2 3)))
  375. (l '())
  376. (rec (lambda args (set! l (cons args l)))))
  377. (array-for-each rec (array-row a 1) (array-row a 0) (array-row a 1))
  378. l))
  379. (pass-if-equal "noncompact arrays 2"
  380. '((3 3 3) (2 2 1))
  381. (let* ((a #2((0 1) (2 3)))
  382. (l '())
  383. (rec (lambda args (set! l (cons args l)))))
  384. (array-for-each rec (array-row a 1) (array-row a 1) (array-col a 1))
  385. l))
  386. (pass-if-equal "noncompact arrays 3"
  387. '((3 3 3) (2 1 1))
  388. (let* ((a #2((0 1) (2 3)))
  389. (l '())
  390. (rec (lambda args (set! l (cons args l)))))
  391. (array-for-each rec (array-row a 1) (array-col a 1) (array-col a 1))
  392. l))
  393. (pass-if-equal "noncompact arrays 4"
  394. '((3 2 3) (1 0 2))
  395. (let* ((a #2((0 1) (2 3)))
  396. (l '())
  397. (rec (lambda args (set! l (cons args l)))))
  398. (array-for-each rec (array-col a 1) (array-col a 0) (array-row a 1))
  399. l)))
  400. (with-test-prefix "empty arrays"
  401. (pass-if "empty other than last, #t" ; fails in 2.0.9 with bad a.
  402. (let* ((a (list))
  403. (b (make-array 0 2 2))
  404. (c (make-shared-array b (lambda (i j) (list i j)) 0 2)))
  405. (array-for-each (lambda (c) (set! a (cons c a))) c)
  406. (equal? a '())))
  407. (pass-if "empty other than last, f64" ; fails in 2.0.9 with out of range.
  408. (let* ((a (list))
  409. (b (make-typed-array 'f64 0 2 2))
  410. (c (make-shared-array b (lambda (i j) (list i j)) 0 2)))
  411. (array-for-each (lambda (c) (set! a (cons c a))) c)
  412. (equal? a '())))
  413. ;; FIXME add type 'b cases.
  414. (pass-if-exception "empty arrays shape check" exception:shape-mismatch
  415. (let* ((a (list))
  416. (b (make-typed-array 'f64 0 0 2))
  417. (c (make-typed-array 'f64 0 2 0)))
  418. (array-for-each (lambda (b c) (set! a (cons* b c a))) b c)))))
  419. ;;;
  420. ;;; array-slice-for-each
  421. ;;;
  422. (with-test-prefix "array-slice-for-each"
  423. (pass-if-equal "1 argument frame rank 1"
  424. #2((1 3 9) (2 7 8))
  425. (let* ((a (list->array 2 '((9 1 3) (7 8 2)))))
  426. (array-slice-for-each 1 (lambda (a) (sort! a <)) a)
  427. a))
  428. (pass-if-equal "1 argument frame rank 1, non-zero base indices"
  429. #2@1@1((1 3 9) (2 7 8))
  430. (let* ((a (make-array *unspecified* '(1 2) '(1 3)))
  431. (b #2@1@1((9 1 3) (7 8 2))))
  432. (array-copy! b a)
  433. (array-slice-for-each 1 (lambda (a) (sort! a <)) a)
  434. a))
  435. (pass-if-equal "2 arguments frame rank 1"
  436. #f64(8 -1)
  437. (let* ((x (list->typed-array 'f64 2 '((9 1) (7 8))))
  438. (y (f64vector 99 99)))
  439. (array-slice-for-each 1 (lambda (y x) (array-set! y (- (array-ref x 0) (array-ref x 1)))) y x)
  440. y))
  441. (pass-if-equal "regression: zero-sized frame loop without unrolling"
  442. 99
  443. (let* ((x 99)
  444. (o (make-array 0. 0 3 2)))
  445. (array-slice-for-each 2
  446. (lambda (o a0 a1)
  447. (set! x 0))
  448. o
  449. (make-shared-array (make-array 1. 0 1) (const '(0 0)) 0 3)
  450. (make-array 2. 0 3))
  451. x)))