]> gitweb.factorcode.org Git - factor.git/blob - basis/interval-sets/interval-sets.factor
interval-maps: bit more speed using unsafe words.
[factor.git] / basis / interval-sets / interval-sets.factor
1 ! Copyright (C) 2009 Daniel Ehrenberg.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors alien.c-types arrays assocs binary-search
4 combinators fry grouping kernel locals make math math.order
5 sequences sequences.private sorting specialized-arrays ;
6 SPECIALIZED-ARRAY: uint
7 IN: interval-sets
8 ! Sets of positive integers
9
10 TUPLE: interval-set { array uint-array read-only } ;
11
12 <PRIVATE
13
14 ALIAS: start first-unsafe
15 ALIAS: end second-unsafe
16
17 : find-interval ( key interval-set -- slice )
18     array>> 2 <sliced-groups>
19     [ start <=> ] with search nip ; inline
20
21 ERROR: not-an-interval-set obj ;
22
23 : check-interval-set ( map -- map )
24     dup interval-set? [ not-an-interval-set ] unless ; inline
25
26 PRIVATE>
27
28 : in? ( key set -- ? )
29     check-interval-set dupd find-interval
30     [ [ start ] [ end 1 - ] bi between? ]
31     [ drop f ] if* ;
32
33 <PRIVATE
34
35 : spec>pairs ( sequence -- intervals )
36     [ dup number? [ dup 2array ] when ] map ;
37
38 : disjoint? ( node1 node2 -- ? )
39     [ end ] [ start ] bi* < ;
40
41 : (delete-redundancies) ( seq -- )
42     dup length {
43         { 0 [ drop ] }
44         { 1 [ % ] }
45         [
46             drop dup first2 <
47             [ unclip-slice , ]
48             [ 2 tail-slice ] if
49             (delete-redundancies) 
50         ]
51     } case ;
52
53 : delete-redundancies ( seq -- seq' )
54     ! If the next element is >= current one, leave out both
55     [ (delete-redundancies) ] uint-array{ } make ;
56
57 : make-intervals ( seq -- interval-set )
58     uint-array{ } like
59     delete-redundancies
60     interval-set boa ;
61
62 : >intervals ( seq -- seq' )
63     [ 1 + ] assoc-map concat ;
64
65 PRIVATE>
66
67 : <interval-set> ( specification -- interval-set )
68     spec>pairs sort-keys
69     >intervals make-intervals ;
70
71 <PRIVATE
72
73 :: or-step ( set1 set2 -- set1' set2' )
74     set1 first ,
75     set1 second set2 first <=
76     [ set1 0 ] [ set2 2 ] if
77     [ second , ] [ set2 swap tail-slice ] bi*
78     set1 2 tail-slice ;
79
80 : combine-or ( set1 set2 -- )
81     {
82         { [ over empty? ] [ % drop ] }
83         { [ dup empty? ] [ drop % ] }
84         [
85             2dup [ first ] bi@ <=
86             [ swap ] unless
87             or-step combine-or
88         ]
89     } cond ;
90
91 PRIVATE>
92
93 : <interval-or> ( set1 set2 -- set )
94     [ array>> ] bi@
95     [ combine-or ] uint-array{ } make
96     make-intervals ;
97
98 <PRIVATE
99
100 : prefix-0 ( seq -- 0seq )
101     0 over ?nth zero? [ rest ] [ 0 prefix ] if ;
102
103 : interval-max ( interval-set1 interval-set2 -- n )
104     [ array>> [ 0 ] [ last ] if-empty ] bi@ max ;
105
106 PRIVATE>
107
108 : <interval-not> ( set maximum -- set' )
109     [ array>> prefix-0 ] dip suffix make-intervals ;
110
111 : <interval-and> ( set1 set2 -- set )
112     2dup interval-max
113     [ '[ _ <interval-not> ] bi@ <interval-or> ] keep
114     <interval-not> ;