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
8 ! Sets of positive integers
10 TUPLE: interval-set { array uint-array read-only } ;
14 ALIAS: start first-unsafe
15 ALIAS: end second-unsafe
17 : find-interval ( key interval-set -- slice )
18 array>> swap dupd [ >=< ] curry search drop
19 [ dup even? [ dup 1 + ] [ [ 1 - ] keep ] if rot <slice-unsafe> ]
20 [ drop f ] if* ; inline
22 ERROR: not-an-interval-set obj ;
24 : check-interval-set ( map -- map )
25 dup interval-set? [ not-an-interval-set ] unless ; inline
29 : in? ( key set -- ? )
30 check-interval-set dupd find-interval
31 [ [ start ] [ end 1 - ] bi between? ]
36 : spec>pairs ( sequence -- intervals )
37 [ dup number? [ dup 2array ] when ] map ;
39 : disjoint? ( node1 node2 -- ? )
40 [ end ] [ start ] bi* < ;
42 : (delete-redundancies) ( seq -- )
54 : delete-redundancies ( seq -- seq' )
55 ! If the next element is >= current one, leave out both
56 [ (delete-redundancies) ] uint-array{ } make ;
58 : make-intervals ( seq -- interval-set )
63 : >intervals ( seq -- seq' )
64 [ 1 + ] assoc-map concat ;
68 : <interval-set> ( specification -- interval-set )
70 >intervals make-intervals ;
74 :: or-step ( set1 set2 -- set1' set2' )
76 set1 second set2 first <=
77 [ set1 0 ] [ set2 2 ] if
78 [ second , ] [ set2 swap tail-slice ] bi*
81 : combine-or ( set1 set2 -- )
83 { [ over empty? ] [ % drop ] }
84 { [ dup empty? ] [ drop % ] }
94 : <interval-or> ( set1 set2 -- set )
96 [ combine-or ] uint-array{ } make
101 : prefix-0 ( seq -- 0seq )
102 0 over ?nth zero? [ rest ] [ 0 prefix ] if ;
104 : interval-max ( interval-set1 interval-set2 -- n )
105 [ array>> [ 0 ] [ last ] if-empty ] bi@ max ;
109 : <interval-not> ( set maximum -- set' )
110 [ array>> prefix-0 ] dip suffix make-intervals ;
112 : <interval-and> ( set1 set2 -- set )
114 [ '[ _ <interval-not> ] bi@ <interval-or> ] keep