inversion-list.scm 11 KB

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