inversion-list.scm 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Mike Sperber
  3. ; Copyright (c) 2005-2006 by Basis Technology Corporation.
  4. ; Inversion lists are representations for sets of integers,
  5. ; represented as sorted sets of ranges.
  6. ; This was taken from Chapter 13 of Richard Gillam: Unicode Demystified.
  7. ; Mike doesn't know what the original source is.
  8. ; This was written as support code for the implementation of SRFI 14,
  9. ; which is why there's so many exports here nobody really needs.
  10. (define-record-type inversion-list :inversion-list
  11. (make-inversion-list min max
  12. range-vector)
  13. inversion-list?
  14. ;; minimum element, needed for complement & difference
  15. (min inversion-list-min)
  16. ;; maximum element, needed size
  17. ;; we pretty much assume consistency for union / intersection for MIN and MAX
  18. (max inversion-list-max)
  19. ;; consecutive elements are paired to form ranges of the form
  20. ;; [ (vector-ref v i) (vector-ref v (+ 1 i)) )
  21. ;; (except the last one, possibly)
  22. (range-vector inversion-list-range-vector))
  23. (define-record-discloser :inversion-list
  24. (lambda (r)
  25. (list 'inversion-list
  26. (inversion-list-min r) (inversion-list-max r)
  27. (inversion-list-range-vector r))))
  28. (define (make-empty-inversion-list min max)
  29. (make-inversion-list min max '#()))
  30. (define (inversion-list-member? n i-list)
  31. (let ((ranges (inversion-list-range-vector i-list)))
  32. (let loop ((low 0)
  33. (high (vector-length ranges)))
  34. (if (< low high)
  35. (let ((mid (quotient (+ low high) 2)))
  36. (if (>= n (vector-ref ranges mid))
  37. (loop (+ 1 mid) high)
  38. (loop low mid)))
  39. (odd? high)))))
  40. (define (inversion-list-complement i-list)
  41. (let* ((ranges (inversion-list-range-vector i-list))
  42. (min (inversion-list-min i-list))
  43. (max (inversion-list-max i-list))
  44. (size (vector-length ranges)))
  45. (make-inversion-list
  46. min max
  47. (cond
  48. ((zero? size)
  49. (vector min))
  50. ((not (= min (vector-ref ranges 0)))
  51. (if (and (even? size)
  52. (= max (vector-ref ranges (- size 1))))
  53. (let ((result (make-vector size)))
  54. (vector-set! result 0 min)
  55. (vector-copy! ranges 0 result 1 (- size 1))
  56. result)
  57. (let ((result (make-vector (+ 1 size))))
  58. (vector-set! result 0 min)
  59. (vector-copy! ranges 0 result 1 size)
  60. result)))
  61. ((and (even? size)
  62. (= max (vector-ref ranges (- size 1))))
  63. (let ((result (make-vector (- size 2))))
  64. (vector-copy! ranges 1 result 0 (- size 2))
  65. result))
  66. (else
  67. (let ((result (make-vector (- size 1))))
  68. (vector-copy! ranges 1 result 0 (- size 1))
  69. result))))))
  70. (define (make-inversion-list-union/intersection
  71. proc-thunk ; for CALL-ERROR
  72. write-increment-count write-decrement-count
  73. process-first? decrement-count?
  74. middle-increment
  75. copy-extra-count)
  76. (lambda (i-list-1 i-list-2)
  77. (if (or (not (= (inversion-list-min i-list-1)
  78. (inversion-list-min i-list-2)))
  79. (not (= (inversion-list-max i-list-1)
  80. (inversion-list-max i-list-2))))
  81. (assertion-violation 'make-inversion-list-union/intersection
  82. "min/max mismatch" (proc-thunk) i-list-1 i-list-2))
  83. (let ((ranges-1 (inversion-list-range-vector i-list-1))
  84. (ranges-2 (inversion-list-range-vector i-list-2))
  85. (min (inversion-list-min i-list-1))
  86. (max (inversion-list-max i-list-1)))
  87. (let ((size-1 (vector-length ranges-1))
  88. (size-2 (vector-length ranges-2)))
  89. (let ((temp (make-vector (+ size-1 size-2))))
  90. (let loop ((index-1 0) (index-2 0)
  91. (count 0)
  92. (index-result 0))
  93. (if (and (< index-1 size-1)
  94. (< index-2 size-2))
  95. (let ((el-1 (vector-ref ranges-1 index-1))
  96. (el-2 (vector-ref ranges-2 index-2)))
  97. (call-with-values
  98. (lambda ()
  99. (if (or (< el-1 el-2)
  100. (and (= el-1 el-2)
  101. (process-first? index-1)))
  102. (values index-1 el-1 (+ 1 index-1) index-2)
  103. (values index-2 el-2 index-1 (+ 1 index-2))))
  104. (lambda (index el index-1 index-2)
  105. (if (even? index)
  106. (if (= write-increment-count count)
  107. (begin
  108. (vector-set! temp index-result el)
  109. (loop index-1 index-2 (+ 1 count) (+ 1 index-result)))
  110. (loop index-1 index-2 (+ 1 count) index-result))
  111. (if (= write-decrement-count count)
  112. (begin
  113. (vector-set! temp index-result el)
  114. (loop index-1 index-2 (- count 1) (+ 1 index-result)))
  115. (loop index-1 index-2 (- count 1) index-result))))))
  116. (let* ((count
  117. (if (or (and (not (= index-1 size-1))
  118. (decrement-count? index-1))
  119. (and (not (= index-2 size-2))
  120. (decrement-count? index-2)))
  121. (+ count middle-increment)
  122. count))
  123. (result-size
  124. (if (= copy-extra-count count)
  125. (+ index-result
  126. (- size-1 index-1)
  127. (- size-2 index-2))
  128. index-result))
  129. (result (make-vector result-size)))
  130. (vector-copy! temp 0 result 0 index-result)
  131. (if (= copy-extra-count count)
  132. (begin
  133. (vector-copy! ranges-1 index-1 result index-result
  134. (- size-1 index-1))
  135. (vector-copy! ranges-2 index-2 result index-result
  136. (- size-2 index-2))))
  137. (make-inversion-list min max result)))))))))
  138. ; for associative procedures only
  139. (define (binary->n-ary proc/2)
  140. (lambda (arg-1 . args)
  141. (if (and (pair? args)
  142. (null? (cdr args)))
  143. (proc/2 arg-1 (car args))
  144. (let loop ((args args)
  145. (result arg-1))
  146. (if (null? args)
  147. result
  148. (loop (cdr args) (proc/2 result (car args))))))))
  149. (define inversion-list-union
  150. (binary->n-ary
  151. (make-inversion-list-union/intersection (lambda () inversion-list-union)
  152. 0 1 even? odd? -1 0)))
  153. (define inversion-list-intersection
  154. (binary->n-ary
  155. (make-inversion-list-union/intersection (lambda () inversion-list-intersection)
  156. 1 2 odd? even? +1 2)))
  157. (define inversion-list-difference
  158. (binary->n-ary
  159. (lambda (i-list-1 i-list-2)
  160. (inversion-list-intersection i-list-1
  161. (inversion-list-complement i-list-2)))))
  162. (define (number->inversion-list min max n)
  163. (if (or (< n min)
  164. (>= n max))
  165. (assertion-violation 'number->inversion-list "invalid number"
  166. min max n))
  167. (make-inversion-list min max
  168. (if (= n (- max 1))
  169. (vector n)
  170. (vector n (+ n 1)))))
  171. (define (numbers->inversion-list min max . numbers)
  172. (cond
  173. ((null? numbers) (make-empty-inversion-list min max))
  174. ((null? (cdr numbers)) (number->inversion-list min max (car numbers)))
  175. (else
  176. (let loop ((numbers (cdr numbers))
  177. (i-list (number->inversion-list min max (car numbers))))
  178. (if (null? numbers)
  179. i-list
  180. (loop (cdr numbers)
  181. (inversion-list-union
  182. i-list
  183. (number->inversion-list min max (car numbers)))))))))
  184. (define (range->inversion-list min max left right)
  185. (if (or (> min max)
  186. (> left right)
  187. (< left min)
  188. (> right max))
  189. (assertion-violation 'range->inversion-list "invalid range"
  190. min max left right))
  191. (make-inversion-list min max
  192. (if (= right max)
  193. (vector left)
  194. (vector left right))))
  195. (define (ranges->inversion-list min max . ranges)
  196. (let loop ((ranges ranges)
  197. (result (make-empty-inversion-list min max)))
  198. (if (null? ranges)
  199. result
  200. (let ((range-pair (car ranges)))
  201. (let ((left (car range-pair))
  202. (right (cdr range-pair)))
  203. (if (not (and (number? left)
  204. (number? right)))
  205. (assertion-violation 'ranges->inversion-list "invalid range"
  206. min max (cons left right)))
  207. (loop (cdr ranges)
  208. (inversion-list-union result
  209. (range->inversion-list min max left right))))))))
  210. (define (inversion-list-adjoin i-list . numbers)
  211. (inversion-list-union i-list
  212. (apply
  213. numbers->inversion-list
  214. (inversion-list-min i-list)
  215. (inversion-list-max i-list)
  216. numbers)))
  217. (define (inversion-list-remove i-list . numbers)
  218. (inversion-list-difference i-list
  219. (apply
  220. numbers->inversion-list
  221. (inversion-list-min i-list)
  222. (inversion-list-max i-list)
  223. numbers)))
  224. (define (inversion-list-size i-list)
  225. (let* ((ranges (inversion-list-range-vector i-list))
  226. (size (vector-length ranges)))
  227. (let loop ((index 0)
  228. (count 0))
  229. (cond
  230. ((>= index size) count)
  231. ((= (+ 1 index) size)
  232. (+ count (- (inversion-list-max i-list)
  233. (vector-ref ranges index))))
  234. (else
  235. (loop (+ 2 index)
  236. (+ count
  237. (- (vector-ref ranges (+ 1 index))
  238. (vector-ref ranges index)))))))))
  239. (define (inversion-list=? i-list-1 i-list-2)
  240. (and (= (inversion-list-min i-list-1)
  241. (inversion-list-min i-list-2))
  242. (= (inversion-list-max i-list-1)
  243. (inversion-list-max i-list-2))
  244. (equal? (inversion-list-range-vector i-list-1)
  245. (inversion-list-range-vector i-list-2))))
  246. (define (inversion-list-copy i-list)
  247. (make-inversion-list (inversion-list-min i-list)
  248. (inversion-list-max i-list)
  249. (vector-copy (inversion-list-range-vector i-list))))
  250. ; Iterate over the elements until DONE? (applied to the accumulator)
  251. ; returns #t
  252. (define (inversion-list-fold/done? kons knil done? i-list)
  253. (let* ((ranges (inversion-list-range-vector i-list))
  254. (size (vector-length ranges)))
  255. (let loop ((v knil)
  256. (i 0))
  257. (if (>= i size)
  258. v
  259. (let ((left (vector-ref ranges i))
  260. (right (if (< i (- size 1))
  261. (vector-ref ranges (+ 1 i))
  262. (inversion-list-max i-list))))
  263. (let inner-loop ((v v) (n left))
  264. (if (>= n right)
  265. (loop v (+ 2 i))
  266. (let ((v (kons n v)))
  267. (if (done? v)
  268. v
  269. (inner-loop v (+ 1 n)))))))))))
  270. ; It never ends with Olin
  271. (define-record-type inversion-list-cursor :inversion-list-cursor
  272. (make-inversion-list-cursor index number)
  273. inversion-list-cursor?
  274. ;; index into the range vector (always even), #f if we're at the end
  275. (index inversion-list-cursor-index)
  276. ;; number within that index
  277. (number inversion-list-cursor-number))
  278. (define (inversion-list-cursor i-list)
  279. (let ((ranges (inversion-list-range-vector i-list)))
  280. (if (zero? (vector-length ranges))
  281. (make-inversion-list-cursor #f #f)
  282. (make-inversion-list-cursor 0 (vector-ref ranges 0)))))
  283. (define (inversion-list-cursor-at-end? cursor)
  284. (not (inversion-list-cursor-index cursor)))
  285. (define (inversion-list-cursor-next i-list cursor)
  286. (let ((index (inversion-list-cursor-index cursor))
  287. (number (inversion-list-cursor-number cursor)))
  288. (let* ((ranges (inversion-list-range-vector i-list))
  289. (size (vector-length ranges))
  290. (right (if (>= (+ index 1) size)
  291. (inversion-list-max i-list)
  292. (vector-ref ranges (+ index 1)))))
  293. (cond
  294. ((< number (- right 1))
  295. (make-inversion-list-cursor index (+ 1 number)))
  296. ((< (+ index 2) size)
  297. (make-inversion-list-cursor (+ index 2)
  298. (vector-ref ranges (+ index 2))))
  299. (else
  300. (make-inversion-list-cursor #f #f))))))
  301. (define (inversion-list-cursor-ref cursor)
  302. (inversion-list-cursor-number cursor))
  303. ; Uses the same method as Olin's reference implementation for SRFI 14.
  304. (define (inversion-list-hash i-list bound)
  305. (let ((mask (let loop ((i #x10000)) ; skip first 16 iterations
  306. (if (>= i bound)
  307. (- i 1)
  308. (loop (+ i i))))))
  309. (let* ((range-vector (inversion-list-range-vector i-list))
  310. (size (vector-length range-vector)))
  311. (let loop ((i 0) (ans 0))
  312. (if (>= i size)
  313. (modulo ans bound)
  314. (loop (+ 1 i)
  315. (bitwise-and mask
  316. (+ (* 37 ans)
  317. (vector-ref range-vector i)))))))))
  318. ;; Utilities
  319. (define (vector-copy! source source-start dest dest-start count)
  320. (let loop ((i 0))
  321. (if (< i count)
  322. (begin
  323. (vector-set! dest (+ dest-start i)
  324. (vector-ref source (+ source-start i)))
  325. (loop (+ 1 i))))))
  326. (define (vector-copy v)
  327. (let* ((size (vector-length v))
  328. (copy (make-vector size)))
  329. (vector-copy! v 0 copy 0 size)
  330. copy))