Skip to content

Commit

Permalink
Added iterator() method.
Browse files Browse the repository at this point in the history
  • Loading branch information
tzaeschke committed Jul 28, 2014
1 parent 49a0ccb commit 42a1a5a
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 0 deletions.
143 changes: 143 additions & 0 deletions CritBit/src/org/zoodb/index/critbit/CritBit.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@
* T.Zaeschke, C.Zimmerli, M.C.Norrie: The PH-Tree - A Space-Efficient Storage Structure and
* Multi-Dimensional Index (SIGMOD 2014)
*
*
* Version: 1.2
* -- Added iterator() to iterate over all entries
*
* Version: 1.1
* -- Slight performance improvements in mergeLong() and readAndSplit()
*
Expand Down Expand Up @@ -695,6 +699,145 @@ private void updateParentAfterRemove(Node<V> parent, long[] newPost, V newVal,
size--;
}

/**
* Create an iterator over all values, keys or entries.
* @return the iterator
*/
public FullIterator<V> iterator() {
checkDim0();
return new FullIterator<V>(this, DEPTH);
}

public static class FullIterator<V> implements Iterator<V> {
private final long[] valIntTemplate;
private long[] nextKey = null;
private V nextValue = null;
private final Node<V>[] stack;
//0==read_lower; 1==read_upper; 2==go_to_parent
private static final byte READ_LOWER = 0;
private static final byte READ_UPPER = 1;
private static final byte RETURN_TO_PARENT = 2;
private final byte[] readHigherNext;
private int stackTop = -1;

@SuppressWarnings("unchecked")
public FullIterator(CritBit<V> cb, int DEPTH) {
this.stack = new Node[DEPTH];
this.readHigherNext = new byte[DEPTH]; // default = false
int intArrayLen = (DEPTH+63) >>> 6;
this.valIntTemplate = new long[intArrayLen];

if (cb.rootKey != null) {
readNextVal(cb.rootKey, cb.rootVal);
return;
}
if (cb.root == null) {
//Tree is empty
return;
}
Node<V> n = cb.root;
CritBit.readInfix(n, valIntTemplate);
stack[++stackTop] = cb.root;
findNext();
}

private void findNext() {
while (stackTop >= 0) {
Node<V> n = stack[stackTop];
//check lower
if (readHigherNext[stackTop] == READ_LOWER) {
readHigherNext[stackTop] = READ_UPPER;
//TODO use bit directly to check validity
BitTools.setBit(valIntTemplate, n.posDiff, false);
if (n.loPost != null) {
CritBit.readPostFix(n.loPost, valIntTemplate);
readNextVal(valIntTemplate, n.loVal);
return;
//proceed to check upper
} else {
CritBit.readInfix(n.lo, valIntTemplate);
stack[++stackTop] = n.lo;
readHigherNext[stackTop] = READ_LOWER;
continue;
}
}
//check upper
if (readHigherNext[stackTop] == READ_UPPER) {
readHigherNext[stackTop] = RETURN_TO_PARENT;
BitTools.setBit(valIntTemplate, n.posDiff, true);
if (n.hiPost != null) {
CritBit.readPostFix(n.hiPost, valIntTemplate);
readNextVal(valIntTemplate, n.hiVal);
--stackTop;
return;
//proceed to move up a level
} else {
CritBit.readInfix(n.hi, valIntTemplate);
stack[++stackTop] = n.hi;
readHigherNext[stackTop] = READ_LOWER;
continue;
}
}
//proceed to move up a level
--stackTop;
}
//Finished
nextValue = null;
nextKey = null;
}


/**
* Full comparison on the parameter. Assigns the parameter to 'nextVal' if comparison
* fits.
* @param keyTemplate
* @return Whether we have a match or not
*/
private void readNextVal(long[] keyTemplate, V value) {
nextValue = value;
nextKey = CritBit.clone(keyTemplate);
}

@Override
public boolean hasNext() {
return nextValue != null;
}

@Override
public V next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
V ret = nextValue;
findNext();
return ret;
}

public long[] nextKey() {
if (!hasNext()) {
throw new NoSuchElementException();
}
long[] ret = nextKey;
findNext();
return ret;
}

public Entry<V> nextEntry() {
if (!hasNext()) {
throw new NoSuchElementException();
}
Entry<V> ret = new Entry<V>(nextKey, nextValue);
findNext();
return ret;
}

@Override
public void remove() {
throw new UnsupportedOperationException();
}

}

public QueryIterator<V> query(long[] min, long[] max) {
checkDim0();
return new QueryIterator<V>(this, min, max, DEPTH);
Expand Down
3 changes: 3 additions & 0 deletions CritBit/src/org/zoodb/index/critbit/CritBit1D.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*/
package org.zoodb.index.critbit;

import org.zoodb.index.critbit.CritBit.FullIterator;
import org.zoodb.index.critbit.CritBit.QueryIterator;

/**
Expand Down Expand Up @@ -49,4 +50,6 @@ public interface CritBit1D<V> {
/** @see CritBit#get(long[]) */
V get(long[] key);

/** @see CritBit#iterator() */
FullIterator<V> iterator();
}
29 changes: 29 additions & 0 deletions CritBit/src/org/zoodb/index/critbit/TestCritBit.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

import org.junit.Test;
import org.zoodb.index.critbit.CritBit.Entry;
import org.zoodb.index.critbit.CritBit.FullIterator;
import org.zoodb.index.critbit.CritBit.QueryIterator;

/**
Expand Down Expand Up @@ -840,6 +841,34 @@ public void test64_True1D_queries_Single() {
assertFalse(it.hasNext());
}

@Test
public void testIterator() {
int N = 10000;
int k = 5;
Random R = new Random(0);

CritBit1D<Integer> cb = newCritBit(k*64);
long[][] data = new long[N][];
for (int i = 0; i < N; i++) {
long[] l = new long[k];
for (int d = 0; d < k; d++) {
l[d] = R.nextInt(12345);
}
data[i] = l;
cb.put(l, i);
}

//test
FullIterator<Integer> it = cb.iterator();
int n = 0;
while (it.hasNext()) {
Entry<Integer> e = it.nextEntry();
assertTrue(isEqual(data[e.value()], e.key()));
n++;
}
assertEquals(N, n);
}

private boolean isEqual(long[] a, long[] r) {
for (int k = 0; k < a.length; k++) {
if (a[k] != r[k]) {
Expand Down

0 comments on commit 42a1a5a

Please sign in to comment.