1 ! Copyright (C) 2008 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: arrays math kernel accessors sequences sequences.private
4 deques search-deques hashtables ;
7 : unroll-factor 32 ; inline
13 TUPLE: node { data array } { prev ?node } { next ?node } ;
19 { front ?node } { front-pos fixnum }
20 { back ?node } { back-pos fixnum } ;
22 : <unrolled-list> ( -- list )
24 unroll-factor >>back-pos ; inline
26 : <hashed-unrolled-list> ( -- search-deque )
27 20 <hashtable> <unrolled-list> <search-deque> ;
29 ERROR: empty-unrolled-list list ;
33 M: unrolled-list deque-empty?
34 dup [ front>> ] [ back>> ] bi dup [
35 eq? [ [ front-pos>> ] [ back-pos>> ] bi eq? ] [ drop f ] if
38 M: unrolled-list clear-deque
42 unroll-factor >>back-pos
45 : <front-node> ( elt front -- node )
47 unroll-factor 0 <array>
48 [ unroll-factor 1- swap set-nth ] keep f
49 ] dip [ node boa dup ] keep
50 dup [ (>>prev) ] [ 2drop ] if ; inline
52 : normalize-back ( list -- )
54 dup prev>> [ drop ] [ swap front>> >>prev ] if
55 ] [ dup front>> >>back ] if* drop ; inline
57 : push-front/new ( elt list -- )
58 unroll-factor 1- >>front-pos
59 [ <front-node> ] change-front
60 normalize-back ; inline
62 : push-front/existing ( elt list front -- )
63 [ [ 1- ] change-front-pos ] dip
64 [ front-pos>> ] [ data>> ] bi* set-nth-unsafe ; inline
66 M: unrolled-list push-front*
67 dup [ front>> ] [ front-pos>> 0 eq? not ] bi
69 [ push-front/existing ] [ drop push-front/new ] if f ;
71 M: unrolled-list peek-front
73 [ [ front-pos>> ] dip data>> nth-unsafe ]
74 [ empty-unrolled-list ]
77 : pop-front/new ( list front -- )
79 [ f ] change-next drop dup [ f >>prev ] when >>front
80 dup front>> [ normalize-back ] [ f >>back drop ] if ; inline
82 : pop-front/existing ( list front -- )
83 [ dup front-pos>> ] [ data>> ] bi* [ 0 ] 2dip set-nth-unsafe
84 [ 1+ ] change-front-pos
87 M: unrolled-list pop-front*
88 dup front>> [ empty-unrolled-list ] unless*
89 over front-pos>> unroll-factor 1- eq?
90 [ pop-front/new ] [ pop-front/existing ] if ;
92 : <back-node> ( elt back -- node )
94 unroll-factor 0 <array> [ set-first ] keep
95 ] dip [ f node boa dup ] keep
96 dup [ (>>next) ] [ 2drop ] if ; inline
98 : normalize-front ( list -- )
100 dup next>> [ drop ] [ swap back>> >>next ] if
101 ] [ dup back>> >>front ] if* drop ; inline
103 : push-back/new ( elt list -- )
105 [ <back-node> ] change-back
106 normalize-front ; inline
108 : push-back/existing ( elt list back -- )
109 [ [ 1+ ] change-back-pos ] dip
110 [ back-pos>> 1- ] [ data>> ] bi* set-nth-unsafe ; inline
112 M: unrolled-list push-back*
113 dup [ back>> ] [ back-pos>> unroll-factor eq? not ] bi
115 [ push-back/existing ] [ drop push-back/new ] if f ;
117 M: unrolled-list peek-back
119 [ [ back-pos>> 1- ] dip data>> nth-unsafe ]
120 [ empty-unrolled-list ]
123 : pop-back/new ( list back -- )
124 [ unroll-factor >>back-pos ] dip
125 [ f ] change-prev drop dup [ f >>next ] when >>back
126 dup back>> [ normalize-front ] [ f >>front drop ] if ; inline
128 : pop-back/existing ( list back -- )
129 [ [ 1- ] change-back-pos ] dip
130 [ dup back-pos>> ] [ data>> ] bi* [ 0 ] 2dip set-nth-unsafe
133 M: unrolled-list pop-back*
134 dup back>> [ empty-unrolled-list ] unless*
135 over back-pos>> 1 eq?
136 [ pop-back/new ] [ pop-back/existing ] if ;
140 INSTANCE: unrolled-list deque