1 ! Copyright (C) 2008 Daniel Ehrenberg.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors arrays assocs binary-search grouping kernel
4 locals make math math.order sequences sequences.private sorting ;
7 ! Intervals are triples of { start end value }
8 TUPLE: interval-map { array array read-only } ;
12 : find-interval ( key interval-map -- interval-node )
13 array>> [ first-unsafe <=> ] with search nip ; inline
15 : interval-contains? ( key interval-node -- ? )
16 first2-unsafe between? ; inline
18 : all-intervals ( sequence -- intervals )
19 [ [ dup number? [ dup 2array ] when ] dip ] { } assoc-map-as ;
21 : disjoint? ( node1 node2 -- ? )
22 [ second-unsafe ] [ first-unsafe ] bi* < ;
24 : ensure-disjoint ( intervals -- intervals )
25 dup [ disjoint? ] monotonic?
26 [ "Intervals are not disjoint" throw ] unless ;
28 : >intervals ( specification -- intervals )
29 [ suffix ] { } assoc>map concat 3 group ;
31 ERROR: not-an-interval-map obj ;
33 : check-interval-map ( map -- map )
34 dup interval-map? [ not-an-interval-map ] unless ; inline
38 : interval-at* ( key map -- value ? )
40 [ drop ] [ find-interval ] 2bi
41 [ nip ] [ interval-contains? ] 2bi
42 [ third-unsafe t ] [ drop f f ] if ; inline
44 : interval-at ( key map -- value ) interval-at* drop ; inline
46 : interval-key? ( key map -- ? ) interval-at* nip ; inline
48 : interval-values ( map -- values )
49 check-interval-map array>> [ third-unsafe ] map ;
51 : <interval-map> ( specification -- map )
52 all-intervals [ first-unsafe second-unsafe ] sort-with
53 >intervals ensure-disjoint interval-map boa ;
55 : <interval-set> ( specification -- map )
56 dup zip <interval-map> ;
58 :: coalesce ( alist -- specification )
59 ! Only works with integer keys, because they're discrete
62 alist sort-keys unclip swap [ first2 dupd ] dip
63 [| oldkey oldval key val | ! Underneath is start
66 [ oldkey 2array oldval 2array , key ] unless
68 ] assoc-each [ 2array ] bi@ ,