1 ;;; Functional name maps
2 ;;; Copyright (C) 2014 Free Software Foundation, Inc.
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.
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.
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/>.
20 ;;; A persistent, functional data structure representing a set of
21 ;;; integers as a tree whose branches are vectors and whose leaves are
22 ;;; fixnums. Intsets are careful to preserve sub-structure, in the
23 ;;; sense of eq?, whereever possible.
27 (define-module (language cps intset)
28 #:use-module (rnrs bytevectors)
29 #:use-module (srfi srfi-9)
30 #:use-module (ice-9 match)
31 #:export (empty-intset
42 (define-syntax-rule (define-inline name val)
43 (define-syntax name (identifier-syntax val)))
46 (use-modules (system base target))
47 (define-syntax compile-time-cond
50 ((_ (test body ...) rest ...)
51 (if (primitive-eval (syntax->datum #'test))
53 #'(begin (compile-time-cond rest ...))))
57 (error "no compile-time-cond expression matched"))))))
60 ((eqv? (target-word-size) 4)
61 (define-inline *leaf-bits* 4))
62 ((eqv? (target-word-size) 8)
63 (define-inline *leaf-bits* 5)))
65 (define-inline *leaf-size* (ash 1 *leaf-bits*))
66 (define-inline *leaf-mask* (1- *leaf-size*))
67 (define-inline *branch-bits* 3)
68 (define-inline *branch-size* (ash 1 *branch-bits*))
69 (define-inline *branch-mask* (1- *branch-size*))
71 (define-record-type <intset>
72 (make-intset min shift root)
79 (define-inlinable (clone-leaf-and-set leaf i val)
82 (logior leaf (ash 1 i))
85 (logand leaf (lognot (ash 1 i)))
87 (define (leaf-empty? leaf)
91 (make-vector *branch-size* #f))
92 (define (clone-branch-and-set branch i elt)
93 (let ((new (new-branch)))
94 (when branch (vector-move-left! branch 0 *branch-size* new 0))
95 (vector-set! new i elt)
97 (define (branch-empty? branch)
99 (or (= i *branch-size*)
100 (and (not (vector-ref branch i))
103 (define (round-down min shift)
104 (logand min (lognot (1- (ash 1 shift)))))
106 (define empty-intset (make-intset 0 *leaf-bits* #f))
108 (define (add-level min shift root)
109 (let* ((shift* (+ shift *branch-bits*))
110 (min* (round-down min shift*))
111 (idx (logand (ash (- min min*) (- shift)) *branch-mask*)))
112 (make-intset min* shift* (clone-branch-and-set #f idx root))))
114 (define (make-intset/prune min shift root)
118 ((= shift *leaf-bits*)
119 (make-intset min shift root))
121 (let lp ((i 0) (elt #f))
124 (if (vector-ref root i)
126 (make-intset min shift root)
130 (let ((shift (- shift *branch-bits*)))
131 (make-intset/prune (+ min (ash elt shift))
133 (vector-ref root elt))))
134 ;; Shouldn't be reached...
135 (else empty-intset))))))
137 (define (intset-add bs i)
138 (define (adjoin i shift root)
140 ((= shift *leaf-bits*)
141 (let ((idx (logand i *leaf-mask*)))
142 (if (and root (logbit? idx root))
144 (clone-leaf-and-set root idx #t))))
146 (let* ((shift (- shift *branch-bits*))
147 (idx (logand (ash i (- shift)) *branch-mask*))
148 (node (and root (vector-ref root idx)))
149 (new-node (adjoin i shift node)))
150 (if (eq? node new-node)
152 (clone-branch-and-set root idx new-node))))))
154 (($ <intset> min shift root)
157 ;; The power-of-two spanning trick doesn't work across 0.
158 (error "Intsets can only hold non-negative integers." i))
160 ;; Add first element.
161 (let ((min (round-down i shift)))
162 (make-intset min *leaf-bits*
163 (adjoin (- i min) *leaf-bits* root))))
164 ((and (<= min i) (< i (+ min (ash 1 shift))))
165 ;; Add element to set; level will not change.
166 (let ((old-root root)
167 (root (adjoin (- i min) shift root)))
168 (if (eq? root old-root)
170 (make-intset min shift root))))
172 ;; Rebuild the tree by unioning two intsets.
173 (intset-union (intset-add empty-intset i) bs))
175 ;; Add a new level and try again.
176 (intset-add (add-level min shift root) i))))))
178 (define (intset-remove bs i)
179 (define (remove i shift root)
181 ((= shift *leaf-bits*)
182 (let ((idx (logand i *leaf-mask*)))
183 (if (logbit? idx root)
184 (let ((root (clone-leaf-and-set root idx #f)))
185 (and (not (leaf-empty? root)) root))
188 (let* ((shift (- shift *branch-bits*))
189 (idx (logand (ash i (- shift)) *branch-mask*)))
191 ((vector-ref root idx)
193 (let ((new-node (remove i shift node)))
194 (if (eq? node new-node)
196 (let ((root (clone-branch-and-set root idx new-node)))
197 (and (or new-node (not (branch-empty? root)))
201 (($ <intset> min shift root)
204 ((and (<= min i) (< i (+ min (ash 1 shift))))
205 ;; Add element to set; level will not change.
206 (let ((old-root root)
207 (root (remove (- i min) shift root)))
208 (if (eq? root old-root)
210 (make-intset/prune min shift root))))
213 (define (intset-ref bs i)
215 (($ <intset> min shift root)
216 (and (<= min i) (< i (+ min (ash 1 shift)))
218 (let lp ((node root) (shift shift))
220 (if (= shift *leaf-bits*)
221 (logbit? (logand i *leaf-mask*) node)
222 (let* ((shift (- shift *branch-bits*))
223 (idx (logand (ash i (- shift)) *branch-mask*)))
224 (lp (vector-ref node idx) shift))))))))))
226 (define (intset-next bs i)
227 (define (visit-leaf node i)
228 (let lp ((idx (logand i *leaf-mask*)))
229 (if (logbit? idx node)
230 (logior (logand i (lognot *leaf-mask*)) idx)
231 (let ((idx (1+ idx)))
232 (and (< idx *leaf-size*)
234 (define (visit-branch node shift i)
235 (let lp ((i i) (idx (logand (ash i (- shift)) *branch-mask*)))
236 (and (< idx *branch-size*)
237 (or (visit-node (vector-ref node idx) shift i)
238 (let ((inc (ash 1 shift)))
239 (lp (+ (round-down i shift) inc) (1+ idx)))))))
240 (define (visit-node node shift i)
242 (if (= shift *leaf-bits*)
244 (visit-branch node (- shift *branch-bits*) i))))
246 (($ <intset> min shift root)
247 (let ((i (if (and i (< min i))
250 (and (< i (ash 1 shift))
251 (let ((i (visit-node root shift i)))
252 (and i (+ min i))))))))
254 (define (intset-size shift root)
257 ((= *leaf-bits* shift) *leaf-size*)
259 (let lp ((i (1- *branch-size*)))
260 (let ((node (vector-ref root i)))
262 (let ((shift (- shift *branch-bits*)))
263 (+ (intset-size shift node)
264 (* i (ash 1 shift))))
267 (define (intset-union a b)
269 (define (union-leaves a b)
270 (logior (or a 0) (or b 0)))
271 ;; Union A and B from index I; the result will be fresh.
272 (define (union-branches/fresh shift a b i fresh)
276 (let* ((a-child (vector-ref a i))
277 (b-child (vector-ref b i)))
278 (vector-set! fresh i (union shift a-child b-child))
281 ;; Union A and B from index I; the result may be eq? to A.
282 (define (union-branches/a shift a b i)
286 (let* ((a-child (vector-ref a i))
287 (b-child (vector-ref b i)))
288 (if (eq? a-child b-child)
290 (let ((child (union shift a-child b-child)))
295 (let ((result (clone-branch-and-set a i child)))
296 (union-branches/fresh shift a b (1+ i) result))))))))
298 ;; Union A and B; the may could be eq? to either.
299 (define (union-branches shift a b)
303 (let* ((a-child (vector-ref a i))
304 (b-child (vector-ref b i)))
305 (if (eq? a-child b-child)
307 (let ((child (union shift a-child b-child)))
310 (union-branches/a shift a b (1+ i)))
312 (union-branches/a shift b a (1+ i)))
314 (let ((result (clone-branch-and-set a i child)))
315 (union-branches/fresh shift a b (1+ i) result))))))))
316 ;; Seems they are the same but not eq?. Odd.
318 (define (union shift a-node b-node)
320 ((not a-node) b-node)
321 ((not b-node) a-node)
322 ((eq? a-node b-node) a-node)
323 ((= shift *leaf-bits*) (union-leaves a-node b-node))
324 (else (union-branches (- shift *branch-bits*) a-node b-node))))
326 ((($ <intset> a-min a-shift a-root) . ($ <intset> b-min b-shift b-root))
328 ((not (= b-shift a-shift))
329 ;; Hoist the set with the lowest shift to meet the one with the
331 (if (< b-shift a-shift)
332 (intset-union a (add-level b-min b-shift b-root))
333 (intset-union (add-level a-min a-shift a-root) b)))
334 ((not (= b-min a-min))
335 ;; Nodes at the same shift but different minimums will cover
336 ;; disjoint ranges (due to the round-down call on min). Hoist
337 ;; both until they cover the same range.
338 (intset-union (add-level a-min a-shift a-root)
339 (add-level b-min b-shift b-root)))
341 ;; At this point, A and B cover the same range.
342 (let ((root (union a-shift a-root b-root)))
344 ((eq? root a-root) a)
345 ((eq? root b-root) b)
346 (else (make-intset a-min a-shift root)))))))))
348 (define (intset-intersect a b)
349 (define tmp (new-leaf))
351 (define (intersect-leaves a b)
353 ;; Intersect A and B from index I; the result will be fresh.
354 (define (intersect-branches/fresh shift a b i fresh)
358 (let* ((a-child (vector-ref a i))
359 (b-child (vector-ref b i)))
360 (vector-set! fresh i (intersect shift a-child b-child))
362 ((branch-empty? fresh) #f)
364 ;; Intersect A and B from index I; the result may be eq? to A.
365 (define (intersect-branches/a shift a b i)
369 (let* ((a-child (vector-ref a i))
370 (b-child (vector-ref b i)))
371 (if (eq? a-child b-child)
373 (let ((child (intersect shift a-child b-child)))
378 (let ((result (clone-branch-and-set a i child)))
379 (intersect-branches/fresh shift a b (1+ i) result))))))))
381 ;; Intersect A and B; the may could be eq? to either.
382 (define (intersect-branches shift a b)
386 (let* ((a-child (vector-ref a i))
387 (b-child (vector-ref b i)))
388 (if (eq? a-child b-child)
390 (let ((child (intersect shift a-child b-child)))
393 (intersect-branches/a shift a b (1+ i)))
395 (intersect-branches/a shift b a (1+ i)))
397 (let ((result (clone-branch-and-set a i child)))
398 (intersect-branches/fresh shift a b (1+ i) result))))))))
399 ;; Seems they are the same but not eq?. Odd.
401 (define (intersect shift a-node b-node)
403 ((or (not a-node) (not b-node)) #f)
404 ((eq? a-node b-node) a-node)
405 ((= shift *leaf-bits*) (intersect-leaves a-node b-node))
406 (else (intersect-branches (- shift *branch-bits*) a-node b-node))))
408 (define (different-mins lo-min lo-shift lo-root hi-min hi-shift hi lo-is-a?)
410 ((<= lo-shift hi-shift)
411 ;; If LO has a lower shift and a lower min, it is disjoint. If
412 ;; it has the same shift and a different min, it is also
416 (let* ((lo-shift (- lo-shift *branch-bits*))
417 (lo-idx (ash (- hi-min lo-min) (- lo-shift))))
419 ((>= lo-idx *branch-size*)
420 ;; HI has a lower shift, but it not within LO.
422 ((vector-ref lo-root lo-idx)
424 (let ((lo (make-intset (+ lo-min (ash lo-idx lo-shift))
428 (intset-intersect lo hi)
429 (intset-intersect hi lo)))))
430 (else empty-intset))))))
432 (define (different-shifts-same-min min hi-shift hi-root lo lo-is-a?)
434 ((vector-ref hi-root 0)
436 (let ((hi (make-intset min
437 (- hi-shift *branch-bits*)
440 (intset-intersect lo hi)
441 (intset-intersect hi lo)))))
442 (else empty-intset)))
445 ((($ <intset> a-min a-shift a-root) . ($ <intset> b-min b-shift b-root))
448 (different-mins a-min a-shift a-root b-min b-shift b #t))
450 (different-mins b-min b-shift b-root a-min a-shift a #f))
452 (different-shifts-same-min b-min b-shift b-root a #t))
454 (different-shifts-same-min a-min a-shift a-root b #f))
456 ;; At this point, A and B cover the same range.
457 (let ((root (intersect a-shift a-root b-root)))
459 ((eq? root a-root) a)
460 ((eq? root b-root) b)
461 (else (make-intset/prune a-min a-shift root)))))))))
463 (define (intset-subtract a b)
464 (define tmp (new-leaf))
466 (define (subtract-leaves a b)
467 (logand a (lognot b)))
468 ;; Subtract B from A starting at index I; the result will be fresh.
469 (define (subtract-branches/fresh shift a b i fresh)
473 (let* ((a-child (vector-ref a i))
474 (b-child (vector-ref b i)))
475 (vector-set! fresh i (subtract-nodes shift a-child b-child))
477 ((branch-empty? fresh) #f)
479 ;; Subtract B from A. The result may be eq? to A.
480 (define (subtract-branches shift a b)
484 (let* ((a-child (vector-ref a i))
485 (b-child (vector-ref b i)))
486 (let ((child (subtract-nodes shift a-child b-child)))
491 (let ((result (clone-branch-and-set a i child)))
492 (subtract-branches/fresh shift a b (1+ i) result)))))))
494 (define (subtract-nodes shift a-node b-node)
496 ((or (not a-node) (not b-node)) a-node)
497 ((eq? a-node b-node) #f)
498 ((= shift *leaf-bits*) (subtract-leaves a-node b-node))
499 (else (subtract-branches (- shift *branch-bits*) a-node b-node))))
502 ((($ <intset> a-min a-shift a-root) . ($ <intset> b-min b-shift b-root))
503 (define (return root)
505 ((eq? root a-root) a)
506 (else (make-intset/prune a-min a-shift root))))
508 ((<= a-shift b-shift)
509 (let lp ((b-min b-min) (b-shift b-shift) (b-root b-root))
510 (if (= a-shift b-shift)
512 (return (subtract-nodes a-shift a-root b-root))
514 (let* ((b-shift (- b-shift *branch-bits*))
515 (b-idx (ash (- a-min b-min) (- b-shift)))
516 (b-min (+ b-min (ash b-idx b-shift)))
519 (< b-idx *branch-size*)
520 (vector-ref b-root b-idx))))
521 (lp b-min b-shift b-root)))))
524 (let lp ((a-min a-min) (a-shift a-shift) (a-root a-root))
525 (if (= a-shift b-shift)
527 (subtract-nodes a-shift a-root b-root)
529 (let* ((a-shift (- a-shift *branch-bits*))
530 (a-idx (ash (- b-min a-min) (- a-shift)))
531 (a-min (+ a-min (ash a-idx a-shift)))
534 (< a-idx *branch-size*)
535 (vector-ref a-root a-idx)))
536 (new (lp a-min a-shift old)))
539 (clone-branch-and-set a-root a-idx new)))))))))))
541 (define (bitvector->intset bv)
542 (define (finish-tail out min tail)
545 (intset-union out (make-intset min *leaf-bits* tail))))
546 (let lp ((out empty-intset) (min 0) (pos 0) (tail 0))
547 (let ((pos (bit-position #t bv pos)))
550 (finish-tail out min tail))
551 ((< pos (+ min *leaf-size*))
552 (lp out min (1+ pos) (logior tail (ash 1 (- pos min)))))
554 (let ((min* (round-down pos *leaf-bits*)))
555 (lp (finish-tail out min tail)
556 min* pos (ash 1 (- pos min*)))))))))