1 ! Copyright (C) 2005, 2010 Slava Pestov, Joe Groff.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: kernel math math.order strings arrays vectors sequences
4 sequences.private accessors fry combinators ;
10 INSTANCE: chunking sequence
12 GENERIC: group@ ( n groups -- from to seq )
14 M: chunking set-nth group@ <slice> 0 swap copy ;
15 M: chunking like drop { } like ; inline
17 MIXIN: subseq-chunking
18 INSTANCE: subseq-chunking chunking
19 INSTANCE: subseq-chunking sequence
21 M: subseq-chunking nth group@ subseq ; inline
24 INSTANCE: slice-chunking chunking
25 INSTANCE: slice-chunking sequence
27 M: slice-chunking nth group@ <slice> ; inline
28 M: slice-chunking nth-unsafe group@ <slice-unsafe> ; inline
30 MIXIN: abstract-groups
31 INSTANCE: abstract-groups sequence
33 M: abstract-groups length
34 [ seq>> length ] [ n>> ] bi [ + 1 - ] keep /i ; inline
36 M: abstract-groups set-length
37 [ n>> * ] [ seq>> ] bi set-length ; inline
39 M: abstract-groups group@
40 [ n>> [ * dup ] keep + ] [ seq>> ] bi [ length min ] keep ; inline
42 MIXIN: abstract-clumps
43 INSTANCE: abstract-clumps sequence
45 M: abstract-clumps length
46 [ seq>> length 1 + ] [ n>> ] bi [-] ; inline
48 M: abstract-clumps set-length
49 [ n>> + 1 - ] [ seq>> ] bi set-length ; inline
51 M: abstract-clumps group@
52 [ n>> over + ] [ seq>> ] bi ; inline
54 TUPLE: chunking-seq { seq read-only } { n read-only } ;
56 : check-groups ( n -- n )
57 dup 0 <= [ "Invalid group count" throw ] when ; inline
59 : new-groups ( seq n class -- groups )
60 [ check-groups ] dip boa ; inline
62 : slice-mod ( n length -- n' )
63 2dup >= [ - ] [ drop ] if ; inline
65 : check-circular-clumps ( seq n -- seq n )
66 2dup 1 - swap bounds-check 2drop ; inline
70 TUPLE: groups < chunking-seq ;
71 INSTANCE: groups subseq-chunking
72 INSTANCE: groups abstract-groups
74 : <groups> ( seq n -- groups )
75 groups new-groups ; inline
77 TUPLE: sliced-groups < chunking-seq ;
78 INSTANCE: sliced-groups slice-chunking
79 INSTANCE: sliced-groups abstract-groups
81 : <sliced-groups> ( seq n -- groups )
82 sliced-groups new-groups ; inline
84 TUPLE: clumps < chunking-seq ;
85 INSTANCE: clumps subseq-chunking
86 INSTANCE: clumps abstract-clumps
88 : <clumps> ( seq n -- clumps )
89 clumps new-groups ; inline
91 TUPLE: sliced-clumps < chunking-seq ;
92 INSTANCE: sliced-clumps slice-chunking
93 INSTANCE: sliced-clumps abstract-clumps
95 : <sliced-clumps> ( seq n -- clumps )
96 sliced-clumps new-groups ; inline
98 : group ( seq n -- array ) <groups> { } like ;
100 : clump ( seq n -- array ) <clumps> { } like ;
102 : monotonic? ( seq quot: ( elt1 elt2 -- ? ) -- ? )
103 over length 2 < [ 2drop t ] [
105 [ first2-unsafe ] dip call
107 [ 2 <sliced-clumps> ] dip
108 '[ first2-unsafe @ ] all?
112 : all-equal? ( seq -- ? ) [ = ] monotonic? ;
114 : all-eq? ( seq -- ? ) [ eq? ] monotonic? ;
116 TUPLE: circular-slice { from read-only } { to read-only } { seq read-only } ;
118 INSTANCE: circular-slice virtual-sequence
120 M: circular-slice equal? over slice? [ sequence= ] [ 2drop f ] if ;
122 M: circular-slice hashcode* [ sequence-hashcode ] recursive-hashcode ;
124 M: circular-slice length [ to>> ] [ from>> ] bi - ; inline
126 M: circular-slice virtual-exemplar seq>> ; inline
128 M: circular-slice virtual@
129 [ from>> + ] [ seq>> ] bi [ length slice-mod ] keep ; inline
131 C: <circular-slice> circular-slice
133 TUPLE: sliced-circular-clumps < chunking-seq ;
134 INSTANCE: sliced-circular-clumps sequence
136 M: sliced-circular-clumps length
137 seq>> length ; inline
139 M: sliced-circular-clumps nth
140 [ n>> over + ] [ seq>> ] bi <circular-slice> ; inline
142 : <sliced-circular-clumps> ( seq n -- clumps )
143 check-circular-clumps sliced-circular-clumps boa ; inline
145 TUPLE: circular-clumps < chunking-seq ;
146 INSTANCE: circular-clumps sequence
148 M: circular-clumps length
149 seq>> length ; inline
151 M: circular-clumps nth
152 [ n>> over + ] [ seq>> ] bi [ <circular-slice> ] [ like ] bi ; inline
154 : <circular-clumps> ( seq n -- clumps )
155 check-circular-clumps circular-clumps boa ; inline
157 : circular-clump ( seq n -- array )
158 <circular-clumps> { } like ; inline