1818import java .util .concurrent .atomic .AtomicBoolean ;
1919
2020public class PersistentVector extends APersistentVector implements IEditableCollection {
21+ public static final int CHUNK = 32 ;
22+ public static final int SHIFT = 5 ;
23+ public static final int MASK = 0x01f ;
2124
22- static class Node {
23- final AtomicBoolean edit ;
24- final Object [] array ;
25+ //note: public fields/classes/ctors for use by Clojure lib only
26+ static public class Node {
27+ public final AtomicBoolean edit ;
28+ public final Object [] array ;
2529
26- Node (AtomicBoolean edit , Object [] array ){
30+ public Node (AtomicBoolean edit , Object [] array ){
2731 this .edit = edit ;
2832 this .array = array ;
2933 }
3034
3135 Node (AtomicBoolean edit ){
3236 this .edit = edit ;
33- this .array = new Object [32 ];
37+ this .array = new Object [CHUNK ];
3438 }
3539}
3640
3741final static AtomicBoolean NOEDIT = new AtomicBoolean (false );
38- final static Node EMPTY_NODE = new Node (NOEDIT , new Object [32 ]);
42+ final static Node EMPTY_NODE = new Node (NOEDIT , new Object [CHUNK ]);
3943
40- final int cnt ;
41- final int shift ;
42- final Node root ;
43- final Object [] tail ;
44+ public final int cnt ;
45+ public final int shift ;
46+ public final Node root ;
47+ public final Object [] tail ;
4448
45- public final static PersistentVector EMPTY = new PersistentVector (0 , 5 , EMPTY_NODE , new Object []{});
49+ public final static PersistentVector EMPTY = new PersistentVector (0 , SHIFT , EMPTY_NODE , new Object []{});
4650
4751static public PersistentVector create (ISeq items ){
4852 MutableVector ret = EMPTY .mutable ();
@@ -65,7 +69,7 @@ static public PersistentVector create(Object... items){
6569 return ret .immutable ();
6670}
6771
68- PersistentVector (int cnt , int shift , Node root , Object [] tail ){
72+ public PersistentVector (int cnt , int shift , Node root , Object [] tail ){
6973 super (null );
7074 this .cnt = cnt ;
7175 this .shift = shift ;
@@ -87,9 +91,9 @@ public MutableVector mutable(){
8791}
8892
8993final int tailoff (){
90- if (cnt < 32 )
94+ if (cnt < CHUNK )
9195 return 0 ;
92- return ((cnt - 1 ) >>> 5 ) << 5 ;
96+ return ((cnt - 1 ) >>> SHIFT ) << SHIFT ;
9397}
9498
9599public Object [] arrayFor (int i ){
@@ -98,16 +102,16 @@ public Object[] arrayFor(int i){
98102 if (i >= tailoff ())
99103 return tail ;
100104 Node node = root ;
101- for (int level = shift ; level > 0 ; level -= 5 )
102- node = (Node ) node .array [(i >>> level ) & 0x01f ];
105+ for (int level = shift ; level > 0 ; level -= SHIFT )
106+ node = (Node ) node .array [(i >>> level ) & MASK ];
103107 return node .array ;
104108 }
105109 throw new IndexOutOfBoundsException ();
106110}
107111
108112public Object nth (int i ){
109113 Object [] node = arrayFor (i );
110- return node [i & 0x01f ];
114+ return node [i & MASK ];
111115}
112116
113117public PersistentVector assocN (int i , Object val ){
@@ -117,7 +121,7 @@ public PersistentVector assocN(int i, Object val){
117121 {
118122 Object [] newTail = new Object [tail .length ];
119123 System .arraycopy (tail , 0 , newTail , 0 , tail .length );
120- newTail [i & 0x01f ] = val ;
124+ newTail [i & MASK ] = val ;
121125
122126 return new PersistentVector (meta (), cnt , shift , root , newTail );
123127 }
@@ -133,12 +137,12 @@ private static Node doAssoc(int level, Node node, int i, Object val){
133137 Node ret = new Node (node .edit ,node .array .clone ());
134138 if (level == 0 )
135139 {
136- ret .array [i & 0x01f ] = val ;
140+ ret .array [i & MASK ] = val ;
137141 }
138142 else
139143 {
140- int subidx = (i >>> level ) & 0x01f ;
141- ret .array [subidx ] = doAssoc (level - 5 , (Node ) node .array [subidx ], i , val );
144+ int subidx = (i >>> level ) & MASK ;
145+ ret .array [subidx ] = doAssoc (level - SHIFT , (Node ) node .array [subidx ], i , val );
142146 }
143147 return ret ;
144148}
@@ -156,7 +160,7 @@ public PersistentVector cons(Object val){
156160 int i = cnt ;
157161 //room in tail?
158162// if(tail.length < 32)
159- if (cnt - tailoff () < 32 )
163+ if (cnt - tailoff () < CHUNK )
160164 {
161165 Object [] newTail = new Object [tail .length + 1 ];
162166 System .arraycopy (tail , 0 , newTail , 0 , tail .length );
@@ -168,12 +172,12 @@ public PersistentVector cons(Object val){
168172 Node tailnode = new Node (root .edit ,tail );
169173 int newshift = shift ;
170174 //overflow root?
171- if ((cnt >>> 5 ) > (1 << shift ))
175+ if ((cnt >>> SHIFT ) > (1 << shift ))
172176 {
173177 newroot = new Node (root .edit );
174178 newroot .array [0 ] = root ;
175179 newroot .array [1 ] = newPath (root .edit ,shift , tailnode );
176- newshift += 5 ;
180+ newshift += SHIFT ;
177181 }
178182 else
179183 newroot = pushTail (shift , root , tailnode );
@@ -185,19 +189,19 @@ private Node pushTail(int level, Node parent, Node tailnode){
185189 // else does it map to an existing child? -> nodeToInsert = pushNode one more level
186190 // else alloc new path
187191 //return nodeToInsert placed in copy of parent
188- int subidx = ((cnt - 1 ) >>> level ) & 0x01f ;
192+ int subidx = ((cnt - 1 ) >>> level ) & MASK ;
189193 Node ret = new Node (parent .edit , parent .array .clone ());
190194 Node nodeToInsert ;
191- if (level == 5 )
195+ if (level == SHIFT )
192196 {
193197 nodeToInsert = tailnode ;
194198 }
195199 else
196200 {
197201 Node child = (Node ) parent .array [subidx ];
198202 nodeToInsert = (child != null )?
199- pushTail (level -5 ,child , tailnode )
200- :newPath (root .edit ,level -5 , tailnode );
203+ pushTail (level - SHIFT ,child , tailnode )
204+ :newPath (root .edit ,level - SHIFT , tailnode );
201205 }
202206 ret .array [subidx ] = nodeToInsert ;
203207 return ret ;
@@ -207,7 +211,7 @@ private static Node newPath(AtomicBoolean edit,int level, Node node){
207211 if (level == 0 )
208212 return node ;
209213 Node ret = new Node (edit );
210- ret .array [0 ] = newPath (edit , level - 5 , node );
214+ ret .array [0 ] = newPath (edit , level - SHIFT , node );
211215 return ret ;
212216}
213217
@@ -339,19 +343,19 @@ public PersistentVector pop(){
339343 {
340344 newroot = EMPTY_NODE ;
341345 }
342- if (shift > 5 && newroot .array [1 ] == null )
346+ if (shift > SHIFT && newroot .array [1 ] == null )
343347 {
344348 newroot = (Node ) newroot .array [0 ];
345- newshift -= 5 ;
349+ newshift -= SHIFT ;
346350 }
347351 return new PersistentVector (meta (), cnt - 1 , newshift , newroot , newtail );
348352}
349353
350354private Node popTail (int level , Node node ){
351- int subidx = ((cnt -2 ) >>> level ) & 0x01f ;
352- if (level > 5 )
355+ int subidx = ((cnt -2 ) >>> level ) & MASK ;
356+ if (level > SHIFT )
353357 {
354- Node newchild = popTail (level - 5 , (Node ) node .array [subidx ]);
358+ Node newchild = popTail (level - SHIFT , (Node ) node .array [subidx ]);
355359 if (newchild == null && subidx == 0 )
356360 return null ;
357361 else
@@ -417,7 +421,7 @@ public PersistentVector immutable(){
417421 }
418422
419423 static Object [] editableTail (Object [] tl ){
420- Object [] ret = new Object [32 ];
424+ Object [] ret = new Object [CHUNK ];
421425 System .arraycopy (tl ,0 ,ret ,0 ,tl .length );
422426 return ret ;
423427 }
@@ -426,25 +430,25 @@ public MutableVector conj(Object val){
426430 ensureEditable ();
427431 int i = cnt ;
428432 //room in tail?
429- if (i - tailoff () < 32 )
433+ if (i - tailoff () < CHUNK )
430434 {
431- tail [i & 0x01f ] = val ;
435+ tail [i & MASK ] = val ;
432436 ++cnt ;
433437 return this ;
434438 }
435439 //full tail, push into tree
436440 Node newroot ;
437441 Node tailnode = new Node (root .edit , tail );
438- tail = new Object [32 ];
442+ tail = new Object [CHUNK ];
439443 tail [0 ] = val ;
440444 int newshift = shift ;
441445 //overflow root?
442- if ((cnt >>> 5 ) > (1 << shift ))
446+ if ((cnt >>> SHIFT ) > (1 << shift ))
443447 {
444448 newroot = new Node (root .edit );
445449 newroot .array [0 ] = root ;
446450 newroot .array [1 ] = newPath (root .edit ,shift , tailnode );
447- newshift += 5 ;
451+ newshift += SHIFT ;
448452 }
449453 else
450454 newroot = pushTail (shift , root , tailnode );
@@ -460,28 +464,28 @@ private Node pushTail(int level, Node parent, Node tailnode){
460464 // else alloc new path
461465 //return nodeToInsert placed in parent
462466 parent = ensureEditable (parent );
463- int subidx = ((cnt - 1 ) >>> level ) & 0x01f ;
467+ int subidx = ((cnt - 1 ) >>> level ) & MASK ;
464468 Node ret = parent ;
465469 Node nodeToInsert ;
466- if (level == 5 )
470+ if (level == SHIFT )
467471 {
468472 nodeToInsert = tailnode ;
469473 }
470474 else
471475 {
472476 Node child = (Node ) parent .array [subidx ];
473477 nodeToInsert = (child != null ) ?
474- pushTail (level - 5 , child , tailnode )
475- : newPath (root .edit , level - 5 , tailnode );
478+ pushTail (level - SHIFT , child , tailnode )
479+ : newPath (root .edit , level - SHIFT , tailnode );
476480 }
477481 ret .array [subidx ] = nodeToInsert ;
478482 return ret ;
479483 }
480484
481485 final int tailoff (){
482- if (cnt < 32 )
486+ if (cnt < CHUNK )
483487 return 0 ;
484- return ((cnt -1 ) >>> 5 ) << 5 ;
488+ return ((cnt -1 ) >>> SHIFT ) << SHIFT ;
485489 }
486490
487491 private Object [] arrayFor (int i ){
@@ -490,8 +494,8 @@ private Object[] arrayFor(int i){
490494 if (i >= tailoff ())
491495 return tail ;
492496 Node node = root ;
493- for (int level = shift ; level > 0 ; level -= 5 )
494- node = (Node ) node .array [(i >>> level ) & 0x01f ];
497+ for (int level = shift ; level > 0 ; level -= SHIFT )
498+ node = (Node ) node .array [(i >>> level ) & MASK ];
495499 return node .array ;
496500 }
497501 throw new IndexOutOfBoundsException ();
@@ -509,7 +513,7 @@ public Object valAt(Object key){
509513
510514 public Object nth (int i ){
511515 Object [] node = arrayFor (i );
512- return node [i & 0x01f ];
516+ return node [i & MASK ];
513517 }
514518
515519 public MutableVector assocN (int i , Object val ){
@@ -518,7 +522,7 @@ public MutableVector assocN(int i, Object val){
518522 {
519523 if (i >= tailoff ())
520524 {
521- tail [i & 0x01f ] = val ;
525+ tail [i & MASK ] = val ;
522526 return this ;
523527 }
524528
@@ -544,12 +548,12 @@ private Node doAssoc(int level, Node node, int i, Object val){
544548 Node ret = node ;
545549 if (level == 0 )
546550 {
547- ret .array [i & 0x01f ] = val ;
551+ ret .array [i & MASK ] = val ;
548552 }
549553 else
550554 {
551- int subidx = (i >>> level ) & 0x01f ;
552- ret .array [subidx ] = doAssoc (level - 5 , (Node ) node .array [subidx ], i , val );
555+ int subidx = (i >>> level ) & MASK ;
556+ ret .array [subidx ] = doAssoc (level - SHIFT , (Node ) node .array [subidx ], i , val );
553557 }
554558 return ret ;
555559 }
@@ -565,7 +569,7 @@ public MutableVector pop(){
565569 }
566570 int i = cnt - 1 ;
567571 //pop in tail?
568- if ((i & 0x01f ) > 0 )
572+ if ((i & MASK ) > 0 )
569573 {
570574 --cnt ;
571575 return this ;
@@ -579,10 +583,10 @@ public MutableVector pop(){
579583 {
580584 newroot = EMPTY_NODE ;
581585 }
582- if (shift > 5 && newroot .array [1 ] == null )
586+ if (shift > SHIFT && newroot .array [1 ] == null )
583587 {
584588 newroot = (Node ) newroot .array [0 ];
585- newshift -= 5 ;
589+ newshift -= SHIFT ;
586590 }
587591 root = newroot ;
588592 shift = newshift ;
@@ -593,10 +597,10 @@ public MutableVector pop(){
593597
594598 private Node popTail (int level , Node node ){
595599 node = ensureEditable (node );
596- int subidx = ((cnt - 2 ) >>> level ) & 0x01f ;
597- if (level > 5 )
600+ int subidx = ((cnt - 2 ) >>> level ) & MASK ;
601+ if (level > SHIFT )
598602 {
599- Node newchild = popTail (level - 5 , (Node ) node .array [subidx ]);
603+ Node newchild = popTail (level - SHIFT , (Node ) node .array [subidx ]);
600604 if (newchild == null && subidx == 0 )
601605 return null ;
602606 else
0 commit comments