intset.scm 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831
  1. ;;; Functional name maps
  2. ;;; Copyright (C) 2014, 2015, 2017 Free Software Foundation, Inc.
  3. ;;;
  4. ;;; This library is free software: you can redistribute it and/or modify
  5. ;;; it under the terms of the GNU Lesser General Public License as
  6. ;;; published by the Free Software Foundation, either version 3 of the
  7. ;;; License, or (at your option) any later version.
  8. ;;;
  9. ;;; This library is distributed in the hope that it will be useful, but
  10. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. ;;; Lesser General Public License for more details.
  13. ;;;
  14. ;;; You should have received a copy of the GNU Lesser General Public
  15. ;;; License along with this program. If not, see
  16. ;;; <http://www.gnu.org/licenses/>.
  17. ;;; Commentary:
  18. ;;;
  19. ;;; A persistent, functional data structure representing a set of
  20. ;;; integers as a tree whose branches are vectors and whose leaves are
  21. ;;; fixnums. Intsets are careful to preserve sub-structure, in the
  22. ;;; sense of eq?, whereever possible.
  23. ;;;
  24. ;;; Code:
  25. (define-module (language cps intset)
  26. #:use-module (rnrs bytevectors)
  27. #:use-module (srfi srfi-9)
  28. #:use-module (srfi srfi-9 gnu)
  29. #:use-module (ice-9 match)
  30. #:use-module ((ice-9 threads) #:select (current-thread))
  31. #:export (empty-intset
  32. intset?
  33. transient-intset?
  34. persistent-intset
  35. transient-intset
  36. intset
  37. intset-add
  38. intset-add!
  39. intset-remove
  40. intset-ref
  41. intset-next
  42. intset-prev
  43. intset-fold
  44. intset-fold-right
  45. intset-union
  46. intset-intersect
  47. intset-subtract
  48. bitvector->intset))
  49. (define-syntax-rule (define-inline name val)
  50. (define-syntax name (identifier-syntax val)))
  51. (eval-when (expand)
  52. (use-modules (system base target))
  53. (define-syntax compile-time-cond
  54. (lambda (x)
  55. (syntax-case x (else)
  56. ((_ (test body ...) rest ...)
  57. (if (primitive-eval (syntax->datum #'test))
  58. #'(begin body ...)
  59. #'(begin (compile-time-cond rest ...))))
  60. ((_ (else body ...))
  61. #'(begin body ...))
  62. ((_)
  63. (error "no compile-time-cond expression matched"))))))
  64. (compile-time-cond
  65. ((eqv? (target-word-size) 4)
  66. (define-inline *leaf-bits* 4))
  67. ((eqv? (target-word-size) 8)
  68. (define-inline *leaf-bits* 5)))
  69. ;; FIXME: This should make an actual atomic reference.
  70. (define-inlinable (make-atomic-reference value)
  71. (list value))
  72. (define-inlinable (get-atomic-reference reference)
  73. (car reference))
  74. (define-inlinable (set-atomic-reference! reference value)
  75. (set-car! reference value))
  76. (define-inline *leaf-size* (ash 1 *leaf-bits*))
  77. (define-inline *leaf-mask* (1- *leaf-size*))
  78. (define-inline *branch-bits* 3)
  79. (define-inline *branch-size* (ash 1 *branch-bits*))
  80. (define-inline *branch-size-with-edit* (1+ *branch-size*))
  81. (define-inline *edit-index* *branch-size*)
  82. (define-inline *branch-mask* (1- *branch-size*))
  83. (define-record-type <intset>
  84. (make-intset min shift root)
  85. intset?
  86. (min intset-min)
  87. (shift intset-shift)
  88. (root intset-root))
  89. (define-record-type <transient-intset>
  90. (make-transient-intset min shift root edit)
  91. transient-intset?
  92. (min transient-intset-min set-transient-intset-min!)
  93. (shift transient-intset-shift set-transient-intset-shift!)
  94. (root transient-intset-root set-transient-intset-root!)
  95. (edit transient-intset-edit set-transient-intset-edit!))
  96. (define-inlinable (clone-leaf-and-set leaf i val)
  97. (if val
  98. (if leaf
  99. (logior leaf (ash 1 i))
  100. (ash 1 i))
  101. (if leaf
  102. (logand leaf (lognot (ash 1 i)))
  103. #f)))
  104. (define (leaf-empty? leaf)
  105. (zero? leaf))
  106. (define-inlinable (new-branch edit)
  107. (let ((vec (make-vector *branch-size-with-edit* #f)))
  108. (when edit (vector-set! vec *edit-index* edit))
  109. vec))
  110. (define-inlinable (clone-branch-and-set branch i elt)
  111. (let ((new (new-branch #f)))
  112. (when branch
  113. (let lp ((n 0))
  114. (when (< n *branch-size*)
  115. (vector-set! new n (vector-ref branch n))
  116. (lp (1+ n)))))
  117. (vector-set! new i elt)
  118. new))
  119. (define-inlinable (assert-readable! root-edit)
  120. (unless (eq? (get-atomic-reference root-edit) (current-thread))
  121. (error "Transient intset owned by another thread" root-edit)))
  122. (define-inlinable (writable-branch branch root-edit)
  123. (let ((edit (vector-ref branch *edit-index*)))
  124. (if (eq? root-edit edit)
  125. branch
  126. (clone-branch-and-set branch *edit-index* root-edit))))
  127. (define (branch-empty? branch)
  128. (let lp ((i 0))
  129. (or (= i *branch-size*)
  130. (and (not (vector-ref branch i))
  131. (lp (1+ i))))))
  132. (define-inlinable (round-down min shift)
  133. (logand min (lognot (1- (ash 1 shift)))))
  134. (define empty-intset (make-intset 0 *leaf-bits* #f))
  135. (define (add-level min shift root)
  136. (let* ((shift* (+ shift *branch-bits*))
  137. (min* (round-down min shift*))
  138. (idx (logand (ash (- min min*) (- shift)) *branch-mask*)))
  139. (make-intset min* shift* (clone-branch-and-set #f idx root))))
  140. (define (make-intset/prune min shift root)
  141. (cond
  142. ((not root)
  143. empty-intset)
  144. ((= shift *leaf-bits*)
  145. (make-intset min shift root))
  146. (else
  147. (let lp ((i 0) (elt #f))
  148. (cond
  149. ((< i *branch-size*)
  150. (if (vector-ref root i)
  151. (if elt
  152. (make-intset min shift root)
  153. (lp (1+ i) i))
  154. (lp (1+ i) elt)))
  155. (elt
  156. (let ((shift (- shift *branch-bits*)))
  157. (make-intset/prune (+ min (ash elt shift))
  158. shift
  159. (vector-ref root elt))))
  160. ;; Shouldn't be reached...
  161. (else empty-intset))))))
  162. (define* (transient-intset #:optional (source empty-intset))
  163. (match source
  164. (($ <transient-intset> min shift root edit)
  165. (assert-readable! edit)
  166. source)
  167. (($ <intset> min shift root)
  168. (let ((edit (make-atomic-reference (current-thread))))
  169. (make-transient-intset min shift root edit)))))
  170. (define* (persistent-intset #:optional (source empty-intset))
  171. (match source
  172. (($ <transient-intset> min shift root edit)
  173. (assert-readable! edit)
  174. ;; Make a fresh reference, causing any further operations on this
  175. ;; transient to clone its root afresh.
  176. (set-transient-intset-edit! source
  177. (make-atomic-reference (current-thread)))
  178. ;; Clear the reference to the current thread, causing our edited
  179. ;; data structures to be persistent again.
  180. (set-atomic-reference! edit #f)
  181. (if min
  182. (make-intset min shift root)
  183. empty-intset))
  184. (($ <intset>)
  185. source)))
  186. (define (intset-add! bs i)
  187. (define (adjoin-leaf i root)
  188. (clone-leaf-and-set root (logand i *leaf-mask*) #t))
  189. (define (ensure-branch! root idx)
  190. (let ((edit (vector-ref root *edit-index*)))
  191. (match (vector-ref root idx)
  192. (#f (let ((v (new-branch edit)))
  193. (vector-set! root idx v)
  194. v))
  195. (v (let ((v* (writable-branch v edit)))
  196. (unless (eq? v v*)
  197. (vector-set! root idx v*))
  198. v*)))))
  199. (define (adjoin-branch! i shift root)
  200. (let* ((shift (- shift *branch-bits*))
  201. (idx (logand (ash i (- shift)) *branch-mask*)))
  202. (cond
  203. ((= shift *leaf-bits*)
  204. (vector-set! root idx (adjoin-leaf i (vector-ref root idx))))
  205. (else
  206. (adjoin-branch! i shift (ensure-branch! root idx))))))
  207. (match bs
  208. (($ <transient-intset> min shift root edit)
  209. (assert-readable! edit)
  210. (cond
  211. ((< i 0)
  212. ;; The power-of-two spanning trick doesn't work across 0.
  213. (error "Intsets can only hold non-negative integers." i))
  214. ((not root)
  215. ;; Add first element.
  216. (let ((min (round-down i shift)))
  217. (set-transient-intset-min! bs min)
  218. (set-transient-intset-shift! bs *leaf-bits*)
  219. (set-transient-intset-root! bs (adjoin-leaf (- i min) root))))
  220. ((and (<= min i) (< i (+ min (ash 1 shift))))
  221. ;; Add element to set; level will not change.
  222. (if (= shift *leaf-bits*)
  223. (set-transient-intset-root! bs (adjoin-leaf (- i min) root))
  224. (let ((root* (writable-branch root edit)))
  225. (unless (eq? root root*)
  226. (set-transient-intset-root! bs root*))
  227. (adjoin-branch! (- i min) shift root*))))
  228. (else
  229. (let lp ((min min)
  230. (shift shift)
  231. (root (if (eqv? shift *leaf-bits*)
  232. root
  233. (writable-branch root edit))))
  234. (let* ((shift* (+ shift *branch-bits*))
  235. (min* (round-down min shift*))
  236. (idx (logand (ash (- min min*) (- shift)) *branch-mask*))
  237. (root* (new-branch edit)))
  238. (vector-set! root* idx root)
  239. (cond
  240. ((and (<= min* i) (< i (+ min* (ash 1 shift*))))
  241. (set-transient-intset-min! bs min*)
  242. (set-transient-intset-shift! bs shift*)
  243. (set-transient-intset-root! bs root*)
  244. (adjoin-branch! (- i min*) shift* root*))
  245. (else
  246. (lp min* shift* root*)))))))
  247. bs)
  248. (($ <intset>)
  249. (intset-add! (transient-intset bs) i))))
  250. (define (intset-add bs i)
  251. (define (adjoin i shift root)
  252. (cond
  253. ((= shift *leaf-bits*)
  254. (let ((idx (logand i *leaf-mask*)))
  255. (if (and root (logbit? idx root))
  256. root
  257. (clone-leaf-and-set root idx #t))))
  258. (else
  259. (let* ((shift (- shift *branch-bits*))
  260. (idx (logand (ash i (- shift)) *branch-mask*))
  261. (node (and root (vector-ref root idx)))
  262. (new-node (adjoin i shift node)))
  263. (if (eq? node new-node)
  264. root
  265. (clone-branch-and-set root idx new-node))))))
  266. (match bs
  267. (($ <intset> min shift root)
  268. (cond
  269. ((< i 0)
  270. ;; The power-of-two spanning trick doesn't work across 0.
  271. (error "Intsets can only hold non-negative integers." i))
  272. ((not root)
  273. ;; Add first element.
  274. (let ((min (round-down i shift)))
  275. (make-intset min *leaf-bits*
  276. (adjoin (- i min) *leaf-bits* root))))
  277. ((and (<= min i) (< i (+ min (ash 1 shift))))
  278. ;; Add element to set; level will not change.
  279. (let ((old-root root)
  280. (root (adjoin (- i min) shift root)))
  281. (if (eq? root old-root)
  282. bs
  283. (make-intset min shift root))))
  284. ((< i min)
  285. ;; Rebuild the tree by unioning two intsets.
  286. (intset-union (intset-add empty-intset i) bs))
  287. (else
  288. ;; Add a new level and try again.
  289. (intset-add (add-level min shift root) i))))))
  290. (define-syntax intset
  291. (syntax-rules ()
  292. ((intset) empty-intset)
  293. ((intset x x* ...) (intset-add (intset x* ...) x))))
  294. (define (intset-remove bs i)
  295. (define (remove i shift root)
  296. (cond
  297. ((= shift *leaf-bits*)
  298. (let ((idx (logand i *leaf-mask*)))
  299. (if (logbit? idx root)
  300. (let ((root (clone-leaf-and-set root idx #f)))
  301. (and (not (leaf-empty? root)) root))
  302. root)))
  303. (else
  304. (let* ((shift (- shift *branch-bits*))
  305. (idx (logand (ash i (- shift)) *branch-mask*)))
  306. (cond
  307. ((vector-ref root idx)
  308. => (lambda (node)
  309. (let ((new-node (remove i shift node)))
  310. (if (eq? node new-node)
  311. root
  312. (let ((root (clone-branch-and-set root idx new-node)))
  313. (and (or new-node (not (branch-empty? root)))
  314. root))))))
  315. (else root))))))
  316. (match bs
  317. (($ <intset> min shift root)
  318. (cond
  319. ((not root) bs)
  320. ((and (<= min i) (< i (+ min (ash 1 shift))))
  321. (let ((old-root root)
  322. (root (remove (- i min) shift root)))
  323. (if (eq? root old-root)
  324. bs
  325. (make-intset/prune min shift root))))
  326. (else bs)))))
  327. (define (intset-ref bs i)
  328. (define (ref min shift root)
  329. (and (<= min i) (< i (+ min (ash 1 shift)))
  330. (let ((i (- i min)))
  331. (let lp ((node root) (shift shift))
  332. (and node
  333. (if (= shift *leaf-bits*)
  334. (logbit? (logand i *leaf-mask*) node)
  335. (let* ((shift (- shift *branch-bits*))
  336. (idx (logand (ash i (- shift)) *branch-mask*)))
  337. (lp (vector-ref node idx) shift))))))))
  338. (match bs
  339. (($ <intset> min shift root)
  340. (ref min shift root))
  341. (($ <transient-intset> min shift root edit)
  342. (assert-readable! edit)
  343. (ref min shift root))))
  344. (define* (intset-next bs #:optional i)
  345. (define (visit-leaf node i)
  346. (let lp ((idx (logand i *leaf-mask*)))
  347. (if (logbit? idx node)
  348. (logior (logand i (lognot *leaf-mask*)) idx)
  349. (let ((idx (1+ idx)))
  350. (and (< idx *leaf-size*)
  351. (lp idx))))))
  352. (define (visit-branch node shift i)
  353. (let lp ((i i) (idx (logand (ash i (- shift)) *branch-mask*)))
  354. (and (< idx *branch-size*)
  355. (or (let ((node (vector-ref node idx)))
  356. (and node (visit-node node shift i)))
  357. (let ((inc (ash 1 shift)))
  358. (lp (+ (round-down i shift) inc) (1+ idx)))))))
  359. (define (visit-node node shift i)
  360. (if (= shift *leaf-bits*)
  361. (visit-leaf node i)
  362. (visit-branch node (- shift *branch-bits*) i)))
  363. (define (next min shift root)
  364. (let ((i (if (and i (< min i))
  365. (- i min)
  366. 0)))
  367. (and root (< i (ash 1 shift))
  368. (let ((i (visit-node root shift i)))
  369. (and i (+ min i))))))
  370. (match bs
  371. (($ <intset> min shift root)
  372. (next min shift root))
  373. (($ <transient-intset> min shift root edit)
  374. (assert-readable! edit)
  375. (next min shift root))))
  376. (define* (intset-prev bs #:optional i)
  377. (define (visit-leaf node i)
  378. (let lp ((idx (logand i *leaf-mask*)))
  379. (if (logbit? idx node)
  380. (logior (logand i (lognot *leaf-mask*)) idx)
  381. (let ((idx (1- idx)))
  382. (and (<= 0 idx) (lp idx))))))
  383. (define (visit-branch node shift i)
  384. (let lp ((i i) (idx (logand (ash i (- shift)) *branch-mask*)))
  385. (and (<= 0 idx)
  386. (or (let ((node (vector-ref node idx)))
  387. (and node (visit-node node shift i)))
  388. (lp (1- (round-down i shift)) (1- idx))))))
  389. (define (visit-node node shift i)
  390. (if (= shift *leaf-bits*)
  391. (visit-leaf node i)
  392. (visit-branch node (- shift *branch-bits*) i)))
  393. (define (prev min shift root)
  394. (let ((i (if (and i (<= i (+ min (ash 1 shift))))
  395. (- i min)
  396. (1- (ash 1 shift)))))
  397. (and root (<= 0 i)
  398. (let ((i (visit-node root shift i)))
  399. (and i (+ min i))))))
  400. (match bs
  401. (($ <intset> min shift root)
  402. (prev min shift root))
  403. (($ <transient-intset> min shift root edit)
  404. (assert-readable! edit)
  405. (prev min shift root))))
  406. (define-syntax-rule (make-intset-folder forward? seed ...)
  407. (lambda (f set seed ...)
  408. (define (visit-branch node shift min seed ...)
  409. (cond
  410. ((= shift *leaf-bits*)
  411. (let lp ((i (if forward? 0 (1- *leaf-size*))) (seed seed) ...)
  412. (if (if forward? (< i *leaf-size*) (<= 0 i))
  413. (if (logbit? i node)
  414. (call-with-values (lambda () (f (+ i min) seed ...))
  415. (lambda (seed ...)
  416. (lp (if forward? (1+ i) (1- i)) seed ...)))
  417. (lp (if forward? (1+ i) (1- i)) seed ...))
  418. (values seed ...))))
  419. (else
  420. (let ((shift (- shift *branch-bits*)))
  421. (let lp ((i (if forward? 0 (1- *branch-size*))) (seed seed) ...)
  422. (if (if forward? (< i *branch-size*) (<= 0 i))
  423. (let ((elt (vector-ref node i)))
  424. (if elt
  425. (call-with-values
  426. (lambda ()
  427. (visit-branch elt shift (+ min (ash i shift)) seed ...))
  428. (lambda (seed ...)
  429. (lp (if forward? (1+ i) (1- i)) seed ...)))
  430. (lp (if forward? (1+ i) (1- i)) seed ...)))
  431. (values seed ...)))))))
  432. (match set
  433. (($ <intset> min shift root)
  434. (cond
  435. ((not root) (values seed ...))
  436. (else (visit-branch root shift min seed ...))))
  437. (($ <transient-intset>)
  438. (intset-fold f (persistent-intset set) seed ...)))))
  439. (define intset-fold
  440. (case-lambda
  441. ((f set)
  442. ((make-intset-folder #t) f set))
  443. ((f set seed)
  444. ((make-intset-folder #t seed) f set seed))
  445. ((f set s0 s1)
  446. ((make-intset-folder #t s0 s1) f set s0 s1))
  447. ((f set s0 s1 s2)
  448. ((make-intset-folder #t s0 s1 s2) f set s0 s1 s2))))
  449. (define intset-fold-right
  450. (case-lambda
  451. ((f set)
  452. ((make-intset-folder #f) f set))
  453. ((f set seed)
  454. ((make-intset-folder #f seed) f set seed))
  455. ((f set s0 s1)
  456. ((make-intset-folder #f s0 s1) f set s0 s1))
  457. ((f set s0 s1 s2)
  458. ((make-intset-folder #f s0 s1 s2) f set s0 s1 s2))))
  459. (define (intset-size shift root)
  460. (cond
  461. ((not root) 0)
  462. ((= *leaf-bits* shift) *leaf-size*)
  463. (else
  464. (let lp ((i (1- *branch-size*)))
  465. (let ((node (vector-ref root i)))
  466. (if node
  467. (let ((shift (- shift *branch-bits*)))
  468. (+ (intset-size shift node)
  469. (* i (ash 1 shift))))
  470. (lp (1- i))))))))
  471. (define (intset-union a b)
  472. ;; Union leaves.
  473. (define (union-leaves a b)
  474. (logior (or a 0) (or b 0)))
  475. ;; Union A and B from index I; the result will be fresh.
  476. (define (union-branches/fresh shift a b i fresh)
  477. (let lp ((i 0))
  478. (cond
  479. ((< i *branch-size*)
  480. (let* ((a-child (vector-ref a i))
  481. (b-child (vector-ref b i)))
  482. (vector-set! fresh i (union shift a-child b-child))
  483. (lp (1+ i))))
  484. (else fresh))))
  485. ;; Union A and B from index I; the result may be eq? to A.
  486. (define (union-branches/a shift a b i)
  487. (let lp ((i i))
  488. (cond
  489. ((< i *branch-size*)
  490. (let* ((a-child (vector-ref a i))
  491. (b-child (vector-ref b i)))
  492. (if (eq? a-child b-child)
  493. (lp (1+ i))
  494. (let ((child (union shift a-child b-child)))
  495. (cond
  496. ((eq? a-child child)
  497. (lp (1+ i)))
  498. (else
  499. (let ((result (clone-branch-and-set a i child)))
  500. (union-branches/fresh shift a b (1+ i) result))))))))
  501. (else a))))
  502. ;; Union A and B; the may could be eq? to either.
  503. (define (union-branches shift a b)
  504. (let lp ((i 0))
  505. (cond
  506. ((< i *branch-size*)
  507. (let* ((a-child (vector-ref a i))
  508. (b-child (vector-ref b i)))
  509. (if (eq? a-child b-child)
  510. (lp (1+ i))
  511. (let ((child (union shift a-child b-child)))
  512. (cond
  513. ((eq? a-child child)
  514. (union-branches/a shift a b (1+ i)))
  515. ((eq? b-child child)
  516. (union-branches/a shift b a (1+ i)))
  517. (else
  518. (let ((result (clone-branch-and-set a i child)))
  519. (union-branches/fresh shift a b (1+ i) result))))))))
  520. ;; Seems they are the same but not eq?. Odd.
  521. (else a))))
  522. (define (union shift a-node b-node)
  523. (cond
  524. ((not a-node) b-node)
  525. ((not b-node) a-node)
  526. ((eq? a-node b-node) a-node)
  527. ((= shift *leaf-bits*) (union-leaves a-node b-node))
  528. (else (union-branches (- shift *branch-bits*) a-node b-node))))
  529. (match (cons a b)
  530. ((($ <intset> a-min a-shift a-root) . ($ <intset> b-min b-shift b-root))
  531. (cond
  532. ((not b-root) a)
  533. ((not a-root) b)
  534. ((not (= b-shift a-shift))
  535. ;; Hoist the set with the lowest shift to meet the one with the
  536. ;; higher shift.
  537. (if (< b-shift a-shift)
  538. (intset-union a (add-level b-min b-shift b-root))
  539. (intset-union (add-level a-min a-shift a-root) b)))
  540. ((not (= b-min a-min))
  541. ;; Nodes at the same shift but different minimums will cover
  542. ;; disjoint ranges (due to the round-down call on min). Hoist
  543. ;; both until they cover the same range.
  544. (intset-union (add-level a-min a-shift a-root)
  545. (add-level b-min b-shift b-root)))
  546. (else
  547. ;; At this point, A and B cover the same range.
  548. (let ((root (union a-shift a-root b-root)))
  549. (cond
  550. ((eq? root a-root) a)
  551. ((eq? root b-root) b)
  552. (else (make-intset a-min a-shift root)))))))))
  553. (define (intset-intersect a b)
  554. ;; Intersect leaves.
  555. (define (intersect-leaves a b)
  556. (let ((leaf (logand a b)))
  557. (if (eqv? leaf 0) #f leaf)))
  558. ;; Intersect A and B from index I; the result will be fresh.
  559. (define (intersect-branches/fresh shift a b i fresh)
  560. (let lp ((i 0))
  561. (cond
  562. ((< i *branch-size*)
  563. (let* ((a-child (vector-ref a i))
  564. (b-child (vector-ref b i)))
  565. (vector-set! fresh i (intersect shift a-child b-child))
  566. (lp (1+ i))))
  567. ((branch-empty? fresh) #f)
  568. (else fresh))))
  569. ;; Intersect A and B from index I; the result may be eq? to A.
  570. (define (intersect-branches/a shift a b i)
  571. (let lp ((i i))
  572. (cond
  573. ((< i *branch-size*)
  574. (let* ((a-child (vector-ref a i))
  575. (b-child (vector-ref b i)))
  576. (if (eq? a-child b-child)
  577. (lp (1+ i))
  578. (let ((child (intersect shift a-child b-child)))
  579. (cond
  580. ((eq? a-child child)
  581. (lp (1+ i)))
  582. (else
  583. (let ((result (clone-branch-and-set a i child)))
  584. (intersect-branches/fresh shift a b (1+ i) result))))))))
  585. (else a))))
  586. ;; Intersect A and B; the may could be eq? to either.
  587. (define (intersect-branches shift a b)
  588. (let lp ((i 0))
  589. (cond
  590. ((< i *branch-size*)
  591. (let* ((a-child (vector-ref a i))
  592. (b-child (vector-ref b i)))
  593. (if (eq? a-child b-child)
  594. (lp (1+ i))
  595. (let ((child (intersect shift a-child b-child)))
  596. (cond
  597. ((eq? a-child child)
  598. (intersect-branches/a shift a b (1+ i)))
  599. ((eq? b-child child)
  600. (intersect-branches/a shift b a (1+ i)))
  601. (else
  602. (let ((result (clone-branch-and-set a i child)))
  603. (intersect-branches/fresh shift a b (1+ i) result))))))))
  604. ;; Seems they are the same but not eq?. Odd.
  605. (else a))))
  606. (define (intersect shift a-node b-node)
  607. (cond
  608. ((or (not a-node) (not b-node)) #f)
  609. ((eq? a-node b-node) a-node)
  610. ((= shift *leaf-bits*) (intersect-leaves a-node b-node))
  611. (else (intersect-branches (- shift *branch-bits*) a-node b-node))))
  612. (define (different-mins lo-min lo-shift lo-root hi-min hi-shift hi lo-is-a?)
  613. (cond
  614. ((<= lo-shift hi-shift)
  615. ;; If LO has a lower shift and a lower min, it is disjoint. If
  616. ;; it has the same shift and a different min, it is also
  617. ;; disjoint.
  618. empty-intset)
  619. (else
  620. (let* ((lo-shift (- lo-shift *branch-bits*))
  621. (lo-idx (ash (- hi-min lo-min) (- lo-shift))))
  622. (cond
  623. ((>= lo-idx *branch-size*)
  624. ;; HI has a lower shift, but it not within LO.
  625. empty-intset)
  626. ((vector-ref lo-root lo-idx)
  627. => (lambda (lo-root)
  628. (let ((lo (make-intset (+ lo-min (ash lo-idx lo-shift))
  629. lo-shift
  630. lo-root)))
  631. (if lo-is-a?
  632. (intset-intersect lo hi)
  633. (intset-intersect hi lo)))))
  634. (else empty-intset))))))
  635. (define (different-shifts-same-min min hi-shift hi-root lo lo-is-a?)
  636. (cond
  637. ((vector-ref hi-root 0)
  638. => (lambda (hi-root)
  639. (let ((hi (make-intset min
  640. (- hi-shift *branch-bits*)
  641. hi-root)))
  642. (if lo-is-a?
  643. (intset-intersect lo hi)
  644. (intset-intersect hi lo)))))
  645. (else empty-intset)))
  646. (match (cons a b)
  647. ((($ <intset> a-min a-shift a-root) . ($ <intset> b-min b-shift b-root))
  648. (cond
  649. ((< a-min b-min)
  650. (different-mins a-min a-shift a-root b-min b-shift b #t))
  651. ((< b-min a-min)
  652. (different-mins b-min b-shift b-root a-min a-shift a #f))
  653. ((< a-shift b-shift)
  654. (different-shifts-same-min b-min b-shift b-root a #t))
  655. ((< b-shift a-shift)
  656. (different-shifts-same-min a-min a-shift a-root b #f))
  657. (else
  658. ;; At this point, A and B cover the same range.
  659. (let ((root (intersect a-shift a-root b-root)))
  660. (cond
  661. ((eq? root a-root) a)
  662. ((eq? root b-root) b)
  663. (else (make-intset/prune a-min a-shift root)))))))))
  664. (define (intset-subtract a b)
  665. ;; Intersect leaves.
  666. (define (subtract-leaves a b)
  667. (let ((out (logand a (lognot b))))
  668. (if (zero? out) #f out)))
  669. ;; Subtract B from A starting at index I; the result will be fresh.
  670. (define (subtract-branches/fresh shift a b i fresh)
  671. (let lp ((i 0))
  672. (cond
  673. ((< i *branch-size*)
  674. (let* ((a-child (vector-ref a i))
  675. (b-child (vector-ref b i)))
  676. (vector-set! fresh i (subtract-nodes shift a-child b-child))
  677. (lp (1+ i))))
  678. ((branch-empty? fresh) #f)
  679. (else fresh))))
  680. ;; Subtract B from A. The result may be eq? to A.
  681. (define (subtract-branches shift a b)
  682. (let lp ((i 0))
  683. (cond
  684. ((< i *branch-size*)
  685. (let* ((a-child (vector-ref a i))
  686. (b-child (vector-ref b i)))
  687. (let ((child (subtract-nodes shift a-child b-child)))
  688. (cond
  689. ((eq? a-child child)
  690. (lp (1+ i)))
  691. (else
  692. (let ((result (clone-branch-and-set a i child)))
  693. (subtract-branches/fresh shift a b (1+ i) result)))))))
  694. (else a))))
  695. (define (subtract-nodes shift a-node b-node)
  696. (cond
  697. ((or (not a-node) (not b-node)) a-node)
  698. ((eq? a-node b-node) #f)
  699. ((= shift *leaf-bits*) (subtract-leaves a-node b-node))
  700. (else (subtract-branches (- shift *branch-bits*) a-node b-node))))
  701. (match (cons a b)
  702. ((($ <intset> a-min a-shift a-root) . ($ <intset> b-min b-shift b-root))
  703. (define (return root)
  704. (cond
  705. ((eq? root a-root) a)
  706. (else (make-intset/prune a-min a-shift root))))
  707. (cond
  708. ((<= a-shift b-shift)
  709. (let lp ((b-min b-min) (b-shift b-shift) (b-root b-root))
  710. (if (= a-shift b-shift)
  711. (if (= a-min b-min)
  712. (return (subtract-nodes a-shift a-root b-root))
  713. a)
  714. (let* ((b-shift (- b-shift *branch-bits*))
  715. (b-idx (ash (- a-min b-min) (- b-shift)))
  716. (b-min (+ b-min (ash b-idx b-shift)))
  717. (b-root (and b-root
  718. (<= 0 b-idx)
  719. (< b-idx *branch-size*)
  720. (vector-ref b-root b-idx))))
  721. (lp b-min b-shift b-root)))))
  722. (else
  723. (return
  724. (let lp ((a-min a-min) (a-shift a-shift) (a-root a-root))
  725. (if (= a-shift b-shift)
  726. (if (= a-min b-min)
  727. (subtract-nodes a-shift a-root b-root)
  728. a-root)
  729. (let* ((a-shift (- a-shift *branch-bits*))
  730. (a-idx (ash (- b-min a-min) (- a-shift)))
  731. (a-min (+ a-min (ash a-idx a-shift)))
  732. (old (and a-root
  733. (<= 0 a-idx)
  734. (< a-idx *branch-size*)
  735. (vector-ref a-root a-idx)))
  736. (new (lp a-min a-shift old)))
  737. (if (eq? old new)
  738. a-root
  739. (let ((root (clone-branch-and-set a-root a-idx new)))
  740. (and (or new (not (branch-empty? root)))
  741. root))))))))))))
  742. (define (bitvector->intset bv)
  743. (define (finish-tail out min tail)
  744. (if (zero? tail)
  745. out
  746. (intset-union out (make-intset min *leaf-bits* tail))))
  747. (let lp ((out empty-intset) (min 0) (pos 0) (tail 0))
  748. (let ((pos (bit-position #t bv pos)))
  749. (cond
  750. ((not pos)
  751. (finish-tail out min tail))
  752. ((< pos (+ min *leaf-size*))
  753. (lp out min (1+ pos) (logior tail (ash 1 (- pos min)))))
  754. (else
  755. (let ((min* (round-down pos *leaf-bits*)))
  756. (lp (finish-tail out min tail)
  757. min* pos (ash 1 (- pos min*)))))))))
  758. (define (intset-key-ranges intset)
  759. (call-with-values
  760. (lambda ()
  761. (intset-fold (lambda (k start end closed)
  762. (cond
  763. ((not start) (values k k closed))
  764. ((= k (1+ end)) (values start k closed))
  765. (else (values k k (acons start end closed)))))
  766. intset #f #f '()))
  767. (lambda (start end closed)
  768. (reverse (if start (acons start end closed) closed)))))
  769. (define (range-string ranges)
  770. (string-join (map (match-lambda
  771. ((start . start)
  772. (format #f "~a" start))
  773. ((start . end)
  774. (format #f "~a-~a" start end)))
  775. ranges)
  776. ","))
  777. (define (print-helper port tag intset)
  778. (let ((ranges (intset-key-ranges intset)))
  779. (match ranges
  780. (()
  781. (format port "#<~a>" tag))
  782. (_
  783. (format port "#<~a ~a>" tag (range-string ranges))))))
  784. (define (print-intset intset port)
  785. (print-helper port "intset" intset))
  786. (define (print-transient-intset intset port)
  787. (print-helper port "transient-intset" intset))
  788. (set-record-type-printer! <intset> print-intset)
  789. (set-record-type-printer! <transient-intset> print-transient-intset)