Skip to content

Commit f457244

Browse files
author
Glen K. Peterson
committed
These are UNTESTED changes, saved so I can switch branches.
1 parent 3fbe89c commit f457244

File tree

3 files changed

+127
-23
lines changed

3 files changed

+127
-23
lines changed

CodeStylePaguro.xml

+13
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,21 @@
11
<code_scheme name="CodeStylePaguro">
2+
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
3+
<option name="IMPORT_LAYOUT_TABLE">
4+
<value>
5+
<emptyLine />
6+
<package name="java" withSubpackages="true" static="false" />
7+
<package name="javax" withSubpackages="true" static="false" />
8+
<emptyLine />
9+
<package name="" withSubpackages="true" static="false" />
10+
<emptyLine />
11+
<package name="" withSubpackages="true" static="true" />
12+
</value>
13+
</option>
214
<option name="RIGHT_MARGIN" value="100" />
315
<option name="JD_DO_NOT_WRAP_ONE_LINE_COMMENTS" value="true" />
416
<option name="JD_LEADING_ASTERISKS_ARE_ENABLED" value="false" />
517
<JavaCodeStyleSettings>
18+
<option name="DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION" value="true" />
619
<option name="ALIGN_MULTILINE_ANNOTATION_PARAMETERS" value="true" />
720
</JavaCodeStyleSettings>
821
<MarkdownNavigatorCodeStyleSettings>

src/main/java/org/organicdesign/fp/experimental/RrbTree1.java

+114-22
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,15 @@
1515

1616
import java.lang.reflect.Array;
1717
import java.util.Arrays;
18+
import java.util.Iterator;
1819
import java.util.List;
20+
import java.util.Stack;
1921

2022
import org.organicdesign.fp.collections.ImList;
2123
import org.organicdesign.fp.collections.MutableList;
2224
import org.organicdesign.fp.collections.UnmodIterable;
2325
import org.organicdesign.fp.collections.UnmodSortedIterable;
26+
import org.organicdesign.fp.collections.UnmodSortedIterator;
2427
import org.organicdesign.fp.tuple.Tuple2;
2528
import org.organicdesign.fp.tuple.Tuple4;
2629

@@ -336,7 +339,26 @@ private RrbTree1(E[] f, int fi, Node<E> r, int s) {
336339
focus = f; focusStartIndex = fi; root = r; size = s;
337340
}
338341

339-
@Override public int size() { return size; }
342+
/**
343+
Adds an item at the end of this structure. This is the most efficient way to build an
344+
RRB Tree as it conforms to the Clojure PersistentVector and all of its optimizations.
345+
@param t the item to append
346+
@return a new RRB-Tree with the item appended.
347+
*/
348+
@Override public RrbTree1<E> append(E t) {
349+
// System.out.println("=== append(" + t + ") ===");
350+
// If our focus isn't set up for appends or if it's full, insert it into the data structure
351+
// where it belongs. Then make a new focus
352+
if (((focusStartIndex < root.size()) && (focus.length > 0) ) ||
353+
(focus.length >= STRICT_NODE_LENGTH) ) {
354+
Node<E> newRoot = root.pushFocus(focusStartIndex, focus);
355+
E[] newFocus = singleElementArray(t);
356+
return new RrbTree1<>(newFocus, size, newRoot, size + 1);
357+
}
358+
359+
E[] newFocus = insertIntoArrayAt(t, focus, focus.length);
360+
return new RrbTree1<>(newFocus, focusStartIndex, root, size + 1);
361+
}
340362

341363
@SuppressWarnings("unchecked")
342364
@Override public boolean equals(Object other) {
@@ -385,27 +407,6 @@ private RrbTree1(E[] f, int fi, Node<E> r, int s) {
385407
return root.get(i);
386408
}
387409

388-
/**
389-
Adds an item at the end of this structure. This is the most efficient way to build an
390-
RRB Tree as it conforms to the Clojure PersistentVector and all of its optimizations.
391-
@param t the item to append
392-
@return a new RRB-Tree with the item appended.
393-
*/
394-
@Override public RrbTree1<E> append(E t) {
395-
// System.out.println("=== append(" + t + ") ===");
396-
// If our focus isn't set up for appends or if it's full, insert it into the data structure
397-
// where it belongs. Then make a new focus
398-
if (((focusStartIndex < root.size()) && (focus.length > 0) ) ||
399-
(focus.length >= STRICT_NODE_LENGTH) ) {
400-
Node<E> newRoot = root.pushFocus(focusStartIndex, focus);
401-
E[] newFocus = singleElementArray(t);
402-
return new RrbTree1<>(newFocus, size, newRoot, size + 1);
403-
}
404-
405-
E[] newFocus = insertIntoArrayAt(t, focus, focus.length);
406-
return new RrbTree1<>(newFocus, focusStartIndex, root, size + 1);
407-
}
408-
409410
@Override public RrbTree1<E> immutable() { return this; }
410411

411412
/**
@@ -445,6 +446,76 @@ public RrbTree1<E> insert(int idx, E element) {
445446
return new RrbTree1<>(newFocus, idx, newRoot, size + 1);
446447
}
447448

449+
private final class IdxNode {
450+
int idx = 0;
451+
final Node<E> node;
452+
IdxNode(Node<E> n) { node = n; }
453+
}
454+
455+
private final class Iter implements UnmodSortedIterator<E> {
456+
// We want this iterator to walk the tree. You MUST
457+
private int childIndex = 0;
458+
private final Stack<IdxNode> stack = new Stack<>();
459+
private Node<E> n;
460+
private Iter() {
461+
// TODO: Handle case where focus and/or root are null.
462+
// Push the focus so we don't have to ever check the index.
463+
Node<E> n = ((focus != null) && focus.length > 0) ? root.pushFocus(focusStartIndex, focus)
464+
: root;
465+
if (n instanceof Leaf) {
466+
stack.add(new IdxNode(n));
467+
} else {
468+
// Descent to left-most bottom node.
469+
while (!(n instanceof Leaf)) {
470+
stack.add(new IdxNode(n));
471+
n = n.firstChild();
472+
}
473+
}
474+
}
475+
476+
@Override public boolean hasNext() { return stack.peek() != null; }
477+
478+
@Override public E next() {
479+
E ret = n.get(childIndex);
480+
childIndex = childIndex + 1;
481+
482+
// Leaf node has been exhausted, find a new one.
483+
if (childIndex >= n.size()) {
484+
// Start the next leaf node at zero.
485+
childIndex = 0;
486+
487+
// Get the immediate parent and increment it's child pointer.
488+
IdxNode parent = stack.peek();
489+
parent.idx = parent.idx + 1;
490+
491+
// Keep walking up the ancestors until one hasn't been exhausted (or we're done).
492+
while (parent.idx >= parent.node.size()) {
493+
stack.pop();
494+
parent = stack.peek();
495+
if (parent == null) {
496+
return ret; // This is the end of the tree - all done!
497+
}
498+
parent.idx = parent.idx + 1;
499+
}
500+
// TODO: We want the node at the index stored with the parent in the IdxNode.
501+
// Now, walk down to the first child.
502+
n = parent.node;
503+
while ( true ) {
504+
n = n.firstChild();
505+
if (n instanceof Leaf) {
506+
break;
507+
}
508+
stack.add(new IdxNode(n));
509+
}
510+
}
511+
return ret;
512+
}
513+
}
514+
515+
@Override public UnmodSortedIterator<E> iterator() {
516+
return new Iter();
517+
}
518+
448519
@Override public MutableList<E> mutable() {
449520
// TODO: Implement or change interfaces.
450521
throw new UnsupportedOperationException("No mutable version (yet)");
@@ -478,6 +549,8 @@ public RrbTree1<E> replace(int index, E item) {
478549
return new RrbTree1<>(focus, focusStartIndex, root.replace(index, item), size);
479550
}
480551

552+
@Override public int size() { return size; }
553+
481554
/**
482555
Divides this RRB-Tree such that every index less-than the given index ends up in the left-hand tree
483556
and the indexed item and all subsequent ones end up in the right-hand tree.
@@ -547,12 +620,16 @@ private interface Node<T> extends Indented {
547620
// So this needs to only be implemented on Relaxed for now.
548621
// Relaxed<T>[] split();
549622

623+
int numChildren();
624+
550625
// Because we want to append/insert into the focus as much as possible, we will treat
551626
// the insert or append of a single item as a degenerate case. Instead, the primary way
552627
// to add to the internal data structure will be to push the entire focus array into it
553628
Node<T> pushFocus(int index, T[] oldFocus);
554629

555630
Node<T> replace(int idx, T t);
631+
632+
Node<T> firstChild();
556633
}
557634

558635
private static class SplitNode<T> extends Tuple4<Node<T>,T[],Node<T>,T[]> implements Indented {
@@ -584,6 +661,11 @@ private static class Leaf<T> implements Node<T> {
584661
// are strict.
585662
// boolean isStrict;
586663
Leaf(T[] ts) { items = ts; }
664+
665+
@Override public Node<T> firstChild() {
666+
throw new UnsupportedOperationException("Don't call this on a leaf");
667+
}
668+
587669
@Override public T get(int i) { return items[i]; }
588670
@Override public int size() { return items.length; }
589671
// If we want to add one more to an existing leaf node, it must already be part of a
@@ -636,6 +718,8 @@ private Leaf<T>[] spliceAndSplit(T[] oldFocus, int splitIndex) {
636718
return new Leaf[] {new Leaf<>(split._1()), new Leaf<>(split._2())};
637719
}
638720

721+
@Override public int numChildren() { return size(); }
722+
639723
// I think this can only be called when the root node is a leaf.
640724
@SuppressWarnings("unchecked")
641725
@Override public Node<T> pushFocus(int index, T[] oldFocus) {
@@ -713,6 +797,8 @@ private static class Strict<T> implements Node<T> {
713797
// System.out.println(" new Strict" + shift + arrayString(ns));
714798
}
715799

800+
@Override public Node<T> firstChild() { return nodes[0]; }
801+
716802
/**
717803
Returns the high bits which we use to index into our array. This is the simplicity (and
718804
speed) of Strict indexing. When everything works, this can be inlined for performance.
@@ -904,6 +990,8 @@ Relaxed<T> relax() {
904990
return new Relaxed<>(newCumSizes, nodes);
905991
}
906992

993+
@Override public int numChildren() { return nodes.length; }
994+
907995
@SuppressWarnings("unchecked")
908996
@Override
909997
public Node<T> pushFocus(int index, T[] oldFocus) {
@@ -1129,6 +1217,8 @@ public static <T> Node<T> fixRight(Node<T>[] origNodes, Node<T> splitRight, int
11291217
}
11301218
}
11311219

1220+
@Override public Node<T> firstChild() { return nodes[0]; }
1221+
11321222
@Override public int size() {
11331223
return cumulativeSizes[cumulativeSizes.length - 1];
11341224
}
@@ -1396,6 +1486,8 @@ public SplitNode<T> splitAt(int splitIndex) {
13961486
return ret;
13971487
}
13981488

1489+
@Override public int numChildren() { return nodes.length; }
1490+
13991491
@SuppressWarnings("unchecked")
14001492
@Override public Node<T> pushFocus(int index, T[] oldFocus) {
14011493
// TODO: Review this entire method.

src/test/java/org/organicdesign/fp/experimental/RrbTree1Test.java

-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import org.junit.Test;
2424
import org.organicdesign.fp.TestUtilities;
2525
import org.organicdesign.fp.collections.ImList;
26-
import org.organicdesign.fp.collections.UnmodListTest;
2726
import org.organicdesign.fp.tuple.Tuple2;
2827

2928
import static org.junit.Assert.assertArrayEquals;

0 commit comments

Comments
 (0)