Mercurial > lasercutter
comparison src/clojure/lang/PersistentVector.java @ 10:ef7dbbd6452c
added clojure source goodness
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 21 Aug 2010 06:25:44 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
9:35cf337adfcf | 10:ef7dbbd6452c |
---|---|
1 /** | |
2 * Copyright (c) Rich Hickey. All rights reserved. | |
3 * The use and distribution terms for this software are covered by the | |
4 * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) | |
5 * which can be found in the file epl-v10.html at the root of this distribution. | |
6 * By using this software in any fashion, you are agreeing to be bound by | |
7 * the terms of this license. | |
8 * You must not remove this notice, or any other, from this software. | |
9 **/ | |
10 | |
11 /* rich Jul 5, 2007 */ | |
12 | |
13 package clojure.lang; | |
14 | |
15 import java.io.Serializable; | |
16 import java.util.List; | |
17 import java.util.concurrent.atomic.AtomicReference; | |
18 | |
19 public class PersistentVector extends APersistentVector implements IObj, IEditableCollection{ | |
20 | |
21 static class Node implements Serializable { | |
22 transient final AtomicReference<Thread> edit; | |
23 final Object[] array; | |
24 | |
25 Node(AtomicReference<Thread> edit, Object[] array){ | |
26 this.edit = edit; | |
27 this.array = array; | |
28 } | |
29 | |
30 Node(AtomicReference<Thread> edit){ | |
31 this.edit = edit; | |
32 this.array = new Object[32]; | |
33 } | |
34 } | |
35 | |
36 final static AtomicReference<Thread> NOEDIT = new AtomicReference<Thread>(null); | |
37 final static Node EMPTY_NODE = new Node(NOEDIT, new Object[32]); | |
38 | |
39 final int cnt; | |
40 final int shift; | |
41 final Node root; | |
42 final Object[] tail; | |
43 final IPersistentMap _meta; | |
44 | |
45 | |
46 public final static PersistentVector EMPTY = new PersistentVector(0, 5, EMPTY_NODE, new Object[]{}); | |
47 | |
48 static public PersistentVector create(ISeq items){ | |
49 TransientVector ret = EMPTY.asTransient(); | |
50 for(; items != null; items = items.next()) | |
51 ret = ret.conj(items.first()); | |
52 return ret.persistent(); | |
53 } | |
54 | |
55 static public PersistentVector create(List items){ | |
56 TransientVector ret = EMPTY.asTransient(); | |
57 for(Object item : items) | |
58 ret = ret.conj(item); | |
59 return ret.persistent(); | |
60 } | |
61 | |
62 static public PersistentVector create(Object... items){ | |
63 TransientVector ret = EMPTY.asTransient(); | |
64 for(Object item : items) | |
65 ret = ret.conj(item); | |
66 return ret.persistent(); | |
67 } | |
68 | |
69 PersistentVector(int cnt, int shift, Node root, Object[] tail){ | |
70 this._meta = null; | |
71 this.cnt = cnt; | |
72 this.shift = shift; | |
73 this.root = root; | |
74 this.tail = tail; | |
75 } | |
76 | |
77 | |
78 PersistentVector(IPersistentMap meta, int cnt, int shift, Node root, Object[] tail){ | |
79 this._meta = meta; | |
80 this.cnt = cnt; | |
81 this.shift = shift; | |
82 this.root = root; | |
83 this.tail = tail; | |
84 } | |
85 | |
86 public TransientVector asTransient(){ | |
87 return new TransientVector(this); | |
88 } | |
89 | |
90 final int tailoff(){ | |
91 if(cnt < 32) | |
92 return 0; | |
93 return ((cnt - 1) >>> 5) << 5; | |
94 } | |
95 | |
96 public Object[] arrayFor(int i){ | |
97 if(i >= 0 && i < cnt) | |
98 { | |
99 if(i >= tailoff()) | |
100 return tail; | |
101 Node node = root; | |
102 for(int level = shift; level > 0; level -= 5) | |
103 node = (Node) node.array[(i >>> level) & 0x01f]; | |
104 return node.array; | |
105 } | |
106 throw new IndexOutOfBoundsException(); | |
107 } | |
108 | |
109 public Object nth(int i){ | |
110 Object[] node = arrayFor(i); | |
111 return node[i & 0x01f]; | |
112 } | |
113 | |
114 public Object nth(int i, Object notFound){ | |
115 if(i >= 0 && i < cnt) | |
116 return nth(i); | |
117 return notFound; | |
118 } | |
119 | |
120 public PersistentVector assocN(int i, Object val){ | |
121 if(i >= 0 && i < cnt) | |
122 { | |
123 if(i >= tailoff()) | |
124 { | |
125 Object[] newTail = new Object[tail.length]; | |
126 System.arraycopy(tail, 0, newTail, 0, tail.length); | |
127 newTail[i & 0x01f] = val; | |
128 | |
129 return new PersistentVector(meta(), cnt, shift, root, newTail); | |
130 } | |
131 | |
132 return new PersistentVector(meta(), cnt, shift, doAssoc(shift, root, i, val), tail); | |
133 } | |
134 if(i == cnt) | |
135 return cons(val); | |
136 throw new IndexOutOfBoundsException(); | |
137 } | |
138 | |
139 private static Node doAssoc(int level, Node node, int i, Object val){ | |
140 Node ret = new Node(node.edit,node.array.clone()); | |
141 if(level == 0) | |
142 { | |
143 ret.array[i & 0x01f] = val; | |
144 } | |
145 else | |
146 { | |
147 int subidx = (i >>> level) & 0x01f; | |
148 ret.array[subidx] = doAssoc(level - 5, (Node) node.array[subidx], i, val); | |
149 } | |
150 return ret; | |
151 } | |
152 | |
153 public int count(){ | |
154 return cnt; | |
155 } | |
156 | |
157 public PersistentVector withMeta(IPersistentMap meta){ | |
158 return new PersistentVector(meta, cnt, shift, root, tail); | |
159 } | |
160 | |
161 public IPersistentMap meta(){ | |
162 return _meta; | |
163 } | |
164 | |
165 | |
166 public PersistentVector cons(Object val){ | |
167 int i = cnt; | |
168 //room in tail? | |
169 // if(tail.length < 32) | |
170 if(cnt - tailoff() < 32) | |
171 { | |
172 Object[] newTail = new Object[tail.length + 1]; | |
173 System.arraycopy(tail, 0, newTail, 0, tail.length); | |
174 newTail[tail.length] = val; | |
175 return new PersistentVector(meta(), cnt + 1, shift, root, newTail); | |
176 } | |
177 //full tail, push into tree | |
178 Node newroot; | |
179 Node tailnode = new Node(root.edit,tail); | |
180 int newshift = shift; | |
181 //overflow root? | |
182 if((cnt >>> 5) > (1 << shift)) | |
183 { | |
184 newroot = new Node(root.edit); | |
185 newroot.array[0] = root; | |
186 newroot.array[1] = newPath(root.edit,shift, tailnode); | |
187 newshift += 5; | |
188 } | |
189 else | |
190 newroot = pushTail(shift, root, tailnode); | |
191 return new PersistentVector(meta(), cnt + 1, newshift, newroot, new Object[]{val}); | |
192 } | |
193 | |
194 private Node pushTail(int level, Node parent, Node tailnode){ | |
195 //if parent is leaf, insert node, | |
196 // else does it map to an existing child? -> nodeToInsert = pushNode one more level | |
197 // else alloc new path | |
198 //return nodeToInsert placed in copy of parent | |
199 int subidx = ((cnt - 1) >>> level) & 0x01f; | |
200 Node ret = new Node(parent.edit, parent.array.clone()); | |
201 Node nodeToInsert; | |
202 if(level == 5) | |
203 { | |
204 nodeToInsert = tailnode; | |
205 } | |
206 else | |
207 { | |
208 Node child = (Node) parent.array[subidx]; | |
209 nodeToInsert = (child != null)? | |
210 pushTail(level-5,child, tailnode) | |
211 :newPath(root.edit,level-5, tailnode); | |
212 } | |
213 ret.array[subidx] = nodeToInsert; | |
214 return ret; | |
215 } | |
216 | |
217 private static Node newPath(AtomicReference<Thread> edit,int level, Node node){ | |
218 if(level == 0) | |
219 return node; | |
220 Node ret = new Node(edit); | |
221 ret.array[0] = newPath(edit, level - 5, node); | |
222 return ret; | |
223 } | |
224 | |
225 public IChunkedSeq chunkedSeq(){ | |
226 if(count() == 0) | |
227 return null; | |
228 return new ChunkedSeq(this,0,0); | |
229 } | |
230 | |
231 public ISeq seq(){ | |
232 return chunkedSeq(); | |
233 } | |
234 | |
235 static public final class ChunkedSeq extends ASeq implements IChunkedSeq{ | |
236 | |
237 public final PersistentVector vec; | |
238 final Object[] node; | |
239 final int i; | |
240 public final int offset; | |
241 | |
242 public ChunkedSeq(PersistentVector vec, int i, int offset){ | |
243 this.vec = vec; | |
244 this.i = i; | |
245 this.offset = offset; | |
246 this.node = vec.arrayFor(i); | |
247 } | |
248 | |
249 ChunkedSeq(IPersistentMap meta, PersistentVector vec, Object[] node, int i, int offset){ | |
250 super(meta); | |
251 this.vec = vec; | |
252 this.node = node; | |
253 this.i = i; | |
254 this.offset = offset; | |
255 } | |
256 | |
257 ChunkedSeq(PersistentVector vec, Object[] node, int i, int offset){ | |
258 this.vec = vec; | |
259 this.node = node; | |
260 this.i = i; | |
261 this.offset = offset; | |
262 } | |
263 | |
264 public IChunk chunkedFirst() throws Exception{ | |
265 return new ArrayChunk(node, offset); | |
266 } | |
267 | |
268 public ISeq chunkedNext(){ | |
269 if(i + node.length < vec.cnt) | |
270 return new ChunkedSeq(vec,i+ node.length,0); | |
271 return null; | |
272 } | |
273 | |
274 public ISeq chunkedMore(){ | |
275 ISeq s = chunkedNext(); | |
276 if(s == null) | |
277 return PersistentList.EMPTY; | |
278 return s; | |
279 } | |
280 | |
281 public Obj withMeta(IPersistentMap meta){ | |
282 if(meta == this._meta) | |
283 return this; | |
284 return new ChunkedSeq(meta, vec, node, i, offset); | |
285 } | |
286 | |
287 public Object first(){ | |
288 return node[offset]; | |
289 } | |
290 | |
291 public ISeq next(){ | |
292 if(offset + 1 < node.length) | |
293 return new ChunkedSeq(vec, node, i, offset + 1); | |
294 return chunkedNext(); | |
295 } | |
296 } | |
297 | |
298 public IPersistentCollection empty(){ | |
299 return EMPTY.withMeta(meta()); | |
300 } | |
301 | |
302 //private Node pushTail(int level, Node node, Object[] tailNode, Box expansion){ | |
303 // Object newchild; | |
304 // if(level == 0) | |
305 // { | |
306 // newchild = tailNode; | |
307 // } | |
308 // else | |
309 // { | |
310 // newchild = pushTail(level - 5, (Object[]) arr[arr.length - 1], tailNode, expansion); | |
311 // if(expansion.val == null) | |
312 // { | |
313 // Object[] ret = arr.clone(); | |
314 // ret[arr.length - 1] = newchild; | |
315 // return ret; | |
316 // } | |
317 // else | |
318 // newchild = expansion.val; | |
319 // } | |
320 // //expansion | |
321 // if(arr.length == 32) | |
322 // { | |
323 // expansion.val = new Object[]{newchild}; | |
324 // return arr; | |
325 // } | |
326 // Object[] ret = new Object[arr.length + 1]; | |
327 // System.arraycopy(arr, 0, ret, 0, arr.length); | |
328 // ret[arr.length] = newchild; | |
329 // expansion.val = null; | |
330 // return ret; | |
331 //} | |
332 | |
333 public PersistentVector pop(){ | |
334 if(cnt == 0) | |
335 throw new IllegalStateException("Can't pop empty vector"); | |
336 if(cnt == 1) | |
337 return EMPTY.withMeta(meta()); | |
338 //if(tail.length > 1) | |
339 if(cnt-tailoff() > 1) | |
340 { | |
341 Object[] newTail = new Object[tail.length - 1]; | |
342 System.arraycopy(tail, 0, newTail, 0, newTail.length); | |
343 return new PersistentVector(meta(), cnt - 1, shift, root, newTail); | |
344 } | |
345 Object[] newtail = arrayFor(cnt - 2); | |
346 | |
347 Node newroot = popTail(shift, root); | |
348 int newshift = shift; | |
349 if(newroot == null) | |
350 { | |
351 newroot = EMPTY_NODE; | |
352 } | |
353 if(shift > 5 && newroot.array[1] == null) | |
354 { | |
355 newroot = (Node) newroot.array[0]; | |
356 newshift -= 5; | |
357 } | |
358 return new PersistentVector(meta(), cnt - 1, newshift, newroot, newtail); | |
359 } | |
360 | |
361 private Node popTail(int level, Node node){ | |
362 int subidx = ((cnt-2) >>> level) & 0x01f; | |
363 if(level > 5) | |
364 { | |
365 Node newchild = popTail(level - 5, (Node) node.array[subidx]); | |
366 if(newchild == null && subidx == 0) | |
367 return null; | |
368 else | |
369 { | |
370 Node ret = new Node(root.edit, node.array.clone()); | |
371 ret.array[subidx] = newchild; | |
372 return ret; | |
373 } | |
374 } | |
375 else if(subidx == 0) | |
376 return null; | |
377 else | |
378 { | |
379 Node ret = new Node(root.edit, node.array.clone()); | |
380 ret.array[subidx] = null; | |
381 return ret; | |
382 } | |
383 } | |
384 | |
385 static final class TransientVector extends AFn implements ITransientVector, Counted{ | |
386 int cnt; | |
387 int shift; | |
388 Node root; | |
389 Object[] tail; | |
390 | |
391 TransientVector(int cnt, int shift, Node root, Object[] tail){ | |
392 this.cnt = cnt; | |
393 this.shift = shift; | |
394 this.root = root; | |
395 this.tail = tail; | |
396 } | |
397 | |
398 TransientVector(PersistentVector v){ | |
399 this(v.cnt, v.shift, editableRoot(v.root), editableTail(v.tail)); | |
400 } | |
401 | |
402 public int count(){ | |
403 ensureEditable(); | |
404 return cnt; | |
405 } | |
406 | |
407 Node ensureEditable(Node node){ | |
408 if(node.edit == root.edit) | |
409 return node; | |
410 return new Node(root.edit, node.array.clone()); | |
411 } | |
412 | |
413 void ensureEditable(){ | |
414 Thread owner = root.edit.get(); | |
415 if(owner == Thread.currentThread()) | |
416 return; | |
417 if(owner != null) | |
418 throw new IllegalAccessError("Transient used by non-owner thread"); | |
419 throw new IllegalAccessError("Transient used after persistent! call"); | |
420 | |
421 // root = editableRoot(root); | |
422 // tail = editableTail(tail); | |
423 } | |
424 | |
425 static Node editableRoot(Node node){ | |
426 return new Node(new AtomicReference<Thread>(Thread.currentThread()), node.array.clone()); | |
427 } | |
428 | |
429 public PersistentVector persistent(){ | |
430 ensureEditable(); | |
431 // Thread owner = root.edit.get(); | |
432 // if(owner != null && owner != Thread.currentThread()) | |
433 // { | |
434 // throw new IllegalAccessError("Mutation release by non-owner thread"); | |
435 // } | |
436 root.edit.set(null); | |
437 Object[] trimmedTail = new Object[cnt-tailoff()]; | |
438 System.arraycopy(tail,0,trimmedTail,0,trimmedTail.length); | |
439 return new PersistentVector(cnt, shift, root, trimmedTail); | |
440 } | |
441 | |
442 static Object[] editableTail(Object[] tl){ | |
443 Object[] ret = new Object[32]; | |
444 System.arraycopy(tl,0,ret,0,tl.length); | |
445 return ret; | |
446 } | |
447 | |
448 public TransientVector conj(Object val){ | |
449 ensureEditable(); | |
450 int i = cnt; | |
451 //room in tail? | |
452 if(i - tailoff() < 32) | |
453 { | |
454 tail[i & 0x01f] = val; | |
455 ++cnt; | |
456 return this; | |
457 } | |
458 //full tail, push into tree | |
459 Node newroot; | |
460 Node tailnode = new Node(root.edit, tail); | |
461 tail = new Object[32]; | |
462 tail[0] = val; | |
463 int newshift = shift; | |
464 //overflow root? | |
465 if((cnt >>> 5) > (1 << shift)) | |
466 { | |
467 newroot = new Node(root.edit); | |
468 newroot.array[0] = root; | |
469 newroot.array[1] = newPath(root.edit,shift, tailnode); | |
470 newshift += 5; | |
471 } | |
472 else | |
473 newroot = pushTail(shift, root, tailnode); | |
474 root = newroot; | |
475 shift = newshift; | |
476 ++cnt; | |
477 return this; | |
478 } | |
479 | |
480 private Node pushTail(int level, Node parent, Node tailnode){ | |
481 //if parent is leaf, insert node, | |
482 // else does it map to an existing child? -> nodeToInsert = pushNode one more level | |
483 // else alloc new path | |
484 //return nodeToInsert placed in parent | |
485 parent = ensureEditable(parent); | |
486 int subidx = ((cnt - 1) >>> level) & 0x01f; | |
487 Node ret = parent; | |
488 Node nodeToInsert; | |
489 if(level == 5) | |
490 { | |
491 nodeToInsert = tailnode; | |
492 } | |
493 else | |
494 { | |
495 Node child = (Node) parent.array[subidx]; | |
496 nodeToInsert = (child != null) ? | |
497 pushTail(level - 5, child, tailnode) | |
498 : newPath(root.edit, level - 5, tailnode); | |
499 } | |
500 ret.array[subidx] = nodeToInsert; | |
501 return ret; | |
502 } | |
503 | |
504 final private int tailoff(){ | |
505 if(cnt < 32) | |
506 return 0; | |
507 return ((cnt-1) >>> 5) << 5; | |
508 } | |
509 | |
510 private Object[] arrayFor(int i){ | |
511 if(i >= 0 && i < cnt) | |
512 { | |
513 if(i >= tailoff()) | |
514 return tail; | |
515 Node node = root; | |
516 for(int level = shift; level > 0; level -= 5) | |
517 node = (Node) node.array[(i >>> level) & 0x01f]; | |
518 return node.array; | |
519 } | |
520 throw new IndexOutOfBoundsException(); | |
521 } | |
522 | |
523 public Object valAt(Object key){ | |
524 //note - relies on ensureEditable in 2-arg valAt | |
525 return valAt(key, null); | |
526 } | |
527 | |
528 public Object valAt(Object key, Object notFound){ | |
529 ensureEditable(); | |
530 if(Util.isInteger(key)) | |
531 { | |
532 int i = ((Number) key).intValue(); | |
533 if(i >= 0 && i < cnt) | |
534 return nth(i); | |
535 } | |
536 return notFound; | |
537 } | |
538 | |
539 public Object invoke(Object arg1) throws Exception{ | |
540 //note - relies on ensureEditable in nth | |
541 if(Util.isInteger(arg1)) | |
542 return nth(((Number) arg1).intValue()); | |
543 throw new IllegalArgumentException("Key must be integer"); | |
544 } | |
545 | |
546 public Object nth(int i){ | |
547 ensureEditable(); | |
548 Object[] node = arrayFor(i); | |
549 return node[i & 0x01f]; | |
550 } | |
551 | |
552 public Object nth(int i, Object notFound){ | |
553 if(i >= 0 && i < count()) | |
554 return nth(i); | |
555 return notFound; | |
556 } | |
557 | |
558 public TransientVector assocN(int i, Object val){ | |
559 ensureEditable(); | |
560 if(i >= 0 && i < cnt) | |
561 { | |
562 if(i >= tailoff()) | |
563 { | |
564 tail[i & 0x01f] = val; | |
565 return this; | |
566 } | |
567 | |
568 root = doAssoc(shift, root, i, val); | |
569 return this; | |
570 } | |
571 if(i == cnt) | |
572 return conj(val); | |
573 throw new IndexOutOfBoundsException(); | |
574 } | |
575 | |
576 public TransientVector assoc(Object key, Object val){ | |
577 //note - relies on ensureEditable in assocN | |
578 if(Util.isInteger(key)) | |
579 { | |
580 int i = ((Number) key).intValue(); | |
581 return assocN(i, val); | |
582 } | |
583 throw new IllegalArgumentException("Key must be integer"); | |
584 } | |
585 | |
586 private Node doAssoc(int level, Node node, int i, Object val){ | |
587 node = ensureEditable(node); | |
588 Node ret = node; | |
589 if(level == 0) | |
590 { | |
591 ret.array[i & 0x01f] = val; | |
592 } | |
593 else | |
594 { | |
595 int subidx = (i >>> level) & 0x01f; | |
596 ret.array[subidx] = doAssoc(level - 5, (Node) node.array[subidx], i, val); | |
597 } | |
598 return ret; | |
599 } | |
600 | |
601 public TransientVector pop(){ | |
602 ensureEditable(); | |
603 if(cnt == 0) | |
604 throw new IllegalStateException("Can't pop empty vector"); | |
605 if(cnt == 1) | |
606 { | |
607 cnt = 0; | |
608 return this; | |
609 } | |
610 int i = cnt - 1; | |
611 //pop in tail? | |
612 if((i & 0x01f) > 0) | |
613 { | |
614 --cnt; | |
615 return this; | |
616 } | |
617 | |
618 Object[] newtail = arrayFor(cnt - 2); | |
619 | |
620 Node newroot = popTail(shift, root); | |
621 int newshift = shift; | |
622 if(newroot == null) | |
623 { | |
624 newroot = new Node(root.edit); | |
625 } | |
626 if(shift > 5 && newroot.array[1] == null) | |
627 { | |
628 newroot = ensureEditable((Node) newroot.array[0]); | |
629 newshift -= 5; | |
630 } | |
631 root = newroot; | |
632 shift = newshift; | |
633 --cnt; | |
634 tail = newtail; | |
635 return this; | |
636 } | |
637 | |
638 private Node popTail(int level, Node node){ | |
639 node = ensureEditable(node); | |
640 int subidx = ((cnt - 2) >>> level) & 0x01f; | |
641 if(level > 5) | |
642 { | |
643 Node newchild = popTail(level - 5, (Node) node.array[subidx]); | |
644 if(newchild == null && subidx == 0) | |
645 return null; | |
646 else | |
647 { | |
648 Node ret = node; | |
649 ret.array[subidx] = newchild; | |
650 return ret; | |
651 } | |
652 } | |
653 else if(subidx == 0) | |
654 return null; | |
655 else | |
656 { | |
657 Node ret = node; | |
658 ret.array[subidx] = null; | |
659 return ret; | |
660 } | |
661 } | |
662 } | |
663 /* | |
664 static public void main(String[] args){ | |
665 if(args.length != 3) | |
666 { | |
667 System.err.println("Usage: PersistentVector size writes reads"); | |
668 return; | |
669 } | |
670 int size = Integer.parseInt(args[0]); | |
671 int writes = Integer.parseInt(args[1]); | |
672 int reads = Integer.parseInt(args[2]); | |
673 // Vector v = new Vector(size); | |
674 ArrayList v = new ArrayList(size); | |
675 // v.setSize(size); | |
676 //PersistentArray p = new PersistentArray(size); | |
677 PersistentVector p = PersistentVector.EMPTY; | |
678 // MutableVector mp = p.mutable(); | |
679 | |
680 for(int i = 0; i < size; i++) | |
681 { | |
682 v.add(i); | |
683 // v.set(i, i); | |
684 //p = p.set(i, 0); | |
685 p = p.cons(i); | |
686 // mp = mp.conj(i); | |
687 } | |
688 | |
689 Random rand; | |
690 | |
691 rand = new Random(42); | |
692 long tv = 0; | |
693 System.out.println("ArrayList"); | |
694 long startTime = System.nanoTime(); | |
695 for(int i = 0; i < writes; i++) | |
696 { | |
697 v.set(rand.nextInt(size), i); | |
698 } | |
699 for(int i = 0; i < reads; i++) | |
700 { | |
701 tv += (Integer) v.get(rand.nextInt(size)); | |
702 } | |
703 long estimatedTime = System.nanoTime() - startTime; | |
704 System.out.println("time: " + estimatedTime / 1000000); | |
705 System.out.println("PersistentVector"); | |
706 rand = new Random(42); | |
707 startTime = System.nanoTime(); | |
708 long tp = 0; | |
709 | |
710 // PersistentVector oldp = p; | |
711 //Random rand2 = new Random(42); | |
712 | |
713 MutableVector mp = p.mutable(); | |
714 for(int i = 0; i < writes; i++) | |
715 { | |
716 // p = p.assocN(rand.nextInt(size), i); | |
717 mp = mp.assocN(rand.nextInt(size), i); | |
718 // mp = mp.assoc(rand.nextInt(size), i); | |
719 //dummy set to force perverse branching | |
720 //oldp = oldp.assocN(rand2.nextInt(size), i); | |
721 } | |
722 for(int i = 0; i < reads; i++) | |
723 { | |
724 // tp += (Integer) p.nth(rand.nextInt(size)); | |
725 tp += (Integer) mp.nth(rand.nextInt(size)); | |
726 } | |
727 // p = mp.immutable(); | |
728 //mp.cons(42); | |
729 estimatedTime = System.nanoTime() - startTime; | |
730 System.out.println("time: " + estimatedTime / 1000000); | |
731 for(int i = 0; i < size / 2; i++) | |
732 { | |
733 mp = mp.pop(); | |
734 // p = p.pop(); | |
735 v.remove(v.size() - 1); | |
736 } | |
737 p = (PersistentVector) mp.immutable(); | |
738 //mp.pop(); //should fail | |
739 for(int i = 0; i < size / 2; i++) | |
740 { | |
741 tp += (Integer) p.nth(i); | |
742 tv += (Integer) v.get(i); | |
743 } | |
744 System.out.println("Done: " + tv + ", " + tp); | |
745 | |
746 } | |
747 // */ | |
748 } |