]> gitweb.factorcode.org Git - factor.git/blob - basis/interval-maps/interval-maps.factor
factor: Rename start -> subseq-start, start* -> subseq-start-from.
[factor.git] / basis / interval-maps / interval-maps.factor
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 ;
5 IN: interval-maps
6
7 ! Intervals are triples of { start end value }
8 TUPLE: interval-map { array array read-only } ;
9
10 <PRIVATE
11
12 : find-interval ( key interval-map -- interval-node )
13     array>> [ first-unsafe <=> ] with search nip ; inline
14
15 : interval-contains? ( key interval-node -- ? )
16     first2-unsafe between? ; inline
17
18 : all-intervals ( sequence -- intervals )
19     [ [ dup number? [ dup 2array ] when ] dip ] { } assoc-map-as ;
20
21 : disjoint? ( node1 node2 -- ? )
22     [ second-unsafe ] [ first-unsafe ] bi* < ;
23
24 : ensure-disjoint ( intervals -- intervals )
25     dup [ disjoint? ] monotonic?
26     [ "Intervals are not disjoint" throw ] unless ;
27
28 : >intervals ( specification -- intervals )
29     [ suffix ] { } assoc>map concat 3 group ;
30
31 ERROR: not-an-interval-map obj ;
32
33 : check-interval-map ( map -- map )
34     dup interval-map? [ not-an-interval-map ] unless ; inline
35
36 PRIVATE>
37
38 : interval-at* ( key map -- value ? )
39     check-interval-map
40     [ drop ] [ find-interval ] 2bi
41     [ nip ] [ interval-contains? ] 2bi
42     [ third-unsafe t ] [ drop f f ] if ; inline
43
44 : interval-at ( key map -- value ) interval-at* drop ; inline
45
46 : interval-key? ( key map -- ? ) interval-at* nip ; inline
47
48 : interval-values ( map -- values )
49     check-interval-map array>> [ third-unsafe ] map ;
50
51 : <interval-map> ( specification -- map )
52     all-intervals [ first-unsafe second-unsafe ] sort-with
53     >intervals ensure-disjoint interval-map boa ;
54
55 : <interval-set> ( specification -- map )
56     dup zip <interval-map> ;
57
58 :: coalesce ( alist -- specification )
59     ! Only works with integer keys, because they're discrete
60     ! Makes 2array keys
61     [
62         alist sort-keys unclip swap [ first2 dupd ] dip
63         [| oldkey oldval key val | ! Underneath is start
64             oldkey 1 + key =
65             oldval val = and
66             [ oldkey 2array oldval 2array , key ] unless
67             key val
68         ] assoc-each [ 2array ] bi@ ,
69     ] { } make ;