8016251: Balanced spliterator for SpinedBuffer
Co-authored-by: Brian Goetz <brian.goetz@oracle.com> Co-authored-by: Peter Levart <peter.levart@gmail.com> Reviewed-by: mduigou
This commit is contained in:
parent
cd61a1e1a5
commit
aed188663e
@ -461,7 +461,7 @@ abstract class DoublePipeline<E_IN>
|
||||
@Override
|
||||
public final double[] toArray() {
|
||||
return Nodes.flattenDouble((Node.OfDouble) evaluateToArrayNode(Double[]::new))
|
||||
.asDoubleArray();
|
||||
.asPrimitiveArray();
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -498,7 +498,7 @@ abstract class IntPipeline<E_IN>
|
||||
@Override
|
||||
public final int[] toArray() {
|
||||
return Nodes.flattenInt((Node.OfInt) evaluateToArrayNode(Integer[]::new))
|
||||
.asIntArray();
|
||||
.asPrimitiveArray();
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -479,7 +479,8 @@ abstract class LongPipeline<E_IN>
|
||||
|
||||
@Override
|
||||
public final long[] toArray() {
|
||||
return Nodes.flattenLong((Node.OfLong) evaluateToArrayNode(Long[]::new)).asLongArray();
|
||||
return Nodes.flattenLong((Node.OfLong) evaluateToArrayNode(Long[]::new))
|
||||
.asPrimitiveArray();
|
||||
}
|
||||
|
||||
|
||||
|
@ -242,7 +242,7 @@ interface Node<T> {
|
||||
* an instance of an Integer[] array with a length of {@link #count()}
|
||||
* and then invokes {@link #copyInto(Integer[], int)} with that
|
||||
* Integer[] array at an offset of 0. This is not efficient and it is
|
||||
* recommended to invoke {@link #asIntArray()}.
|
||||
* recommended to invoke {@link #asPrimitiveArray()}.
|
||||
*/
|
||||
@Override
|
||||
default Integer[] asArray(IntFunction<Integer[]> generator) {
|
||||
@ -254,7 +254,7 @@ interface Node<T> {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @implSpec the default implementation invokes {@link #asIntArray()} to
|
||||
* @implSpec the default implementation invokes {@link #asPrimitiveArray()} to
|
||||
* obtain an int[] array then and copies the elements from that int[]
|
||||
* array into the boxed Integer[] array. This is not efficient and it
|
||||
* is recommended to invoke {@link #copyInto(int[], int)}.
|
||||
@ -264,7 +264,7 @@ interface Node<T> {
|
||||
if (Tripwire.ENABLED)
|
||||
Tripwire.trip(getClass(), "{0} calling Node.OfInt.copyInto(Integer[], int)");
|
||||
|
||||
int[] array = asIntArray();
|
||||
int[] array = asPrimitiveArray();
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
boxed[offset + i] = array[i];
|
||||
}
|
||||
@ -285,7 +285,7 @@ interface Node<T> {
|
||||
*
|
||||
* @return an array containing the contents of this {@code Node}
|
||||
*/
|
||||
int[] asIntArray();
|
||||
int[] asPrimitiveArray();
|
||||
|
||||
/**
|
||||
* Copies the content of this {@code Node} into an int[] array, starting
|
||||
@ -362,7 +362,7 @@ interface Node<T> {
|
||||
* an instance of a Long[] array with a length of {@link #count()} and
|
||||
* then invokes {@link #copyInto(Long[], int)} with that Long[] array at
|
||||
* an offset of 0. This is not efficient and it is recommended to
|
||||
* invoke {@link #asLongArray()}.
|
||||
* invoke {@link #asPrimitiveArray()}.
|
||||
*/
|
||||
@Override
|
||||
default Long[] asArray(IntFunction<Long[]> generator) {
|
||||
@ -374,7 +374,7 @@ interface Node<T> {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @implSpec the default implementation invokes {@link #asLongArray()}
|
||||
* @implSpec the default implementation invokes {@link #asPrimitiveArray()}
|
||||
* to obtain a long[] array then and copies the elements from that
|
||||
* long[] array into the boxed Long[] array. This is not efficient and
|
||||
* it is recommended to invoke {@link #copyInto(long[], int)}.
|
||||
@ -384,7 +384,7 @@ interface Node<T> {
|
||||
if (Tripwire.ENABLED)
|
||||
Tripwire.trip(getClass(), "{0} calling Node.OfInt.copyInto(Long[], int)");
|
||||
|
||||
long[] array = asLongArray();
|
||||
long[] array = asPrimitiveArray();
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
boxed[offset + i] = array[i];
|
||||
}
|
||||
@ -405,7 +405,7 @@ interface Node<T> {
|
||||
*
|
||||
* @return an array containing the contents of this {@code Node}
|
||||
*/
|
||||
long[] asLongArray();
|
||||
long[] asPrimitiveArray();
|
||||
|
||||
/**
|
||||
* Copies the content of this {@code Node} into a long[] array, starting
|
||||
@ -485,7 +485,7 @@ interface Node<T> {
|
||||
* an instance of a Double[] array with a length of {@link #count()} and
|
||||
* then invokes {@link #copyInto(Double[], int)} with that Double[]
|
||||
* array at an offset of 0. This is not efficient and it is recommended
|
||||
* to invoke {@link #asDoubleArray()}.
|
||||
* to invoke {@link #asPrimitiveArray()}.
|
||||
*/
|
||||
@Override
|
||||
default Double[] asArray(IntFunction<Double[]> generator) {
|
||||
@ -497,7 +497,7 @@ interface Node<T> {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @implSpec the default implementation invokes {@link #asDoubleArray()}
|
||||
* @implSpec the default implementation invokes {@link #asPrimitiveArray()}
|
||||
* to obtain a double[] array then and copies the elements from that
|
||||
* double[] array into the boxed Double[] array. This is not efficient
|
||||
* and it is recommended to invoke {@link #copyInto(double[], int)}.
|
||||
@ -507,7 +507,7 @@ interface Node<T> {
|
||||
if (Tripwire.ENABLED)
|
||||
Tripwire.trip(getClass(), "{0} calling Node.OfDouble.copyInto(Double[], int)");
|
||||
|
||||
double[] array = asDoubleArray();
|
||||
double[] array = asPrimitiveArray();
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
boxed[offset + i] = array[i];
|
||||
}
|
||||
@ -528,7 +528,7 @@ interface Node<T> {
|
||||
*
|
||||
* @return an array containing the contents of this {@code Node}
|
||||
*/
|
||||
double[] asDoubleArray();
|
||||
double[] asPrimitiveArray();
|
||||
|
||||
/**
|
||||
* Copies the content of this {@code Node} into a double[] array, starting
|
||||
|
@ -679,7 +679,7 @@ final class Nodes {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] asIntArray() {
|
||||
public int[] asPrimitiveArray() {
|
||||
return EMPTY_INT_ARRAY;
|
||||
}
|
||||
}
|
||||
@ -696,7 +696,7 @@ final class Nodes {
|
||||
}
|
||||
|
||||
@Override
|
||||
public long[] asLongArray() {
|
||||
public long[] asPrimitiveArray() {
|
||||
return EMPTY_LONG_ARRAY;
|
||||
}
|
||||
}
|
||||
@ -713,7 +713,7 @@ final class Nodes {
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] asDoubleArray() {
|
||||
public double[] asPrimitiveArray() {
|
||||
return EMPTY_DOUBLE_ARRAY;
|
||||
}
|
||||
}
|
||||
@ -1395,7 +1395,7 @@ final class Nodes {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] asIntArray() {
|
||||
public int[] asPrimitiveArray() {
|
||||
if (array.length == curSize) {
|
||||
return array;
|
||||
} else {
|
||||
@ -1449,7 +1449,7 @@ final class Nodes {
|
||||
}
|
||||
|
||||
@Override
|
||||
public long[] asLongArray() {
|
||||
public long[] asPrimitiveArray() {
|
||||
if (array.length == curSize) {
|
||||
return array;
|
||||
} else {
|
||||
@ -1503,7 +1503,7 @@ final class Nodes {
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] asDoubleArray() {
|
||||
public double[] asPrimitiveArray() {
|
||||
if (array.length == curSize) {
|
||||
return array;
|
||||
} else {
|
||||
@ -1561,7 +1561,7 @@ final class Nodes {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] asIntArray() {
|
||||
public int[] asPrimitiveArray() {
|
||||
int[] array = new int[(int) count()];
|
||||
copyInto(array, 0);
|
||||
return array;
|
||||
@ -1594,7 +1594,7 @@ final class Nodes {
|
||||
}
|
||||
|
||||
@Override
|
||||
public long[] asLongArray() {
|
||||
public long[] asPrimitiveArray() {
|
||||
long[] array = new long[(int) count()];
|
||||
copyInto(array, 0);
|
||||
return array;
|
||||
@ -1627,7 +1627,7 @@ final class Nodes {
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] asDoubleArray() {
|
||||
public double[] asPrimitiveArray() {
|
||||
double[] array = new double[(int) count()];
|
||||
copyInto(array, 0);
|
||||
return array;
|
||||
@ -1844,9 +1844,9 @@ final class Nodes {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] asIntArray() {
|
||||
public int[] asPrimitiveArray() {
|
||||
assert !building : "during building";
|
||||
return super.asIntArray();
|
||||
return super.asPrimitiveArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1904,9 +1904,9 @@ final class Nodes {
|
||||
}
|
||||
|
||||
@Override
|
||||
public long[] asLongArray() {
|
||||
public long[] asPrimitiveArray() {
|
||||
assert !building : "during building";
|
||||
return super.asLongArray();
|
||||
return super.asPrimitiveArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1964,9 +1964,9 @@ final class Nodes {
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] asDoubleArray() {
|
||||
public double[] asPrimitiveArray() {
|
||||
assert !building : "during building";
|
||||
return super.asDoubleArray();
|
||||
return super.asPrimitiveArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -192,7 +192,7 @@ final class SortedOps {
|
||||
else {
|
||||
Node.OfInt n = (Node.OfInt) helper.evaluate(spliterator, true, generator);
|
||||
|
||||
int[] content = n.asIntArray();
|
||||
int[] content = n.asPrimitiveArray();
|
||||
Arrays.parallelSort(content);
|
||||
|
||||
return Nodes.node(content);
|
||||
@ -231,7 +231,7 @@ final class SortedOps {
|
||||
else {
|
||||
Node.OfLong n = (Node.OfLong) helper.evaluate(spliterator, true, generator);
|
||||
|
||||
long[] content = n.asLongArray();
|
||||
long[] content = n.asPrimitiveArray();
|
||||
Arrays.parallelSort(content);
|
||||
|
||||
return Nodes.node(content);
|
||||
@ -270,7 +270,7 @@ final class SortedOps {
|
||||
else {
|
||||
Node.OfDouble n = (Node.OfDouble) helper.evaluate(spliterator, true, generator);
|
||||
|
||||
double[] content = n.asDoubleArray();
|
||||
double[] content = n.asPrimitiveArray();
|
||||
Arrays.parallelSort(content);
|
||||
|
||||
return Nodes.node(content);
|
||||
@ -401,7 +401,7 @@ final class SortedOps {
|
||||
|
||||
@Override
|
||||
public void end() {
|
||||
int[] ints = b.asIntArray();
|
||||
int[] ints = b.asPrimitiveArray();
|
||||
Arrays.sort(ints);
|
||||
downstream.begin(ints.length);
|
||||
for (int anInt : ints)
|
||||
@ -466,7 +466,7 @@ final class SortedOps {
|
||||
|
||||
@Override
|
||||
public void end() {
|
||||
long[] longs = b.asLongArray();
|
||||
long[] longs = b.asPrimitiveArray();
|
||||
Arrays.sort(longs);
|
||||
downstream.begin(longs.length);
|
||||
for (long aLong : longs)
|
||||
@ -531,7 +531,7 @@ final class SortedOps {
|
||||
|
||||
@Override
|
||||
public void end() {
|
||||
double[] doubles = b.asDoubleArray();
|
||||
double[] doubles = b.asPrimitiveArray();
|
||||
Arrays.sort(doubles);
|
||||
downstream.begin(doubles.length);
|
||||
for (double aDouble : doubles)
|
||||
|
@ -269,25 +269,45 @@ class SpinedBuffer<E>
|
||||
* Return a {@link Spliterator} describing the contents of the buffer.
|
||||
*/
|
||||
public Spliterator<E> spliterator() {
|
||||
return new Spliterator<E>() {
|
||||
class Splitr implements Spliterator<E> {
|
||||
// The current spine index
|
||||
int splSpineIndex;
|
||||
|
||||
// Last spine index
|
||||
final int lastSpineIndex;
|
||||
|
||||
// The current element index into the current spine
|
||||
int splElementIndex;
|
||||
|
||||
// When splSpineIndex >= spineIndex and splElementIndex >= elementIndex then
|
||||
// Last spine's last element index + 1
|
||||
final int lastSpineElementFence;
|
||||
|
||||
// When splSpineIndex >= lastSpineIndex and
|
||||
// splElementIndex >= lastSpineElementFence then
|
||||
// this spliterator is fully traversed
|
||||
// tryAdvance can set splSpineIndex > spineIndex if the last spine is full
|
||||
|
||||
// The current spine array
|
||||
E[] splChunk = (spine == null) ? curChunk : spine[0];
|
||||
E[] splChunk;
|
||||
|
||||
Splitr(int firstSpineIndex, int lastSpineIndex,
|
||||
int firstSpineElementIndex, int lastSpineElementFence) {
|
||||
this.splSpineIndex = firstSpineIndex;
|
||||
this.lastSpineIndex = lastSpineIndex;
|
||||
this.splElementIndex = firstSpineElementIndex;
|
||||
this.lastSpineElementFence = lastSpineElementFence;
|
||||
assert spine != null || firstSpineIndex == 0 && lastSpineIndex == 0;
|
||||
splChunk = (spine == null) ? curChunk : spine[firstSpineIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
public long estimateSize() {
|
||||
return (spine == null)
|
||||
? (elementIndex - splElementIndex)
|
||||
: count() - (priorElementCount[splSpineIndex] + splElementIndex);
|
||||
return (splSpineIndex == lastSpineIndex)
|
||||
? (long) lastSpineElementFence - splElementIndex
|
||||
: // # of elements prior to end -
|
||||
priorElementCount[lastSpineIndex] + lastSpineElementFence -
|
||||
// # of elements prior to current
|
||||
priorElementCount[splSpineIndex] - splElementIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -297,14 +317,14 @@ class SpinedBuffer<E>
|
||||
|
||||
@Override
|
||||
public boolean tryAdvance(Consumer<? super E> consumer) {
|
||||
if (splSpineIndex < spineIndex
|
||||
|| (splSpineIndex == spineIndex && splElementIndex < elementIndex)) {
|
||||
if (splSpineIndex < lastSpineIndex
|
||||
|| (splSpineIndex == lastSpineIndex && splElementIndex < lastSpineElementFence)) {
|
||||
consumer.accept(splChunk[splElementIndex++]);
|
||||
|
||||
if (splElementIndex == splChunk.length) {
|
||||
splElementIndex = 0;
|
||||
++splSpineIndex;
|
||||
if (spine != null && splSpineIndex < spine.length)
|
||||
if (spine != null && splSpineIndex <= lastSpineIndex)
|
||||
splChunk = spine[splSpineIndex];
|
||||
}
|
||||
return true;
|
||||
@ -314,45 +334,47 @@ class SpinedBuffer<E>
|
||||
|
||||
@Override
|
||||
public void forEachRemaining(Consumer<? super E> consumer) {
|
||||
if (splSpineIndex < spineIndex
|
||||
|| (splSpineIndex == spineIndex && splElementIndex < elementIndex)) {
|
||||
if (splSpineIndex < lastSpineIndex
|
||||
|| (splSpineIndex == lastSpineIndex && splElementIndex < lastSpineElementFence)) {
|
||||
int i = splElementIndex;
|
||||
// completed chunks, if any
|
||||
for (int sp = splSpineIndex; sp < spineIndex; sp++) {
|
||||
for (int sp = splSpineIndex; sp < lastSpineIndex; sp++) {
|
||||
E[] chunk = spine[sp];
|
||||
for (; i < chunk.length; i++) {
|
||||
consumer.accept(chunk[i]);
|
||||
}
|
||||
i = 0;
|
||||
}
|
||||
|
||||
// current chunk
|
||||
E[] chunk = curChunk;
|
||||
int hElementIndex = elementIndex;
|
||||
// last (or current uncompleted) chunk
|
||||
E[] chunk = (splSpineIndex == lastSpineIndex) ? splChunk : spine[lastSpineIndex];
|
||||
int hElementIndex = lastSpineElementFence;
|
||||
for (; i < hElementIndex; i++) {
|
||||
consumer.accept(chunk[i]);
|
||||
}
|
||||
|
||||
splSpineIndex = spineIndex;
|
||||
splElementIndex = elementIndex;
|
||||
// mark consumed
|
||||
splSpineIndex = lastSpineIndex;
|
||||
splElementIndex = lastSpineElementFence;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spliterator<E> trySplit() {
|
||||
if (splSpineIndex < spineIndex) {
|
||||
Spliterator<E> ret = Arrays.spliterator(spine[splSpineIndex],
|
||||
splElementIndex, spine[splSpineIndex].length);
|
||||
splChunk = spine[++splSpineIndex];
|
||||
if (splSpineIndex < lastSpineIndex) {
|
||||
// split just before last chunk (if it is full this means 50:50 split)
|
||||
Spliterator<E> ret = new Splitr(splSpineIndex, lastSpineIndex - 1,
|
||||
splElementIndex, spine[lastSpineIndex-1].length);
|
||||
// position to start of last chunk
|
||||
splSpineIndex = lastSpineIndex;
|
||||
splElementIndex = 0;
|
||||
splChunk = spine[splSpineIndex];
|
||||
return ret;
|
||||
}
|
||||
else if (splSpineIndex == spineIndex) {
|
||||
int t = (elementIndex - splElementIndex) / 2;
|
||||
else if (splSpineIndex == lastSpineIndex) {
|
||||
int t = (lastSpineElementFence - splElementIndex) / 2;
|
||||
if (t == 0)
|
||||
return null;
|
||||
else {
|
||||
Spliterator<E> ret = Arrays.spliterator(curChunk, splElementIndex, splElementIndex + t);
|
||||
Spliterator<E> ret = Arrays.spliterator(splChunk, splElementIndex, splElementIndex + t);
|
||||
splElementIndex += t;
|
||||
return ret;
|
||||
}
|
||||
@ -361,7 +383,8 @@ class SpinedBuffer<E>
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
return new Splitr(0, spineIndex, 0, elementIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -436,7 +459,7 @@ class SpinedBuffer<E>
|
||||
protected abstract T_ARR[] newArrayArray(int size);
|
||||
|
||||
/** Create a new array of the proper type and size */
|
||||
protected abstract T_ARR newArray(int size);
|
||||
public abstract T_ARR newArray(int size);
|
||||
|
||||
/** Get the length of an array */
|
||||
protected abstract int arrayLength(T_ARR array);
|
||||
@ -555,30 +578,53 @@ class SpinedBuffer<E>
|
||||
arrayForEach(curChunk, 0, elementIndex, consumer);
|
||||
}
|
||||
|
||||
abstract class BaseSpliterator<T_SPLITER extends Spliterator<E>>
|
||||
implements Spliterator<E> {
|
||||
abstract class BaseSpliterator<T_SPLITR extends Spliterator.OfPrimitive<E, T_CONS, T_SPLITR>>
|
||||
implements Spliterator.OfPrimitive<E, T_CONS, T_SPLITR> {
|
||||
// The current spine index
|
||||
int splSpineIndex;
|
||||
|
||||
// Last spine index
|
||||
final int lastSpineIndex;
|
||||
|
||||
// The current element index into the current spine
|
||||
int splElementIndex;
|
||||
|
||||
// When splSpineIndex >= spineIndex and splElementIndex >= elementIndex then
|
||||
// Last spine's last element index + 1
|
||||
final int lastSpineElementFence;
|
||||
|
||||
// When splSpineIndex >= lastSpineIndex and
|
||||
// splElementIndex >= lastSpineElementFence then
|
||||
// this spliterator is fully traversed
|
||||
// tryAdvance can set splSpineIndex > spineIndex if the last spine is full
|
||||
|
||||
// The current spine array
|
||||
T_ARR splChunk = (spine == null) ? curChunk : spine[0];
|
||||
T_ARR splChunk;
|
||||
|
||||
BaseSpliterator(int firstSpineIndex, int lastSpineIndex,
|
||||
int firstSpineElementIndex, int lastSpineElementFence) {
|
||||
this.splSpineIndex = firstSpineIndex;
|
||||
this.lastSpineIndex = lastSpineIndex;
|
||||
this.splElementIndex = firstSpineElementIndex;
|
||||
this.lastSpineElementFence = lastSpineElementFence;
|
||||
assert spine != null || firstSpineIndex == 0 && lastSpineIndex == 0;
|
||||
splChunk = (spine == null) ? curChunk : spine[firstSpineIndex];
|
||||
}
|
||||
|
||||
abstract T_SPLITR newSpliterator(int firstSpineIndex, int lastSpineIndex,
|
||||
int firstSpineElementIndex, int lastSpineElementFence);
|
||||
|
||||
abstract void arrayForOne(T_ARR array, int index, T_CONS consumer);
|
||||
|
||||
abstract T_SPLITER arraySpliterator(T_ARR array, int offset, int len);
|
||||
abstract T_SPLITR arraySpliterator(T_ARR array, int offset, int len);
|
||||
|
||||
@Override
|
||||
public long estimateSize() {
|
||||
return (spine == null)
|
||||
? (elementIndex - splElementIndex)
|
||||
: count() - (priorElementCount[splSpineIndex] + splElementIndex);
|
||||
return (splSpineIndex == lastSpineIndex)
|
||||
? (long) lastSpineElementFence - splElementIndex
|
||||
: // # of elements prior to end -
|
||||
priorElementCount[lastSpineIndex] + lastSpineElementFence -
|
||||
// # of elements prior to current
|
||||
priorElementCount[splSpineIndex] - splElementIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -586,15 +632,16 @@ class SpinedBuffer<E>
|
||||
return SPLITERATOR_CHARACTERISTICS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryAdvance(T_CONS consumer) {
|
||||
if (splSpineIndex < spineIndex
|
||||
|| (splSpineIndex == spineIndex && splElementIndex < elementIndex)) {
|
||||
if (splSpineIndex < lastSpineIndex
|
||||
|| (splSpineIndex == lastSpineIndex && splElementIndex < lastSpineElementFence)) {
|
||||
arrayForOne(splChunk, splElementIndex++, consumer);
|
||||
|
||||
if (splElementIndex == arrayLength(splChunk)) {
|
||||
splElementIndex = 0;
|
||||
++splSpineIndex;
|
||||
if (spine != null && splSpineIndex < spine.length)
|
||||
if (spine != null && splSpineIndex <= lastSpineIndex)
|
||||
splChunk = spine[splSpineIndex];
|
||||
}
|
||||
return true;
|
||||
@ -602,39 +649,44 @@ class SpinedBuffer<E>
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEachRemaining(T_CONS consumer) {
|
||||
if (splSpineIndex < spineIndex
|
||||
|| (splSpineIndex == spineIndex && splElementIndex < elementIndex)) {
|
||||
if (splSpineIndex < lastSpineIndex
|
||||
|| (splSpineIndex == lastSpineIndex && splElementIndex < lastSpineElementFence)) {
|
||||
int i = splElementIndex;
|
||||
// completed chunks, if any
|
||||
for (int sp = splSpineIndex; sp < spineIndex; sp++) {
|
||||
for (int sp = splSpineIndex; sp < lastSpineIndex; sp++) {
|
||||
T_ARR chunk = spine[sp];
|
||||
arrayForEach(chunk, i, arrayLength(chunk), consumer);
|
||||
i = 0;
|
||||
}
|
||||
|
||||
arrayForEach(curChunk, i, elementIndex, consumer);
|
||||
|
||||
splSpineIndex = spineIndex;
|
||||
splElementIndex = elementIndex;
|
||||
// last (or current uncompleted) chunk
|
||||
T_ARR chunk = (splSpineIndex == lastSpineIndex) ? splChunk : spine[lastSpineIndex];
|
||||
arrayForEach(chunk, i, lastSpineElementFence, consumer);
|
||||
// mark consumed
|
||||
splSpineIndex = lastSpineIndex;
|
||||
splElementIndex = lastSpineElementFence;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public T_SPLITER trySplit() {
|
||||
if (splSpineIndex < spineIndex) {
|
||||
T_SPLITER ret = arraySpliterator(spine[splSpineIndex], splElementIndex,
|
||||
arrayLength(spine[splSpineIndex]) - splElementIndex);
|
||||
splChunk = spine[++splSpineIndex];
|
||||
public T_SPLITR trySplit() {
|
||||
if (splSpineIndex < lastSpineIndex) {
|
||||
// split just before last chunk (if it is full this means 50:50 split)
|
||||
T_SPLITR ret = newSpliterator(splSpineIndex, lastSpineIndex - 1,
|
||||
splElementIndex, arrayLength(spine[lastSpineIndex - 1]));
|
||||
// position us to start of last chunk
|
||||
splSpineIndex = lastSpineIndex;
|
||||
splElementIndex = 0;
|
||||
splChunk = spine[splSpineIndex];
|
||||
return ret;
|
||||
}
|
||||
else if (splSpineIndex == spineIndex) {
|
||||
int t = (elementIndex - splElementIndex) / 2;
|
||||
else if (splSpineIndex == lastSpineIndex) {
|
||||
int t = (lastSpineElementFence - splElementIndex) / 2;
|
||||
if (t == 0)
|
||||
return null;
|
||||
else {
|
||||
T_SPLITER ret = arraySpliterator(curChunk, splElementIndex, t);
|
||||
T_SPLITR ret = arraySpliterator(splChunk, splElementIndex, t);
|
||||
splElementIndex += t;
|
||||
return ret;
|
||||
}
|
||||
@ -675,7 +727,7 @@ class SpinedBuffer<E>
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int[] newArray(int size) {
|
||||
public int[] newArray(int size) {
|
||||
return new int[size];
|
||||
}
|
||||
|
||||
@ -706,10 +758,6 @@ class SpinedBuffer<E>
|
||||
return spine[ch][(int) (index-priorElementCount[ch])];
|
||||
}
|
||||
|
||||
public int[] asIntArray() {
|
||||
return asPrimitiveArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrimitiveIterator.OfInt iterator() {
|
||||
return Spliterators.iterator(spliterator());
|
||||
@ -718,6 +766,18 @@ class SpinedBuffer<E>
|
||||
public Spliterator.OfInt spliterator() {
|
||||
class Splitr extends BaseSpliterator<Spliterator.OfInt>
|
||||
implements Spliterator.OfInt {
|
||||
Splitr(int firstSpineIndex, int lastSpineIndex,
|
||||
int firstSpineElementIndex, int lastSpineElementFence) {
|
||||
super(firstSpineIndex, lastSpineIndex,
|
||||
firstSpineElementIndex, lastSpineElementFence);
|
||||
}
|
||||
|
||||
@Override
|
||||
Splitr newSpliterator(int firstSpineIndex, int lastSpineIndex,
|
||||
int firstSpineElementIndex, int lastSpineElementFence) {
|
||||
return new Splitr(firstSpineIndex, lastSpineIndex,
|
||||
firstSpineElementIndex, lastSpineElementFence);
|
||||
}
|
||||
|
||||
@Override
|
||||
void arrayForOne(int[] array, int index, IntConsumer consumer) {
|
||||
@ -728,13 +788,13 @@ class SpinedBuffer<E>
|
||||
Spliterator.OfInt arraySpliterator(int[] array, int offset, int len) {
|
||||
return Arrays.spliterator(array, offset, offset+len);
|
||||
}
|
||||
};
|
||||
return new Splitr();
|
||||
}
|
||||
return new Splitr(0, spineIndex, 0, elementIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
int[] array = asIntArray();
|
||||
int[] array = asPrimitiveArray();
|
||||
if (array.length < 200) {
|
||||
return String.format("%s[length=%d, chunks=%d]%s",
|
||||
getClass().getSimpleName(), array.length,
|
||||
@ -778,7 +838,7 @@ class SpinedBuffer<E>
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long[] newArray(int size) {
|
||||
public long[] newArray(int size) {
|
||||
return new long[size];
|
||||
}
|
||||
|
||||
@ -809,10 +869,6 @@ class SpinedBuffer<E>
|
||||
return spine[ch][(int) (index-priorElementCount[ch])];
|
||||
}
|
||||
|
||||
public long[] asLongArray() {
|
||||
return asPrimitiveArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrimitiveIterator.OfLong iterator() {
|
||||
return Spliterators.iterator(spliterator());
|
||||
@ -822,6 +878,19 @@ class SpinedBuffer<E>
|
||||
public Spliterator.OfLong spliterator() {
|
||||
class Splitr extends BaseSpliterator<Spliterator.OfLong>
|
||||
implements Spliterator.OfLong {
|
||||
Splitr(int firstSpineIndex, int lastSpineIndex,
|
||||
int firstSpineElementIndex, int lastSpineElementFence) {
|
||||
super(firstSpineIndex, lastSpineIndex,
|
||||
firstSpineElementIndex, lastSpineElementFence);
|
||||
}
|
||||
|
||||
@Override
|
||||
Splitr newSpliterator(int firstSpineIndex, int lastSpineIndex,
|
||||
int firstSpineElementIndex, int lastSpineElementFence) {
|
||||
return new Splitr(firstSpineIndex, lastSpineIndex,
|
||||
firstSpineElementIndex, lastSpineElementFence);
|
||||
}
|
||||
|
||||
@Override
|
||||
void arrayForOne(long[] array, int index, LongConsumer consumer) {
|
||||
consumer.accept(array[index]);
|
||||
@ -831,13 +900,13 @@ class SpinedBuffer<E>
|
||||
Spliterator.OfLong arraySpliterator(long[] array, int offset, int len) {
|
||||
return Arrays.spliterator(array, offset, offset+len);
|
||||
}
|
||||
};
|
||||
return new Splitr();
|
||||
}
|
||||
return new Splitr(0, spineIndex, 0, elementIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
long[] array = asLongArray();
|
||||
long[] array = asPrimitiveArray();
|
||||
if (array.length < 200) {
|
||||
return String.format("%s[length=%d, chunks=%d]%s",
|
||||
getClass().getSimpleName(), array.length,
|
||||
@ -882,7 +951,7 @@ class SpinedBuffer<E>
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double[] newArray(int size) {
|
||||
public double[] newArray(int size) {
|
||||
return new double[size];
|
||||
}
|
||||
|
||||
@ -913,10 +982,6 @@ class SpinedBuffer<E>
|
||||
return spine[ch][(int) (index-priorElementCount[ch])];
|
||||
}
|
||||
|
||||
public double[] asDoubleArray() {
|
||||
return asPrimitiveArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrimitiveIterator.OfDouble iterator() {
|
||||
return Spliterators.iterator(spliterator());
|
||||
@ -925,6 +990,19 @@ class SpinedBuffer<E>
|
||||
public Spliterator.OfDouble spliterator() {
|
||||
class Splitr extends BaseSpliterator<Spliterator.OfDouble>
|
||||
implements Spliterator.OfDouble {
|
||||
Splitr(int firstSpineIndex, int lastSpineIndex,
|
||||
int firstSpineElementIndex, int lastSpineElementFence) {
|
||||
super(firstSpineIndex, lastSpineIndex,
|
||||
firstSpineElementIndex, lastSpineElementFence);
|
||||
}
|
||||
|
||||
@Override
|
||||
Splitr newSpliterator(int firstSpineIndex, int lastSpineIndex,
|
||||
int firstSpineElementIndex, int lastSpineElementFence) {
|
||||
return new Splitr(firstSpineIndex, lastSpineIndex,
|
||||
firstSpineElementIndex, lastSpineElementFence);
|
||||
}
|
||||
|
||||
@Override
|
||||
void arrayForOne(double[] array, int index, DoubleConsumer consumer) {
|
||||
consumer.accept(array[index]);
|
||||
@ -935,12 +1013,12 @@ class SpinedBuffer<E>
|
||||
return Arrays.spliterator(array, offset, offset+len);
|
||||
}
|
||||
}
|
||||
return new Splitr();
|
||||
return new Splitr(0, spineIndex, 0, elementIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
double[] array = asDoubleArray();
|
||||
double[] array = asPrimitiveArray();
|
||||
if (array.length < 200) {
|
||||
return String.format("%s[length=%d, chunks=%d]%s",
|
||||
getClass().getSimpleName(), array.length,
|
||||
|
@ -122,12 +122,12 @@ public class DoubleNodeTest extends OpTestCase {
|
||||
|
||||
@Test(dataProvider = "nodes")
|
||||
public void testAsArray(double[] array, Node.OfDouble n) {
|
||||
assertEquals(n.asDoubleArray(), array);
|
||||
assertEquals(n.asPrimitiveArray(), array);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "nodes")
|
||||
public void testFlattenAsArray(double[] array, Node.OfDouble n) {
|
||||
assertEquals(Nodes.flattenDouble(n).asDoubleArray(), array);
|
||||
assertEquals(Nodes.flattenDouble(n).asPrimitiveArray(), array);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "nodes")
|
||||
|
@ -122,12 +122,12 @@ public class IntNodeTest extends OpTestCase {
|
||||
|
||||
@Test(dataProvider = "nodes")
|
||||
public void testAsArray(int[] array, Node.OfInt n) {
|
||||
assertEquals(n.asIntArray(), array);
|
||||
assertEquals(n.asPrimitiveArray(), array);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "nodes")
|
||||
public void testFlattenAsArray(int[] array, Node.OfInt n) {
|
||||
assertEquals(Nodes.flattenInt(n).asIntArray(), array);
|
||||
assertEquals(Nodes.flattenInt(n).asPrimitiveArray(), array);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "nodes")
|
||||
|
@ -122,12 +122,12 @@ public class LongNodeTest extends OpTestCase {
|
||||
|
||||
@Test(dataProvider = "nodes")
|
||||
public void testAsArray(long[] array, Node.OfLong n) {
|
||||
assertEquals(n.asLongArray(), array);
|
||||
assertEquals(n.asPrimitiveArray(), array);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "nodes")
|
||||
public void testFlattenAsArray(long[] array, Node.OfLong n) {
|
||||
assertEquals(Nodes.flattenLong(n).asLongArray(), array);
|
||||
assertEquals(Nodes.flattenLong(n).asPrimitiveArray(), array);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "nodes")
|
||||
|
@ -210,7 +210,7 @@ public class SpinedBufferTest {
|
||||
list2.clear();
|
||||
sb.forEach((int i) -> list2.add(i));
|
||||
assertEquals(list1, list2);
|
||||
int[] array = sb.asIntArray();
|
||||
int[] array = sb.asPrimitiveArray();
|
||||
list2.clear();
|
||||
for (int i : array)
|
||||
list2.add(i);
|
||||
@ -285,7 +285,7 @@ public class SpinedBufferTest {
|
||||
list2.clear();
|
||||
sb.forEach((long i) -> list2.add(i));
|
||||
assertEquals(list1, list2);
|
||||
long[] array = sb.asLongArray();
|
||||
long[] array = sb.asPrimitiveArray();
|
||||
list2.clear();
|
||||
for (long i : array)
|
||||
list2.add(i);
|
||||
@ -361,7 +361,7 @@ public class SpinedBufferTest {
|
||||
list2.clear();
|
||||
sb.forEach((double i) -> list2.add(i));
|
||||
assertEquals(list1, list2);
|
||||
double[] array = sb.asDoubleArray();
|
||||
double[] array = sb.asPrimitiveArray();
|
||||
list2.clear();
|
||||
for (double i : array)
|
||||
list2.add(i);
|
||||
|
Loading…
Reference in New Issue
Block a user