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
41 (define-syntax-rule (define-inline name val)
42 (define-syntax name (identifier-syntax val)))
45 (use-modules (system base target))
46 (define-syntax compile-time-cond
49 ((_ (test body ...) rest ...)
50 (if (primitive-eval (syntax->datum #'test))
52 #'(begin (compile-time-cond rest ...))))
56 (error "no compile-time-cond expression matched"))))))
59 ((eqv? (target-word-size) 4)
60 (define-inline *leaf-bits* 4))
61 ((eqv? (target-word-size) 8)
62 (define-inline *leaf-bits* 5)))
64 (define-inline *leaf-size* (ash 1 *leaf-bits*))
65 (define-inline *leaf-mask* (1- *leaf-size*))
66 (define-inline *branch-bits* 3)
67 (define-inline *branch-size* (ash 1 *branch-bits*))
68 (define-inline *branch-mask* (1- *branch-size*))
70 (define-record-type <intset>
71 (make-intset min shift root)
78 (define-inlinable (clone-leaf-and-set leaf i val)
81 (logior leaf (ash 1 i))
84 (logand leaf (lognot (ash 1 i)))
86 (define (leaf-empty? leaf)
90 (make-vector *branch-size* #f))
91 (define (clone-branch-and-set branch i elt)
92 (let ((new (new-branch)))
93 (when branch (vector-move-left! branch 0 *branch-size* new 0))
94 (vector-set! new i elt)
96 (define (branch-empty? branch)
98 (or (= i *branch-size*)
99 (and (not (vector-ref branch i))
102 (define (round-down min shift)
103 (logand min (lognot (1- (ash 1 shift)))))
105 (define empty-intset (make-intset 0 *leaf-bits* #f))
107 (define (add-level min shift root)
108 (let* ((shift* (+ shift *branch-bits*))
109 (min* (round-down min shift*))
110 (idx (logand (ash (- min min*) (- shift)) *branch-mask*)))
111 (make-intset min* shift* (clone-branch-and-set #f idx root))))
113 (define (make-intset/prune min shift root)
117 ((= shift *leaf-bits*)
118 (make-intset min shift root))
120 (let lp ((i 0) (elt #f))
123 (if (vector-ref root i)
125 (make-intset min shift root)
129 (let ((shift (- shift *branch-bits*)))
130 (make-intset/prune (+ min (ash elt shift))
132 (vector-ref root elt))))
133 ;; Shouldn't be reached...
134 (else empty-intset))))))
136 (define (intset-add bs i)
137 (define (adjoin i shift root)
139 ((= shift *leaf-bits*)
140 (let ((idx (logand i *leaf-mask*)))
141 (if (and root (logbit? idx root))
143 (clone-leaf-and-set root idx #t))))
145 (let* ((shift (- shift *branch-bits*))
146 (idx (logand (ash i (- shift)) *branch-mask*))
147 (node (and root (vector-ref root idx)))
148 (new-node (adjoin i shift node)))
149 (if (eq? node new-node)
151 (clone-branch-and-set root idx new-node))))))
153 (($ <intset> min shift root)
156 ;; The power-of-two spanning trick doesn't work across 0.
157 (error "Intsets can only hold non-negative integers." i))
159 ;; Add first element.
160 (let ((min (round-down i shift)))
161 (make-intset min *leaf-bits*
162 (adjoin (- i min) *leaf-bits* root))))
163 ((and (<= min i) (< i (+ min (ash 1 shift))))
164 ;; Add element to set; level will not change.
165 (let ((old-root root)
166 (root (adjoin (- i min) shift root)))
167 (if (eq? root old-root)
169 (make-intset min shift root))))
171 ;; Rebuild the tree by unioning two intsets.
172 (intset-union (intset-add empty-intset i) bs))
174 ;; Add a new level and try again.
175 (intset-add (add-level min shift root) i))))))
177 (define (intset-remove bs i)
178 (define (remove i shift root)
180 ((= shift *leaf-bits*)
181 (let ((idx (logand i *leaf-mask*)))
182 (if (logbit? idx root)
183 (let ((root (clone-leaf-and-set root idx #f)))
184 (and (not (leaf-empty? root)) root))
187 (let* ((shift (- shift *branch-bits*))
188 (idx (logand (ash i (- shift)) *branch-mask*)))
190 ((vector-ref root idx)
192 (let ((new-node (remove i shift node)))
193 (if (eq? node new-node)
195 (let ((root (clone-branch-and-set root idx new-node)))
196 (and (or new-node (not (branch-empty? root)))
200 (($ <intset> min shift root)
203 ((and (<= min i) (< i (+ min (ash 1 shift))))
204 ;; Add element to set; level will not change.
205 (let ((old-root root)
206 (root (remove (- i min) shift root)))
207 (if (eq? root old-root)
209 (make-intset/prune min shift root))))
212 (define (intset-ref bs i)
214 (($ <intset> min shift root)
215 (and (<= min i) (< i (+ min (ash 1 shift)))
217 (let lp ((node root) (shift shift))
219 (if (= shift *leaf-bits*)
220 (logbit? (logand i *leaf-mask*) node)
221 (let* ((shift (- shift *branch-bits*))
222 (idx (logand (ash i (- shift)) *branch-mask*)))
223 (lp (vector-ref node idx) shift))))))))))
225 (define (intset-next bs i)
226 (define (visit-leaf node i)
227 (let lp ((idx (logand i *leaf-mask*)))
228 (if (logbit? idx node)
229 (logior (logand i (lognot *leaf-mask*)) idx)
230 (let ((idx (1+ idx)))
231 (and (< idx *leaf-size*)
233 (define (visit-branch node shift i)
234 (let lp ((i i) (idx (logand (ash i (- shift)) *branch-mask*)))
235 (and (< idx *branch-size*)
236 (or (visit-node (vector-ref node idx) shift i)
237 (let ((inc (ash 1 shift)))
238 (lp (+ (round-down i shift) inc) (1+ idx)))))))
239 (define (visit-node node shift i)
241 (if (= shift *leaf-bits*)
243 (visit-branch node (- shift *branch-bits*) i))))
245 (($ <intset> min shift root)
246 (let ((i (if (and i (< min i))
249 (and (< i (ash 1 shift))
250 (let ((i (visit-node root shift i)))
251 (and i (+ min i))))))))
253 (define (intset-size shift root)
256 ((= *leaf-bits* shift) *leaf-size*)
258 (let lp ((i (1- *branch-size*)))
259 (let ((node (vector-ref root i)))
261 (let ((shift (- shift *branch-bits*)))
262 (+ (intset-size shift node)
263 (* i (ash 1 shift))))
266 (define (intset-union a b)
268 (define (union-leaves a b)
269 (logior (or a 0) (or b 0)))
270 ;; Union A and B from index I; the result will be fresh.
271 (define (union-branches/fresh shift a b i fresh)
275 (let* ((a-child (vector-ref a i))
276 (b-child (vector-ref b i)))
277 (vector-set! fresh i (union shift a-child b-child))
280 ;; Union A and B from index I; the result may be eq? to A.
281 (define (union-branches/a shift a b i)
285 (let* ((a-child (vector-ref a i))
286 (b-child (vector-ref b i)))
287 (if (eq? a-child b-child)
289 (let ((child (union shift a-child b-child)))
294 (let ((result (clone-branch-and-set a i child)))
295 (union-branches/fresh shift a b (1+ i) result))))))))
297 ;; Union A and B; the may could be eq? to either.
298 (define (union-branches shift a b)
302 (let* ((a-child (vector-ref a i))
303 (b-child (vector-ref b i)))
304 (if (eq? a-child b-child)
306 (let ((child (union shift a-child b-child)))
309 (union-branches/a shift a b (1+ i)))
311 (union-branches/a shift b a (1+ i)))
313 (let ((result (clone-branch-and-set a i child)))
314 (union-branches/fresh shift a b (1+ i) result))))))))
315 ;; Seems they are the same but not eq?. Odd.
317 (define (union shift a-node b-node)
319 ((not a-node) b-node)
320 ((not b-node) a-node)
321 ((eq? a-node b-node) a-node)
322 ((= shift *leaf-bits*) (union-leaves a-node b-node))
323 (else (union-branches (- shift *branch-bits*) a-node b-node))))
325 ((($ <intset> a-min a-shift a-root) . ($ <intset> b-min b-shift b-root))
327 ((not (= b-shift a-shift))
328 ;; Hoist the set with the lowest shift to meet the one with the
330 (if (< b-shift a-shift)
331 (intset-union a (add-level b-min b-shift b-root))
332 (intset-union (add-level a-min a-shift a-root) b)))
333 ((not (= b-min a-min))
334 ;; Nodes at the same shift but different minimums will cover
335 ;; disjoint ranges (due to the round-down call on min). Hoist
336 ;; both until they cover the same range.
337 (intset-union (add-level a-min a-shift a-root)
338 (add-level b-min b-shift b-root)))
340 ;; At this point, A and B cover the same range.
341 (let ((root (union a-shift a-root b-root)))
343 ((eq? root a-root) a)
344 ((eq? root b-root) b)
345 (else (make-intset a-min a-shift root)))))))))
347 (define (intset-intersect a b)
348 (define tmp (new-leaf))
350 (define (intersect-leaves a b)
352 ;; Intersect A and B from index I; the result will be fresh.
353 (define (intersect-branches/fresh shift a b i fresh)
357 (let* ((a-child (vector-ref a i))
358 (b-child (vector-ref b i)))
359 (vector-set! fresh i (intersect shift a-child b-child))
361 ((branch-empty? fresh) #f)
363 ;; Intersect A and B from index I; the result may be eq? to A.
364 (define (intersect-branches/a shift a b i)
368 (let* ((a-child (vector-ref a i))
369 (b-child (vector-ref b i)))
370 (if (eq? a-child b-child)
372 (let ((child (intersect shift a-child b-child)))
377 (let ((result (clone-branch-and-set a i child)))
378 (intersect-branches/fresh shift a b (1+ i) result))))))))
380 ;; Intersect A and B; the may could be eq? to either.
381 (define (intersect-branches shift a b)
385 (let* ((a-child (vector-ref a i))
386 (b-child (vector-ref b i)))
387 (if (eq? a-child b-child)
389 (let ((child (intersect shift a-child b-child)))
392 (intersect-branches/a shift a b (1+ i)))
394 (intersect-branches/a shift b a (1+ i)))
396 (let ((result (clone-branch-and-set a i child)))
397 (intersect-branches/fresh shift a b (1+ i) result))))))))
398 ;; Seems they are the same but not eq?. Odd.
400 (define (intersect shift a-node b-node)
402 ((or (not a-node) (not b-node)) #f)
403 ((eq? a-node b-node) a-node)
404 ((= shift *leaf-bits*) (intersect-leaves a-node b-node))
405 (else (intersect-branches (- shift *branch-bits*) a-node b-node))))
407 (define (different-mins lo-min lo-shift lo-root hi-min hi-shift hi lo-is-a?)
409 ((<= lo-shift hi-shift)
410 ;; If LO has a lower shift and a lower min, it is disjoint. If
411 ;; it has the same shift and a different min, it is also
415 (let* ((lo-shift (- lo-shift *branch-bits*))
416 (lo-idx (ash (- hi-min lo-min) (- lo-shift))))
418 ((>= lo-idx *branch-size*)
419 ;; HI has a lower shift, but it not within LO.
421 ((vector-ref lo-root lo-idx)
423 (let ((lo (make-intset (+ lo-min (ash lo-idx lo-shift))
427 (intset-intersect lo hi)
428 (intset-intersect hi lo)))))
429 (else empty-intset))))))
431 (define (different-shifts-same-min min hi-shift hi-root lo lo-is-a?)
433 ((vector-ref hi-root 0)
435 (let ((hi (make-intset min
436 (- hi-shift *branch-bits*)
439 (intset-intersect lo hi)
440 (intset-intersect hi lo)))))
441 (else empty-intset)))
444 ((($ <intset> a-min a-shift a-root) . ($ <intset> b-min b-shift b-root))
447 (different-mins a-min a-shift a-root b-min b-shift b #t))
449 (different-mins b-min b-shift b-root a-min a-shift a #f))
451 (different-shifts-same-min b-min b-shift b-root a #t))
453 (different-shifts-same-min a-min a-shift a-root b #f))
455 ;; At this point, A and B cover the same range.
456 (let ((root (intersect a-shift a-root b-root)))
458 ((eq? root a-root) a)
459 ((eq? root b-root) b)
460 (else (make-intset/prune a-min a-shift root)))))))))
462 (define (intset-subtract a b)
463 (define tmp (new-leaf))
465 (define (subtract-leaves a b)
466 (logand a (lognot b)))
467 ;; Subtract B from A starting at index I; the result will be fresh.
468 (define (subtract-branches/fresh shift a b i fresh)
472 (let* ((a-child (vector-ref a i))
473 (b-child (vector-ref b i)))
474 (vector-set! fresh i (subtract-nodes shift a-child b-child))
476 ((branch-empty? fresh) #f)
478 ;; Subtract B from A. The result may be eq? to A.
479 (define (subtract-branches shift a b)
483 (let* ((a-child (vector-ref a i))
484 (b-child (vector-ref b i)))
485 (let ((child (subtract-nodes shift a-child b-child)))
490 (let ((result (clone-branch-and-set a i child)))
491 (subtract-branches/fresh shift a b (1+ i) result)))))))
493 (define (subtract-nodes shift a-node b-node)
495 ((or (not a-node) (not b-node)) a-node)
496 ((eq? a-node b-node) #f)
497 ((= shift *leaf-bits*) (subtract-leaves a-node b-node))
498 (else (subtract-branches (- shift *branch-bits*) a-node b-node))))
501 ((($ <intset> a-min a-shift a-root) . ($ <intset> b-min b-shift b-root))
502 (define (return root)
504 ((eq? root a-root) a)
505 (else (make-intset/prune a-min a-shift root))))
507 ((<= a-shift b-shift)
508 (let lp ((b-min b-min) (b-shift b-shift) (b-root b-root))
509 (if (= a-shift b-shift)
511 (return (subtract-nodes a-shift a-root b-root))
513 (let* ((b-shift (- b-shift *branch-bits*))
514 (b-idx (ash (- a-min b-min) (- b-shift)))
515 (b-min (+ b-min (ash b-idx b-shift)))
518 (< b-idx *branch-size*)
519 (vector-ref b-root b-idx))))
520 (lp b-min b-shift b-root)))))
523 (let lp ((a-min a-min) (a-shift a-shift) (a-root a-root))
524 (if (= a-shift b-shift)
526 (subtract-nodes a-shift a-root b-root)
528 (let* ((a-shift (- a-shift *branch-bits*))
529 (a-idx (ash (- b-min a-min) (- a-shift)))
530 (a-min (+ a-min (ash a-idx a-shift)))
533 (< a-idx *branch-size*)
534 (vector-ref a-root a-idx)))
535 (new (lp a-min a-shift old)))
538 (clone-branch-and-set a-root a-idx new)))))))))))