srfi-67.test 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222
  1. ;;; -*- mode: scheme; coding: utf-8; -*-
  2. ;;; Copyright (C) 2010 Free Software Foundation, Inc.
  3. ;;; Copyright (c) 2005 Sebastian Egner and Jens Axel S{\o}gaard.
  4. ;;;
  5. ;;; This code is based on the file examples.scm in the reference
  6. ;;; implementation of SRFI-67, provided under the following license:
  7. ;;;
  8. ;;; Permission is hereby granted, free of charge, to any person obtaining
  9. ;;; a copy of this software and associated documentation files (the
  10. ;;; ``Software''), to deal in the Software without restriction, including
  11. ;;; without limitation the rights to use, copy, modify, merge, publish,
  12. ;;; distribute, sublicense, and/or sell copies of the Software, and to
  13. ;;; permit persons to whom the Software is furnished to do so, subject to
  14. ;;; the following conditions:
  15. ;;;
  16. ;;; The above copyright notice and this permission notice shall be
  17. ;;; included in all copies or substantial portions of the Software.
  18. ;;;
  19. ;;; THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
  20. ;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  21. ;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  22. ;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  23. ;;; LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  24. ;;; OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  25. ;;; WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  26. ;;;
  27. (define-module (test-srfi-67)
  28. #:use-module (test-suite lib)
  29. #:use-module (srfi srfi-42)
  30. #:use-module (srfi srfi-67))
  31. ; =============================================================================
  32. ; Test engine
  33. ; ===========
  34. ;
  35. ; We use an extended version of the checker of SRFI-42 (with
  36. ; Felix' reduction on codesize) for running a batch of tests for
  37. ; the various procedures of 'compare.scm'. Moreover, we use the
  38. ; comprehensions of SRFI-42 to generate examples systematically.
  39. ; (my-check expr => desired-result)
  40. ; evaluates expr and compares the value with desired-result.
  41. (define-syntax my-check
  42. (syntax-rules (=>)
  43. ((my-check expr => desired-result)
  44. (my-check-proc 'expr (lambda () expr) desired-result))))
  45. (define (my-check-proc expr thunk desired-result)
  46. (pass-if expr (equal? (thunk) desired-result)))
  47. ; (my-check-ec <qualifier>* <ok?> <expr>)
  48. ; runs (every?-ec <qualifier>* <ok?>), counting the times <ok?>
  49. ; is evaluated as a correct example, and stopping at the first
  50. ; counter example for which <expr> provides the argument.
  51. (define-syntax my-check-ec
  52. (syntax-rules (nested)
  53. ((my-check-ec (nested q1 ...) q etc1 etc2 etc ...)
  54. (my-check-ec (nested q1 ... q) etc1 etc2 etc ...))
  55. ((my-check-ec q1 q2 etc1 etc2 etc ...)
  56. (my-check-ec (nested q1 q2) etc1 etc2 etc ...))
  57. ((my-check-ec ok? expr)
  58. (my-check-ec (nested) ok? expr))
  59. ((my-check-ec (nested q ...) ok? expr)
  60. (my-check-ec-proc
  61. '(every?-ec q ... ok?)
  62. (lambda ()
  63. (first-ec
  64. 'ok
  65. (nested q ...)
  66. (:let ok ok?)
  67. (if (not ok))
  68. (list expr)))
  69. 'expr))
  70. ((my-check-ec q ok? expr)
  71. (my-check-ec (nested q) ok? expr))))
  72. (define (my-check-ec-proc expr thunk arg-counter-example)
  73. (pass-if expr (eqv? (thunk) 'ok)))
  74. ; =============================================================================
  75. ; Abstractions etc.
  76. ; =================
  77. (define ci integer-compare) ; very frequently used
  78. ; (result-ok? actual desired)
  79. ; tests if actual and desired specify the same ordering.
  80. (define (result-ok? actual desired)
  81. (eqv? actual desired))
  82. ; (my-check-compare compare increasing-elements)
  83. ; evaluates (compare x y) for x, y in increasing-elements
  84. ; and checks the result against -1, 0, or 1 depending on
  85. ; the position of x and y in the list increasing-elements.
  86. (define-syntax my-check-compare
  87. (syntax-rules ()
  88. ((my-check-compare compare increasing-elements)
  89. (my-check-ec
  90. (:list x (index ix) increasing-elements)
  91. (:list y (index iy) increasing-elements)
  92. (result-ok? (compare x y) (ci ix iy))
  93. (list x y)))))
  94. ; sorted lists
  95. (define my-booleans '(#f #t))
  96. (define my-chars '(#\a #\b #\c))
  97. (define my-chars-ci '(#\a #\B #\c #\D))
  98. (define my-strings '("" "a" "aa" "ab" "b" "ba" "bb"))
  99. (define my-strings-ci '("" "a" "aA" "Ab" "B" "bA" "BB"))
  100. (define my-symbols '(a aa ab b ba bb))
  101. (define my-reals
  102. (append-ec (:range xn -6 7)
  103. (:let x (/ xn 3))
  104. (list x (+ x (exact->inexact (/ 1 100))))))
  105. (define my-rationals
  106. (list-ec (:list x my-reals)
  107. (and (exact? x) (rational? x))
  108. x))
  109. (define my-integers
  110. (list-ec (:list x my-reals)
  111. (if (and (exact? x) (integer? x)))
  112. x))
  113. (define my-complexes
  114. (list-ec (:list re-x my-reals)
  115. (if (inexact? re-x))
  116. (:list im-x my-reals)
  117. (if (inexact? im-x))
  118. (make-rectangular re-x im-x)))
  119. (define my-lists
  120. '(() (1) (1 1) (1 2) (2) (2 1) (2 2)))
  121. (define my-vector-as-lists
  122. (map list->vector my-lists))
  123. (define my-list-as-vectors
  124. '(() (1) (2) (1 1) (1 2) (2 1) (2 2)))
  125. (define my-vectors
  126. (map list->vector my-list-as-vectors))
  127. (define my-null-or-pairs
  128. '(()
  129. (1) (1 1) (1 2) (1 . 1) (1 . 2)
  130. (2) (2 1) (2 2) (2 . 1) (2 . 2)))
  131. (define my-objects
  132. (append my-null-or-pairs
  133. my-booleans
  134. my-chars
  135. my-strings
  136. my-symbols
  137. my-integers
  138. my-vectors))
  139. ; =============================================================================
  140. ; The checks
  141. ; ==========
  142. (define (check:if3)
  143. ; basic functionality
  144. (my-check (if3 -1 'n 'z 'p) => 'n)
  145. (my-check (if3 0 'n 'z 'p) => 'z)
  146. (my-check (if3 1 'n 'z 'p) => 'p)
  147. ; check arguments are evaluated only once
  148. (my-check
  149. (let ((x -1))
  150. (if3 (let ((x0 x)) (set! x (+ x 1)) x0) 'n 'z 'p))
  151. => 'n)
  152. (my-check
  153. (let ((x -1) (y 0))
  154. (if3 (let ((x0 x)) (set! x (+ x 1)) x0)
  155. (begin (set! y (+ y 1)) y)
  156. (begin (set! y (+ y 10)) y)
  157. (begin (set! y (+ y 100)) y)))
  158. => 1)
  159. (my-check
  160. (let ((x 0) (y 0))
  161. (if3 (let ((x0 x)) (set! x (+ x 1)) x0)
  162. (begin (set! y (+ y 1)) y)
  163. (begin (set! y (+ y 10)) y)
  164. (begin (set! y (+ y 100)) y)))
  165. => 10)
  166. (my-check
  167. (let ((x 1) (y 0))
  168. (if3 (let ((x0 x)) (set! x (+ x 1)) x0)
  169. (begin (set! y (+ y 1)) y)
  170. (begin (set! y (+ y 10)) y)
  171. (begin (set! y (+ y 100)) y)))
  172. => 100)
  173. ) ; check:if3
  174. (define-syntax my-check-if2
  175. (syntax-rules ()
  176. ((my-check-if2 if-rel? rel)
  177. (begin
  178. ; check result
  179. (my-check (if-rel? -1 'yes 'no) => (if (rel -1 0) 'yes 'no))
  180. (my-check (if-rel? 0 'yes 'no) => (if (rel 0 0) 'yes 'no))
  181. (my-check (if-rel? 1 'yes 'no) => (if (rel 1 0) 'yes 'no))
  182. ; check result of 'laterally challenged if'
  183. (my-check (let ((x #f)) (if-rel? -1 (set! x #t)) x) => (rel -1 0))
  184. (my-check (let ((x #f)) (if-rel? 0 (set! x #t)) x) => (rel 0 0))
  185. (my-check (let ((x #f)) (if-rel? 1 (set! x #t)) x) => (rel 1 0))
  186. ; check that <c> is evaluated exactly once
  187. (my-check (let ((n 0)) (if-rel? (begin (set! n (+ n 1)) -1) #t #f) n) => 1)
  188. (my-check (let ((n 0)) (if-rel? (begin (set! n (+ n 1)) 0) #t #f) n) => 1)
  189. (my-check (let ((n 0)) (if-rel? (begin (set! n (+ n 1)) 1) #t #f) n) => 1)
  190. (my-check (let ((n 0)) (if-rel? (begin (set! n (+ n 1)) -1) #t) n) => 1)
  191. (my-check (let ((n 0)) (if-rel? (begin (set! n (+ n 1)) 0) #t) n) => 1)
  192. (my-check (let ((n 0)) (if-rel? (begin (set! n (+ n 1)) 1) #t) n) => 1)
  193. ))))
  194. (define (check:ifs)
  195. (my-check-if2 if=? =)
  196. (my-check-if2 if<? <)
  197. (my-check-if2 if>? >)
  198. (my-check-if2 if<=? <=)
  199. (my-check-if2 if>=? >=)
  200. (my-check-if2 if-not=? (lambda (x y) (not (= x y))))
  201. ) ; check:if2
  202. ; <? etc. macros
  203. (define-syntax my-check-chain2
  204. (syntax-rules ()
  205. ((my-check-chain2 rel? rel)
  206. (begin
  207. ; all chains of length 2
  208. (my-check (rel? ci 0 0) => (rel 0 0))
  209. (my-check (rel? ci 0 1) => (rel 0 1))
  210. (my-check (rel? ci 1 0) => (rel 1 0))
  211. ; using default-compare
  212. (my-check (rel? 0 0) => (rel 0 0))
  213. (my-check (rel? 0 1) => (rel 0 1))
  214. (my-check (rel? 1 0) => (rel 1 0))
  215. ; as a combinator
  216. (my-check ((rel? ci) 0 0) => (rel 0 0))
  217. (my-check ((rel? ci) 0 1) => (rel 0 1))
  218. (my-check ((rel? ci) 1 0) => (rel 1 0))
  219. ; using default-compare as a combinator
  220. (my-check ((rel?) 0 0) => (rel 0 0))
  221. (my-check ((rel?) 0 1) => (rel 0 1))
  222. (my-check ((rel?) 1 0) => (rel 1 0))
  223. ))))
  224. (define (list->set xs) ; xs a list of integers
  225. (if (null? xs)
  226. '()
  227. (let ((max-xs
  228. (let max-without-apply ((m 1) (xs xs))
  229. (if (null? xs)
  230. m
  231. (max-without-apply (max m (car xs)) (cdr xs))))))
  232. (let ((in-xs? (make-vector (+ max-xs 1) #f)))
  233. (do-ec (:list x xs) (vector-set! in-xs? x #t))
  234. (list-ec (:vector in? (index x) in-xs?)
  235. (if in?)
  236. x)))))
  237. (define-syntax arguments-used ; set of arguments (integer, >=0) used in compare
  238. (syntax-rules ()
  239. ((arguments-used (rel1/rel2 compare arg ...))
  240. (let ((used '()))
  241. (rel1/rel2 (lambda (x y)
  242. (set! used (cons x (cons y used)))
  243. (compare x y))
  244. arg ...)
  245. (list->set used)))))
  246. (define-syntax my-check-chain3
  247. (syntax-rules ()
  248. ((my-check-chain3 rel1/rel2? rel1 rel2)
  249. (begin
  250. ; all chains of length 3
  251. (my-check (rel1/rel2? ci 0 0 0) => (and (rel1 0 0) (rel2 0 0)))
  252. (my-check (rel1/rel2? ci 0 0 1) => (and (rel1 0 0) (rel2 0 1)))
  253. (my-check (rel1/rel2? ci 0 1 0) => (and (rel1 0 1) (rel2 1 0)))
  254. (my-check (rel1/rel2? ci 1 0 0) => (and (rel1 1 0) (rel2 0 0)))
  255. (my-check (rel1/rel2? ci 1 1 0) => (and (rel1 1 1) (rel2 1 0)))
  256. (my-check (rel1/rel2? ci 1 0 1) => (and (rel1 1 0) (rel2 0 1)))
  257. (my-check (rel1/rel2? ci 0 1 1) => (and (rel1 0 1) (rel2 1 1)))
  258. (my-check (rel1/rel2? ci 0 1 2) => (and (rel1 0 1) (rel2 1 2)))
  259. (my-check (rel1/rel2? ci 0 2 1) => (and (rel1 0 2) (rel2 2 1)))
  260. (my-check (rel1/rel2? ci 1 2 0) => (and (rel1 1 2) (rel2 2 0)))
  261. (my-check (rel1/rel2? ci 1 0 2) => (and (rel1 1 0) (rel2 0 2)))
  262. (my-check (rel1/rel2? ci 2 0 1) => (and (rel1 2 0) (rel2 0 1)))
  263. (my-check (rel1/rel2? ci 2 1 0) => (and (rel1 2 1) (rel2 1 0)))
  264. ; using default-compare
  265. (my-check (rel1/rel2? 0 0 0) => (and (rel1 0 0) (rel2 0 0)))
  266. (my-check (rel1/rel2? 0 0 1) => (and (rel1 0 0) (rel2 0 1)))
  267. (my-check (rel1/rel2? 0 1 0) => (and (rel1 0 1) (rel2 1 0)))
  268. (my-check (rel1/rel2? 1 0 0) => (and (rel1 1 0) (rel2 0 0)))
  269. (my-check (rel1/rel2? 1 1 0) => (and (rel1 1 1) (rel2 1 0)))
  270. (my-check (rel1/rel2? 1 0 1) => (and (rel1 1 0) (rel2 0 1)))
  271. (my-check (rel1/rel2? 0 1 1) => (and (rel1 0 1) (rel2 1 1)))
  272. (my-check (rel1/rel2? 0 1 2) => (and (rel1 0 1) (rel2 1 2)))
  273. (my-check (rel1/rel2? 0 2 1) => (and (rel1 0 2) (rel2 2 1)))
  274. (my-check (rel1/rel2? 1 2 0) => (and (rel1 1 2) (rel2 2 0)))
  275. (my-check (rel1/rel2? 1 0 2) => (and (rel1 1 0) (rel2 0 2)))
  276. (my-check (rel1/rel2? 2 0 1) => (and (rel1 2 0) (rel2 0 1)))
  277. (my-check (rel1/rel2? 2 1 0) => (and (rel1 2 1) (rel2 1 0)))
  278. ; as a combinator
  279. (my-check ((rel1/rel2? ci) 0 0 0) => (and (rel1 0 0) (rel2 0 0)))
  280. (my-check ((rel1/rel2? ci) 0 0 1) => (and (rel1 0 0) (rel2 0 1)))
  281. (my-check ((rel1/rel2? ci) 0 1 0) => (and (rel1 0 1) (rel2 1 0)))
  282. (my-check ((rel1/rel2? ci) 1 0 0) => (and (rel1 1 0) (rel2 0 0)))
  283. (my-check ((rel1/rel2? ci) 1 1 0) => (and (rel1 1 1) (rel2 1 0)))
  284. (my-check ((rel1/rel2? ci) 1 0 1) => (and (rel1 1 0) (rel2 0 1)))
  285. (my-check ((rel1/rel2? ci) 0 1 1) => (and (rel1 0 1) (rel2 1 1)))
  286. (my-check ((rel1/rel2? ci) 0 1 2) => (and (rel1 0 1) (rel2 1 2)))
  287. (my-check ((rel1/rel2? ci) 0 2 1) => (and (rel1 0 2) (rel2 2 1)))
  288. (my-check ((rel1/rel2? ci) 1 2 0) => (and (rel1 1 2) (rel2 2 0)))
  289. (my-check ((rel1/rel2? ci) 1 0 2) => (and (rel1 1 0) (rel2 0 2)))
  290. (my-check ((rel1/rel2? ci) 2 0 1) => (and (rel1 2 0) (rel2 0 1)))
  291. (my-check ((rel1/rel2? ci) 2 1 0) => (and (rel1 2 1) (rel2 1 0)))
  292. ; as a combinator using default-compare
  293. (my-check ((rel1/rel2?) 0 0 0) => (and (rel1 0 0) (rel2 0 0)))
  294. (my-check ((rel1/rel2?) 0 0 1) => (and (rel1 0 0) (rel2 0 1)))
  295. (my-check ((rel1/rel2?) 0 1 0) => (and (rel1 0 1) (rel2 1 0)))
  296. (my-check ((rel1/rel2?) 1 0 0) => (and (rel1 1 0) (rel2 0 0)))
  297. (my-check ((rel1/rel2?) 1 1 0) => (and (rel1 1 1) (rel2 1 0)))
  298. (my-check ((rel1/rel2?) 1 0 1) => (and (rel1 1 0) (rel2 0 1)))
  299. (my-check ((rel1/rel2?) 0 1 1) => (and (rel1 0 1) (rel2 1 1)))
  300. (my-check ((rel1/rel2?) 0 1 2) => (and (rel1 0 1) (rel2 1 2)))
  301. (my-check ((rel1/rel2?) 0 2 1) => (and (rel1 0 2) (rel2 2 1)))
  302. (my-check ((rel1/rel2?) 1 2 0) => (and (rel1 1 2) (rel2 2 0)))
  303. (my-check ((rel1/rel2?) 1 0 2) => (and (rel1 1 0) (rel2 0 2)))
  304. (my-check ((rel1/rel2?) 2 0 1) => (and (rel1 2 0) (rel2 0 1)))
  305. (my-check ((rel1/rel2?) 2 1 0) => (and (rel1 2 1) (rel2 1 0)))
  306. ; test if all arguments are type checked
  307. (my-check (arguments-used (rel1/rel2? ci 0 1 2)) => '(0 1 2))
  308. (my-check (arguments-used (rel1/rel2? ci 0 2 1)) => '(0 1 2))
  309. (my-check (arguments-used (rel1/rel2? ci 1 2 0)) => '(0 1 2))
  310. (my-check (arguments-used (rel1/rel2? ci 1 0 2)) => '(0 1 2))
  311. (my-check (arguments-used (rel1/rel2? ci 2 0 1)) => '(0 1 2))
  312. (my-check (arguments-used (rel1/rel2? ci 2 1 0)) => '(0 1 2))
  313. ))))
  314. (define-syntax my-check-chain
  315. (syntax-rules ()
  316. ((my-check-chain chain-rel? rel)
  317. (begin
  318. ; the chain of length 0
  319. (my-check (chain-rel? ci) => #t)
  320. ; a chain of length 1
  321. (my-check (chain-rel? ci 0) => #t)
  322. ; all chains of length 2
  323. (my-check (chain-rel? ci 0 0) => (rel 0 0))
  324. (my-check (chain-rel? ci 0 1) => (rel 0 1))
  325. (my-check (chain-rel? ci 1 0) => (rel 1 0))
  326. ; all chains of length 3
  327. (my-check (chain-rel? ci 0 0 0) => (rel 0 0 0))
  328. (my-check (chain-rel? ci 0 0 1) => (rel 0 0 1))
  329. (my-check (chain-rel? ci 0 1 0) => (rel 0 1 0))
  330. (my-check (chain-rel? ci 1 0 0) => (rel 1 0 0))
  331. (my-check (chain-rel? ci 1 1 0) => (rel 1 1 0))
  332. (my-check (chain-rel? ci 1 0 1) => (rel 1 0 1))
  333. (my-check (chain-rel? ci 0 1 1) => (rel 0 1 1))
  334. (my-check (chain-rel? ci 0 1 2) => (rel 0 1 2))
  335. (my-check (chain-rel? ci 0 2 1) => (rel 0 2 1))
  336. (my-check (chain-rel? ci 1 2 0) => (rel 1 2 0))
  337. (my-check (chain-rel? ci 1 0 2) => (rel 1 0 2))
  338. (my-check (chain-rel? ci 2 0 1) => (rel 2 0 1))
  339. (my-check (chain-rel? ci 2 1 0) => (rel 2 1 0))
  340. ; check if all arguments are used
  341. (my-check (arguments-used (chain-rel? ci 0)) => '(0))
  342. (my-check (arguments-used (chain-rel? ci 0 1)) => '(0 1))
  343. (my-check (arguments-used (chain-rel? ci 1 0)) => '(0 1))
  344. (my-check (arguments-used (chain-rel? ci 0 1 2)) => '(0 1 2))
  345. (my-check (arguments-used (chain-rel? ci 0 2 1)) => '(0 1 2))
  346. (my-check (arguments-used (chain-rel? ci 1 2 0)) => '(0 1 2))
  347. (my-check (arguments-used (chain-rel? ci 1 0 2)) => '(0 1 2))
  348. (my-check (arguments-used (chain-rel? ci 2 0 1)) => '(0 1 2))
  349. (my-check (arguments-used (chain-rel? ci 2 1 0)) => '(0 1 2))
  350. ))))
  351. (define (check:predicates-from-compare)
  352. (my-check-chain2 =? =)
  353. (my-check-chain2 <? <)
  354. (my-check-chain2 >? >)
  355. (my-check-chain2 <=? <=)
  356. (my-check-chain2 >=? >=)
  357. (my-check-chain2 not=? (lambda (x y) (not (= x y))))
  358. (my-check-chain3 </<? < <)
  359. (my-check-chain3 </<=? < <=)
  360. (my-check-chain3 <=/<? <= <)
  361. (my-check-chain3 <=/<=? <= <=)
  362. (my-check-chain3 >/>? > >)
  363. (my-check-chain3 >/>=? > >=)
  364. (my-check-chain3 >=/>? >= >)
  365. (my-check-chain3 >=/>=? >= >=)
  366. (my-check-chain chain=? =)
  367. (my-check-chain chain<? <)
  368. (my-check-chain chain>? >)
  369. (my-check-chain chain<=? <=)
  370. (my-check-chain chain>=? >=)
  371. ) ; check:predicates-from-compare
  372. ; pairwise-not=?
  373. (define pairwise-not=?:long-sequences
  374. (let ()
  375. (define (extremal-pivot-sequence r)
  376. ; The extremal pivot sequence of order r is a
  377. ; permutation of {0..2^(r+1)-2} such that the
  378. ; middle element is minimal, and this property
  379. ; holds recursively for each binary subdivision.
  380. ; This sequence exposes a naive implementation of
  381. ; pairwise-not=? chosing the middle element as pivot.
  382. (if (zero? r)
  383. '(0)
  384. (let* ((s (extremal-pivot-sequence (- r 1)))
  385. (ns (length s)))
  386. (append (list-ec (:list x s) (+ x 1))
  387. '(0)
  388. (list-ec (:list x s) (+ x ns 1))))))
  389. (list (list-ec (: i 4096) i)
  390. (list-ec (: i 4097 0 -1) i)
  391. (list-ec (: i 4099) (modulo (* 1003 i) 4099))
  392. (extremal-pivot-sequence 11))))
  393. (define pairwise-not=?:short-sequences
  394. (let ()
  395. (define (combinations/repeats n l)
  396. ; return list of all sublists of l of size n,
  397. ; the order of the elements occur in the sublists
  398. ; of the output is the same as in the input
  399. (let ((len (length l)))
  400. (cond
  401. ((= n 0) '())
  402. ((= n 1) (map list l))
  403. ((= len 1) (do ((r '() (cons (car l) r))
  404. (i n (- i 1)))
  405. ((= i 0) (list r))))
  406. (else (append (combinations/repeats n (cdr l))
  407. (map (lambda (c) (cons (car l) c))
  408. (combinations/repeats (- n 1) l)))))))
  409. (define (permutations l)
  410. ; return a list of all permutations of l
  411. (let ((len (length l)))
  412. (cond
  413. ((= len 0) '(()))
  414. ((= len 1) (list l))
  415. (else (apply append
  416. (map (lambda (p) (insert-every-where (car l) p))
  417. (permutations (cdr l))))))))
  418. (define (insert-every-where x xs)
  419. (let loop ((result '()) (before '()) (after xs))
  420. (let ((new (append before (cons x after))))
  421. (cond
  422. ((null? after) (cons new result))
  423. (else (loop (cons new result)
  424. (append before (list (car after)))
  425. (cdr after)))))))
  426. (define (sequences n max)
  427. (apply append
  428. (map permutations
  429. (combinations/repeats n (list-ec (: i max) i)))))
  430. (append-ec (: n 5) (sequences n 5))))
  431. (define (colliding-compare x y)
  432. (ci (modulo x 3) (modulo y 3)))
  433. (define (naive-pairwise-not=? compare . xs)
  434. (let ((xs (list->vector xs)))
  435. (every?-ec (:range i (- (vector-length xs) 1))
  436. (:let xs-i (vector-ref xs i))
  437. (:range j (+ i 1) (vector-length xs))
  438. (:let xs-j (vector-ref xs j))
  439. (not=? compare xs-i xs-j))))
  440. (define (check:pairwise-not=?)
  441. ; 0-ary, 1-ary
  442. (my-check (pairwise-not=? ci) => #t)
  443. (my-check (pairwise-not=? ci 0) => #t)
  444. ; 2-ary
  445. (my-check (pairwise-not=? ci 0 0) => #f)
  446. (my-check (pairwise-not=? ci 0 1) => #t)
  447. (my-check (pairwise-not=? ci 1 0) => #t)
  448. ; 3-ary
  449. (my-check (pairwise-not=? ci 0 0 0) => #f)
  450. (my-check (pairwise-not=? ci 0 0 1) => #f)
  451. (my-check (pairwise-not=? ci 0 1 0) => #f)
  452. (my-check (pairwise-not=? ci 1 0 0) => #f)
  453. (my-check (pairwise-not=? ci 1 1 0) => #f)
  454. (my-check (pairwise-not=? ci 1 0 1) => #f)
  455. (my-check (pairwise-not=? ci 0 1 1) => #f)
  456. (my-check (pairwise-not=? ci 0 1 2) => #t)
  457. (my-check (pairwise-not=? ci 0 2 1) => #t)
  458. (my-check (pairwise-not=? ci 1 2 0) => #t)
  459. (my-check (pairwise-not=? ci 1 0 2) => #t)
  460. (my-check (pairwise-not=? ci 2 0 1) => #t)
  461. (my-check (pairwise-not=? ci 2 1 0) => #t)
  462. ; n-ary, n large: [0..n-1], [n,n-1..1], 5^[0..96] mod 97
  463. (my-check (apply pairwise-not=? ci (list-ec (: i 10) i)) => #t)
  464. (my-check (apply pairwise-not=? ci (list-ec (: i 100) i)) => #t)
  465. (my-check (apply pairwise-not=? ci (list-ec (: i 1000) i)) => #t)
  466. (my-check (apply pairwise-not=? ci (list-ec (: i 10 0 -1) i)) => #t)
  467. (my-check (apply pairwise-not=? ci (list-ec (: i 100 0 -1) i)) => #t)
  468. (my-check (apply pairwise-not=? ci (list-ec (: i 1000 0 -1) i)) => #t)
  469. (my-check (apply pairwise-not=? ci
  470. (list-ec (: i 97) (modulo (* 5 i) 97)))
  471. => #t)
  472. ; bury another copy of 72 = 5^50 mod 97 in 5^[0..96] mod 97
  473. (my-check (apply pairwise-not=? ci
  474. (append (list-ec (: i 0 23) (modulo (* 5 i) 97))
  475. '(72)
  476. (list-ec (: i 23 97) (modulo (* 5 i) 97))))
  477. => #f)
  478. (my-check (apply pairwise-not=? ci
  479. (append (list-ec (: i 0 75) (modulo (* 5 i) 97))
  480. '(72)
  481. (list-ec (: i 75 97) (modulo (* 5 i) 97))))
  482. => #f)
  483. ; check if all arguments are used
  484. (my-check (arguments-used (pairwise-not=? ci 0)) => '(0))
  485. (my-check (arguments-used (pairwise-not=? ci 0 1)) => '(0 1))
  486. (my-check (arguments-used (pairwise-not=? ci 1 0)) => '(0 1))
  487. (my-check (arguments-used (pairwise-not=? ci 0 2 1)) => '(0 1 2))
  488. (my-check (arguments-used (pairwise-not=? ci 1 2 0)) => '(0 1 2))
  489. (my-check (arguments-used (pairwise-not=? ci 1 0 2)) => '(0 1 2))
  490. (my-check (arguments-used (pairwise-not=? ci 2 0 1)) => '(0 1 2))
  491. (my-check (arguments-used (pairwise-not=? ci 2 1 0)) => '(0 1 2))
  492. (my-check (arguments-used (pairwise-not=? ci 0 0 0 1 0 0 0 2 0 0 0 3))
  493. => '(0 1 2 3))
  494. ; Guess if the implementation is O(n log n):
  495. ; The test is run for 2^e pairwise unequal inputs, e >= 1,
  496. ; and the number of calls to the compare procedure is counted.
  497. ; all pairs: A = Binomial[2^e, 2] = 2^(2 e - 1) * (1 - 2^-e).
  498. ; divide and conquer: D = e 2^e.
  499. ; Since an implementation can be randomized, the actual count may
  500. ; be a random number. We put a threshold at 100 e 2^e and choose
  501. ; e such that A/D >= 150, i.e. e >= 12.
  502. ; The test is applied to several inputs that are known to cause
  503. ; trouble in simplistic sorting algorithms: (0..2^e-1), (2^e+1,2^e..1),
  504. ; a pseudo-random permutation, and a sequence with an extremal pivot
  505. ; at the center of each subsequence.
  506. (my-check-ec
  507. (:list input pairwise-not=?:long-sequences)
  508. (let ((compares 0))
  509. (apply pairwise-not=?
  510. (lambda (x y)
  511. (set! compares (+ compares 1))
  512. (ci x y))
  513. input)
  514. ; (display compares) (newline)
  515. (< compares (* 100 12 4096)))
  516. (length input))
  517. ; check many short sequences
  518. (my-check-ec
  519. (:list input pairwise-not=?:short-sequences)
  520. (eq?
  521. (apply pairwise-not=? colliding-compare input)
  522. (apply naive-pairwise-not=? colliding-compare input))
  523. input)
  524. ; check if the arguments are used for short sequences
  525. (my-check-ec
  526. (:list input pairwise-not=?:short-sequences)
  527. (let ((args '()))
  528. (apply pairwise-not=?
  529. (lambda (x y)
  530. (set! args (cons x (cons y args)))
  531. (colliding-compare x y))
  532. input)
  533. (equal? (list->set args) (list->set input)))
  534. input)
  535. ) ; check:pairwise-not=?
  536. ; min/max
  537. (define min/max:sequences
  538. (append pairwise-not=?:short-sequences
  539. pairwise-not=?:long-sequences))
  540. (define (check:min/max)
  541. ; all lists of length 1,2,3
  542. (my-check (min-compare ci 0) => 0)
  543. (my-check (min-compare ci 0 0) => 0)
  544. (my-check (min-compare ci 0 1) => 0)
  545. (my-check (min-compare ci 1 0) => 0)
  546. (my-check (min-compare ci 0 0 0) => 0)
  547. (my-check (min-compare ci 0 0 1) => 0)
  548. (my-check (min-compare ci 0 1 0) => 0)
  549. (my-check (min-compare ci 1 0 0) => 0)
  550. (my-check (min-compare ci 1 1 0) => 0)
  551. (my-check (min-compare ci 1 0 1) => 0)
  552. (my-check (min-compare ci 0 1 1) => 0)
  553. (my-check (min-compare ci 0 1 2) => 0)
  554. (my-check (min-compare ci 0 2 1) => 0)
  555. (my-check (min-compare ci 1 2 0) => 0)
  556. (my-check (min-compare ci 1 0 2) => 0)
  557. (my-check (min-compare ci 2 0 1) => 0)
  558. (my-check (min-compare ci 2 1 0) => 0)
  559. (my-check (max-compare ci 0) => 0)
  560. (my-check (max-compare ci 0 0) => 0)
  561. (my-check (max-compare ci 0 1) => 1)
  562. (my-check (max-compare ci 1 0) => 1)
  563. (my-check (max-compare ci 0 0 0) => 0)
  564. (my-check (max-compare ci 0 0 1) => 1)
  565. (my-check (max-compare ci 0 1 0) => 1)
  566. (my-check (max-compare ci 1 0 0) => 1)
  567. (my-check (max-compare ci 1 1 0) => 1)
  568. (my-check (max-compare ci 1 0 1) => 1)
  569. (my-check (max-compare ci 0 1 1) => 1)
  570. (my-check (max-compare ci 0 1 2) => 2)
  571. (my-check (max-compare ci 0 2 1) => 2)
  572. (my-check (max-compare ci 1 2 0) => 2)
  573. (my-check (max-compare ci 1 0 2) => 2)
  574. (my-check (max-compare ci 2 0 1) => 2)
  575. (my-check (max-compare ci 2 1 0) => 2)
  576. ; check that the first minimal value is returned
  577. (my-check (min-compare (pair-compare-car ci)
  578. '(0 1) '(0 2) '(0 3))
  579. => '(0 1))
  580. (my-check (max-compare (pair-compare-car ci)
  581. '(0 1) '(0 2) '(0 3))
  582. => '(0 1))
  583. ; check for many inputs
  584. (my-check-ec
  585. (:list input min/max:sequences)
  586. (= (apply min-compare ci input)
  587. (apply min (apply max input) input))
  588. input)
  589. (my-check-ec
  590. (:list input min/max:sequences)
  591. (= (apply max-compare ci input)
  592. (apply max (apply min input) input))
  593. input)
  594. ; Note the stupid extra argument in the apply for
  595. ; the standard min/max makes sure the elements are
  596. ; identical when apply truncates the arglist.
  597. ) ; check:min/max
  598. ; kth-largest
  599. (define kth-largest:sequences
  600. pairwise-not=?:short-sequences)
  601. (define (naive-kth-largest compare k . xs)
  602. (let ((vec (list->vector xs)))
  603. ; bubble sort: simple, stable, O(|xs|^2)
  604. (do-ec (:range n (- (vector-length vec) 1))
  605. (:range i 0 (- (- (vector-length vec) 1) n))
  606. (if>? (compare (vector-ref vec i)
  607. (vector-ref vec (+ i 1)))
  608. (let ((vec-i (vector-ref vec i)))
  609. (vector-set! vec i (vector-ref vec (+ i 1)))
  610. (vector-set! vec (+ i 1) vec-i))))
  611. (vector-ref vec (modulo k (vector-length vec)))))
  612. (define (check:kth-largest)
  613. ; check extensively against naive-kth-largest
  614. (my-check-ec
  615. (:list input kth-largest:sequences)
  616. (: k (- -2 (length input)) (+ (length input) 2))
  617. (= (apply naive-kth-largest colliding-compare k input)
  618. (apply kth-largest colliding-compare k input))
  619. (list input k))
  620. ) ;check:kth-largest
  621. ; compare-by< etc. procedures
  622. (define (check:compare-from-predicates)
  623. (my-check-compare
  624. (compare-by< <)
  625. my-integers)
  626. (my-check-compare
  627. (compare-by> >)
  628. my-integers)
  629. (my-check-compare
  630. (compare-by<= <=)
  631. my-integers)
  632. (my-check-compare
  633. (compare-by>= >=)
  634. my-integers)
  635. (my-check-compare
  636. (compare-by=/< = <)
  637. my-integers)
  638. (my-check-compare
  639. (compare-by=/> = >)
  640. my-integers)
  641. ; with explicit arguments
  642. (my-check-compare
  643. (lambda (x y) (compare-by< < x y))
  644. my-integers)
  645. (my-check-compare
  646. (lambda (x y) (compare-by> > x y))
  647. my-integers)
  648. (my-check-compare
  649. (lambda (x y) (compare-by<= <= x y))
  650. my-integers)
  651. (my-check-compare
  652. (lambda (x y) (compare-by>= >= x y))
  653. my-integers)
  654. (my-check-compare
  655. (lambda (x y) (compare-by=/< = < x y))
  656. my-integers)
  657. (my-check-compare
  658. (lambda (x y) (compare-by=/> = > x y))
  659. my-integers)
  660. ) ; check:compare-from-predicates
  661. (define (check:atomic)
  662. (my-check-compare boolean-compare my-booleans)
  663. (my-check-compare char-compare my-chars)
  664. (my-check-compare char-compare-ci my-chars-ci)
  665. (my-check-compare string-compare my-strings)
  666. (my-check-compare string-compare-ci my-strings-ci)
  667. (my-check-compare symbol-compare my-symbols)
  668. (my-check-compare integer-compare my-integers)
  669. (my-check-compare rational-compare my-rationals)
  670. (my-check-compare real-compare my-reals)
  671. (my-check-compare complex-compare my-complexes)
  672. (my-check-compare number-compare my-complexes)
  673. ) ; check:atomic
  674. (define (check:refine-select-cond)
  675. ; refine-compare
  676. (my-check-compare
  677. (lambda (x y) (refine-compare))
  678. '(#f))
  679. (my-check-compare
  680. (lambda (x y) (refine-compare (integer-compare x y)))
  681. my-integers)
  682. (my-check-compare
  683. (lambda (x y)
  684. (refine-compare (integer-compare (car x) (car y))
  685. (symbol-compare (cdr x) (cdr y))))
  686. '((1 . a) (1 . b) (2 . b) (2 . c) (3 . a) (3 . c)))
  687. (my-check-compare
  688. (lambda (x y)
  689. (refine-compare (integer-compare (car x) (car y))
  690. (symbol-compare (cadr x) (cadr y))
  691. (string-compare (caddr x) (caddr y))))
  692. '((1 a "a") (1 b "a") (1 b "b") (2 b "c") (2 c "a") (3 a "b") (3 c "b")))
  693. ; select-compare
  694. (my-check-compare
  695. (lambda (x y) (select-compare x y))
  696. '(#f))
  697. (my-check-compare
  698. (lambda (x y)
  699. (select-compare x y
  700. (integer? (ci x y))))
  701. my-integers)
  702. (my-check-compare
  703. (lambda (x y)
  704. (select-compare x y
  705. (pair? (integer-compare (car x) (car y))
  706. (symbol-compare (cdr x) (cdr y)))))
  707. '((1 . a) (1 . b) (2 . b) (2 . c) (3 . a) (3 . c)))
  708. (my-check-compare
  709. (lambda (x y)
  710. (select-compare x y
  711. (else (integer-compare x y))))
  712. my-integers)
  713. (my-check-compare
  714. (lambda (x y)
  715. (select-compare x y
  716. (else (integer-compare (car x) (car y))
  717. (symbol-compare (cdr x) (cdr y)))))
  718. '((1 . a) (1 . b) (2 . b) (2 . c) (3 . a) (3 . c)))
  719. (my-check-compare
  720. (lambda (x y)
  721. (select-compare x y
  722. (symbol? (symbol-compare x y))
  723. (string? (string-compare x y))))
  724. '(a b c "a" "b" "c" 1)) ; implicit (else 0)
  725. (my-check-compare
  726. (lambda (x y)
  727. (select-compare x y
  728. (symbol? (symbol-compare x y))
  729. (else (string-compare x y))))
  730. '(a b c "a" "b" "c"))
  731. ; test if arguments are only evaluated once
  732. (my-check
  733. (let ((nx 0) (ny 0) (nt 0))
  734. (select-compare (begin (set! nx (+ nx 1)) 1)
  735. (begin (set! ny (+ ny 1)) 2)
  736. ((lambda (z) (set! nt (+ nt 1)) #f) 0)
  737. ((lambda (z) (set! nt (+ nt 10)) #f) 0)
  738. ((lambda (z) (set! nt (+ nt 100)) #f) 0)
  739. (else 0))
  740. (list nx ny nt))
  741. => '(1 1 222))
  742. ; cond-compare
  743. (my-check-compare
  744. (lambda (x y) (cond-compare))
  745. '(#f))
  746. (my-check-compare
  747. (lambda (x y)
  748. (cond-compare
  749. (((integer? x) (integer? y)) (integer-compare x y))))
  750. my-integers)
  751. (my-check-compare
  752. (lambda (x y)
  753. (cond-compare
  754. (((pair? x) (pair? y)) (integer-compare (car x) (car y))
  755. (symbol-compare (cdr x) (cdr y)))))
  756. '((1 . a) (1 . b) (2 . b) (2 . c) (3 . a) (3 . c)))
  757. (my-check-compare
  758. (lambda (x y)
  759. (cond-compare
  760. (else (integer-compare x y))))
  761. my-integers)
  762. (my-check-compare
  763. (lambda (x y)
  764. (cond-compare
  765. (else (integer-compare (car x) (car y))
  766. (symbol-compare (cdr x) (cdr y)))))
  767. '((1 . a) (1 . b) (2 . b) (2 . c) (3 . a) (3 . c)))
  768. (my-check-compare
  769. (lambda (x y)
  770. (cond-compare
  771. (((symbol? x) (symbol? y)) (symbol-compare x y))
  772. (((string? x) (string? y)) (string-compare x y))))
  773. '(a b c "a" "b" "c" 1)) ; implicit (else 0)
  774. (my-check-compare
  775. (lambda (x y)
  776. (cond-compare
  777. (((symbol? x) (symbol? y)) (symbol-compare x y))
  778. (else (string-compare x y))))
  779. '(a b c "a" "b" "c"))
  780. ) ; check:refine-select-cond
  781. ; We define our own list/vector data structure
  782. ; as '(my-list x[1] .. x[n]), n >= 0, in order
  783. ; to make sure the default ops don't work on it.
  784. (define (my-list-checked obj)
  785. (if (and (list? obj) (eqv? (car obj) 'my-list))
  786. obj
  787. (error "expected my-list but received" obj)))
  788. (define (list->my-list list) (cons 'my-list list))
  789. (define (my-empty? x) (null? (cdr (my-list-checked x))))
  790. (define (my-head x) (cadr (my-list-checked x)))
  791. (define (my-tail x) (cons 'my-list (cddr (my-list-checked x))))
  792. (define (my-size x) (- (length (my-list-checked x)) 1))
  793. (define (my-ref x i) (list-ref (my-list-checked x) (+ i 1)))
  794. (define (check:data-structures)
  795. (my-check-compare
  796. (pair-compare-car ci)
  797. '((1 . b) (2 . a) (3 . c)))
  798. (my-check-compare
  799. (pair-compare-cdr ci)
  800. '((b . 1) (a . 2) (c . 3)))
  801. ; pair-compare
  802. (my-check-compare pair-compare my-null-or-pairs)
  803. (my-check-compare
  804. (lambda (x y) (pair-compare ci x y))
  805. my-null-or-pairs)
  806. (my-check-compare
  807. (lambda (x y) (pair-compare ci symbol-compare x y))
  808. '((1 . a) (1 . b) (2 . b) (2 . c) (3 . a)))
  809. ; list-compare
  810. (my-check-compare list-compare my-lists)
  811. (my-check-compare
  812. (lambda (x y) (list-compare ci x y))
  813. my-lists)
  814. (my-check-compare
  815. (lambda (x y) (list-compare x y my-empty? my-head my-tail))
  816. (map list->my-list my-lists))
  817. (my-check-compare
  818. (lambda (x y) (list-compare ci x y my-empty? my-head my-tail))
  819. (map list->my-list my-lists))
  820. ; list-compare-as-vector
  821. (my-check-compare list-compare-as-vector my-list-as-vectors)
  822. (my-check-compare
  823. (lambda (x y) (list-compare-as-vector ci x y))
  824. my-list-as-vectors)
  825. (my-check-compare
  826. (lambda (x y) (list-compare-as-vector x y my-empty? my-head my-tail))
  827. (map list->my-list my-list-as-vectors))
  828. (my-check-compare
  829. (lambda (x y) (list-compare-as-vector ci x y my-empty? my-head my-tail))
  830. (map list->my-list my-list-as-vectors))
  831. ; vector-compare
  832. (my-check-compare vector-compare my-vectors)
  833. (my-check-compare
  834. (lambda (x y) (vector-compare ci x y))
  835. my-vectors)
  836. (my-check-compare
  837. (lambda (x y) (vector-compare x y my-size my-ref))
  838. (map list->my-list my-list-as-vectors))
  839. (my-check-compare
  840. (lambda (x y) (vector-compare ci x y my-size my-ref))
  841. (map list->my-list my-list-as-vectors))
  842. ; vector-compare-as-list
  843. (my-check-compare vector-compare-as-list my-vector-as-lists)
  844. (my-check-compare
  845. (lambda (x y) (vector-compare-as-list ci x y))
  846. my-vector-as-lists)
  847. (my-check-compare
  848. (lambda (x y) (vector-compare-as-list x y my-size my-ref))
  849. (map list->my-list my-lists))
  850. (my-check-compare
  851. (lambda (x y) (vector-compare-as-list ci x y my-size my-ref))
  852. (map list->my-list my-lists))
  853. ) ; check:data-structures
  854. (define (check:default-compare)
  855. (my-check-compare default-compare my-objects)
  856. ; check if default-compare refines pair-compare
  857. (my-check-ec
  858. (:list x (index ix) my-objects)
  859. (:list y (index iy) my-objects)
  860. (:let c-coarse (pair-compare x y))
  861. (:let c-fine (default-compare x y))
  862. (or (eqv? c-coarse 0) (eqv? c-fine c-coarse))
  863. (list x y))
  864. ; check if default-compare passes on debug-compare
  865. (my-check-compare (debug-compare default-compare) my-objects)
  866. ) ; check:default-compare
  867. (define (sort-by-less xs pred) ; trivial quicksort
  868. (if (or (null? xs) (null? (cdr xs)))
  869. xs
  870. (append
  871. (sort-by-less (list-ec (:list x (cdr xs))
  872. (if (pred x (car xs)))
  873. x)
  874. pred)
  875. (list (car xs))
  876. (sort-by-less (list-ec (:list x (cdr xs))
  877. (if (not (pred x (car xs))))
  878. x)
  879. pred))))
  880. (define (check:more-examples)
  881. ; define recursive order on tree type (nodes are dotted pairs)
  882. (my-check-compare
  883. (letrec ((c (lambda (x y)
  884. (cond-compare (((null? x) (null? y)) 0)
  885. (else (pair-compare c c x y))))))
  886. c)
  887. (list '() (list '()) (list '() '()) (list (list '())))
  888. ;'(() (() . ()) (() . (() . ())) ((() . ()) . ())) ; Chicken can't parse this ?
  889. )
  890. ; redefine default-compare using select-compare
  891. (my-check-compare
  892. (letrec ((c (lambda (x y)
  893. (select-compare x y
  894. (null? 0)
  895. (pair? (pair-compare c c x y))
  896. (boolean? (boolean-compare x y))
  897. (char? (char-compare x y))
  898. (string? (string-compare x y))
  899. (symbol? (symbol-compare x y))
  900. (number? (number-compare x y))
  901. (vector? (vector-compare c x y))
  902. (else (error "unrecognized type in c" x y))))))
  903. c)
  904. my-objects)
  905. ; redefine default-compare using cond-compare
  906. (my-check-compare
  907. (letrec ((c (lambda (x y)
  908. (cond-compare
  909. (((null? x) (null? y)) 0)
  910. (((pair? x) (pair? y)) (pair-compare c c x y))
  911. (((boolean? x) (boolean? y)) (boolean-compare x y))
  912. (((char? x) (char? y)) (char-compare x y))
  913. (((string? x) (string? y)) (string-compare x y))
  914. (((symbol? x) (symbol? y)) (symbol-compare x y))
  915. (((number? x) (number? y)) (number-compare x y))
  916. (((vector? x) (vector? y)) (vector-compare c x y))
  917. (else (error "unrecognized type in c" x y))))))
  918. c)
  919. my-objects)
  920. ; compare strings with character order reversed
  921. (my-check-compare
  922. (lambda (x y)
  923. (vector-compare-as-list
  924. (lambda (x y) (char-compare y x))
  925. x y string-length string-ref))
  926. '("" "b" "bb" "ba" "a" "ab" "aa"))
  927. ; examples from SRFI text for <? etc.
  928. (my-check (>? "laugh" "LOUD") => #t)
  929. (my-check (<? string-compare-ci "laugh" "LOUD") => #t)
  930. (my-check (sort-by-less '(1 a "b") (<?)) => '("b" a 1))
  931. (my-check (sort-by-less '(1 a "b") (>?)) => '(1 a "b"))
  932. ) ; check:more-examples
  933. ; Real life examples
  934. ; ==================
  935. ; (update/insert compare x s)
  936. ; inserts x into list s, or updates an equivalent element by x.
  937. ; It is assumed that s is sorted with respect to compare,
  938. ; i.e. (apply chain<=? compare s). The result is a list with x
  939. ; replacing the first element s[i] for which (=? compare s[i] x),
  940. ; or with x inserted in the proper place.
  941. ; The algorithm uses linear insertion from the front.
  942. (define (insert/update compare x s) ; insert x into list s, or update
  943. (if (null? s)
  944. (list x)
  945. (if3 (compare x (car s))
  946. (cons x s)
  947. (cons x (cdr s))
  948. (cons (car s) (insert/update compare x (cdr s))))))
  949. ; (index-in-vector compare vec x)
  950. ; an index i such that (=? compare vec[i] x), or #f if there is none.
  951. ; It is assumed that s is sorted with respect to compare,
  952. ; i.e. (apply chain<=? compare (vector->list s)). If there are
  953. ; several elements equivalent to x then it is unspecified which
  954. ; these is chosen.
  955. ; The algorithm uses binary search.
  956. (define (index-in-vector compare vec x)
  957. (let binary-search ((lo -1) (hi (vector-length vec)))
  958. ; invariant: vec[lo] < x < vec[hi]
  959. (if (=? (- hi lo) 1)
  960. #f
  961. (let ((mi (quotient (+ lo hi) 2)))
  962. (if3 (compare x (vector-ref vec mi))
  963. (binary-search lo mi)
  964. mi
  965. (binary-search mi hi))))))
  966. ; Run the checks
  967. ; ==============
  968. ; comment in/out as needed
  969. (with-test-prefix "atomic" (check:atomic))
  970. (with-test-prefix "if3" (check:if3))
  971. (with-test-prefix "ifs" (check:ifs))
  972. (with-test-prefix "predicates-form-compare"
  973. (check:predicates-from-compare))
  974. (with-test-prefix "pairwise-not=?"
  975. (check:pairwise-not=?))
  976. (with-test-prefix "min/max"
  977. (check:min/max))
  978. (with-test-prefix "kth-largest"
  979. (check:kth-largest))
  980. (with-test-prefix "compare-from-predicates"
  981. (check:compare-from-predicates))
  982. (with-test-prefix "refine-select-cond"
  983. (check:refine-select-cond))
  984. (with-test-prefix "data-structures"
  985. (check:data-structures))
  986. (with-test-prefix "default-compare"
  987. (check:default-compare))
  988. (with-test-prefix "more-examples"
  989. (check:more-examples))