mirror of
https://github.com/Eaglercraft-Archive/Eaglercraftx-1.8.8-src.git
synced 2025-06-28 10:58:15 -05:00
Update #51 - Protocol and FPS improvements, better workspace
This commit is contained in:
@ -1,51 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.ByteCursor;
|
||||
import com.carrotsearch.hppc.predicates.BytePredicate;
|
||||
import java.util.Arrays;
|
||||
|
||||
/** Common superclass for collections. */
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "AbstractKTypeCollection.java")
|
||||
abstract class AbstractByteCollection implements ByteCollection {
|
||||
/** Default implementation uses a predicate for removal. */
|
||||
@Override
|
||||
public int removeAll(final ByteLookupContainer c) {
|
||||
return this.removeAll(c::contains);
|
||||
}
|
||||
|
||||
/** Default implementation uses a predicate for retaining. */
|
||||
@Override
|
||||
public int retainAll(final ByteLookupContainer c) {
|
||||
// We know c holds sub-types of byte and we're not modifying c, so go unchecked.
|
||||
return this.removeAll(k -> !c.contains(k));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation redirects to {@link #removeAll(BytePredicate)} and negates the
|
||||
* predicate.
|
||||
*/
|
||||
@Override
|
||||
public int retainAll(final BytePredicate predicate) {
|
||||
return removeAll(value -> !predicate.apply(value));
|
||||
}
|
||||
|
||||
/** Default implementation of copying to an array. */
|
||||
@Override
|
||||
public byte[] toArray() {
|
||||
|
||||
byte[] array = (new byte[size()]);
|
||||
int i = 0;
|
||||
for (ByteCursor c : this) {
|
||||
array[i++] = c.value;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/** Convert the contents of this container to a human-friendly string. */
|
||||
@Override
|
||||
public String toString() {
|
||||
return Arrays.toString(this.toArray());
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.CharCursor;
|
||||
import com.carrotsearch.hppc.predicates.CharPredicate;
|
||||
import java.util.Arrays;
|
||||
|
||||
/** Common superclass for collections. */
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "AbstractKTypeCollection.java")
|
||||
abstract class AbstractCharCollection implements CharCollection {
|
||||
/** Default implementation uses a predicate for removal. */
|
||||
@Override
|
||||
public int removeAll(final CharLookupContainer c) {
|
||||
return this.removeAll(c::contains);
|
||||
}
|
||||
|
||||
/** Default implementation uses a predicate for retaining. */
|
||||
@Override
|
||||
public int retainAll(final CharLookupContainer c) {
|
||||
// We know c holds sub-types of char and we're not modifying c, so go unchecked.
|
||||
return this.removeAll(k -> !c.contains(k));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation redirects to {@link #removeAll(CharPredicate)} and negates the
|
||||
* predicate.
|
||||
*/
|
||||
@Override
|
||||
public int retainAll(final CharPredicate predicate) {
|
||||
return removeAll(value -> !predicate.apply(value));
|
||||
}
|
||||
|
||||
/** Default implementation of copying to an array. */
|
||||
@Override
|
||||
public char[] toArray() {
|
||||
|
||||
char[] array = (new char[size()]);
|
||||
int i = 0;
|
||||
for (CharCursor c : this) {
|
||||
array[i++] = c.value;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/** Convert the contents of this container to a human-friendly string. */
|
||||
@Override
|
||||
public String toString() {
|
||||
return Arrays.toString(this.toArray());
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.DoubleCursor;
|
||||
import com.carrotsearch.hppc.predicates.DoublePredicate;
|
||||
import java.util.Arrays;
|
||||
|
||||
/** Common superclass for collections. */
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "AbstractKTypeCollection.java")
|
||||
abstract class AbstractDoubleCollection implements DoubleCollection {
|
||||
/** Default implementation uses a predicate for removal. */
|
||||
@Override
|
||||
public int removeAll(final DoubleLookupContainer c) {
|
||||
return this.removeAll(c::contains);
|
||||
}
|
||||
|
||||
/** Default implementation uses a predicate for retaining. */
|
||||
@Override
|
||||
public int retainAll(final DoubleLookupContainer c) {
|
||||
// We know c holds sub-types of double and we're not modifying c, so go unchecked.
|
||||
return this.removeAll(k -> !c.contains(k));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation redirects to {@link #removeAll(DoublePredicate)} and negates the
|
||||
* predicate.
|
||||
*/
|
||||
@Override
|
||||
public int retainAll(final DoublePredicate predicate) {
|
||||
return removeAll(value -> !predicate.apply(value));
|
||||
}
|
||||
|
||||
/** Default implementation of copying to an array. */
|
||||
@Override
|
||||
public double[] toArray() {
|
||||
|
||||
double[] array = (new double[size()]);
|
||||
int i = 0;
|
||||
for (DoubleCursor c : this) {
|
||||
array[i++] = c.value;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/** Convert the contents of this container to a human-friendly string. */
|
||||
@Override
|
||||
public String toString() {
|
||||
return Arrays.toString(this.toArray());
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.FloatCursor;
|
||||
import com.carrotsearch.hppc.predicates.FloatPredicate;
|
||||
import java.util.Arrays;
|
||||
|
||||
/** Common superclass for collections. */
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "AbstractKTypeCollection.java")
|
||||
abstract class AbstractFloatCollection implements FloatCollection {
|
||||
/** Default implementation uses a predicate for removal. */
|
||||
@Override
|
||||
public int removeAll(final FloatLookupContainer c) {
|
||||
return this.removeAll(c::contains);
|
||||
}
|
||||
|
||||
/** Default implementation uses a predicate for retaining. */
|
||||
@Override
|
||||
public int retainAll(final FloatLookupContainer c) {
|
||||
// We know c holds sub-types of float and we're not modifying c, so go unchecked.
|
||||
return this.removeAll(k -> !c.contains(k));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation redirects to {@link #removeAll(FloatPredicate)} and negates the
|
||||
* predicate.
|
||||
*/
|
||||
@Override
|
||||
public int retainAll(final FloatPredicate predicate) {
|
||||
return removeAll(value -> !predicate.apply(value));
|
||||
}
|
||||
|
||||
/** Default implementation of copying to an array. */
|
||||
@Override
|
||||
public float[] toArray() {
|
||||
|
||||
float[] array = (new float[size()]);
|
||||
int i = 0;
|
||||
for (FloatCursor c : this) {
|
||||
array[i++] = c.value;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/** Convert the contents of this container to a human-friendly string. */
|
||||
@Override
|
||||
public String toString() {
|
||||
return Arrays.toString(this.toArray());
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.IntCursor;
|
||||
import com.carrotsearch.hppc.predicates.IntPredicate;
|
||||
import java.util.Arrays;
|
||||
|
||||
/** Common superclass for collections. */
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "AbstractKTypeCollection.java")
|
||||
abstract class AbstractIntCollection implements IntCollection {
|
||||
/** Default implementation uses a predicate for removal. */
|
||||
@Override
|
||||
public int removeAll(final IntLookupContainer c) {
|
||||
return this.removeAll(c::contains);
|
||||
}
|
||||
|
||||
/** Default implementation uses a predicate for retaining. */
|
||||
@Override
|
||||
public int retainAll(final IntLookupContainer c) {
|
||||
// We know c holds sub-types of int and we're not modifying c, so go unchecked.
|
||||
return this.removeAll(k -> !c.contains(k));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation redirects to {@link #removeAll(IntPredicate)} and negates the predicate.
|
||||
*/
|
||||
@Override
|
||||
public int retainAll(final IntPredicate predicate) {
|
||||
return removeAll(value -> !predicate.apply(value));
|
||||
}
|
||||
|
||||
/** Default implementation of copying to an array. */
|
||||
@Override
|
||||
public int[] toArray() {
|
||||
|
||||
int[] array = (new int[size()]);
|
||||
int i = 0;
|
||||
for (IntCursor c : this) {
|
||||
array[i++] = c.value;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/** Convert the contents of this container to a human-friendly string. */
|
||||
@Override
|
||||
public String toString() {
|
||||
return Arrays.toString(this.toArray());
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
/*
|
||||
* HPPC
|
||||
*
|
||||
* Copyright (C) 2010-2024 Carrot Search s.c. and contributors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Refer to the full license file "LICENSE.txt":
|
||||
* https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
|
||||
*/
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/** Simplifies the implementation of iterators a bit. Modeled loosely after Google Guava's API. */
|
||||
public abstract class AbstractIterator<E> implements Iterator<E> {
|
||||
private static final int NOT_CACHED = 0;
|
||||
private static final int CACHED = 1;
|
||||
private static final int AT_END = 2;
|
||||
|
||||
/** Current iterator state. */
|
||||
private int state = NOT_CACHED;
|
||||
|
||||
/** The next element to be returned from {@link #next()} if fetched. */
|
||||
private E nextElement;
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (state == NOT_CACHED) {
|
||||
state = CACHED;
|
||||
nextElement = fetch();
|
||||
}
|
||||
return state == CACHED;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public E next() {
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
state = NOT_CACHED;
|
||||
return nextElement;
|
||||
}
|
||||
|
||||
/** Default implementation throws {@link UnsupportedOperationException}. */
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch next element. The implementation must return {@link #done()} when all elements have been
|
||||
* fetched.
|
||||
*
|
||||
* @return Returns the next value for the iterator or chain-calls {@link #done()}.
|
||||
*/
|
||||
protected abstract E fetch();
|
||||
|
||||
/**
|
||||
* Call when done.
|
||||
*
|
||||
* @return Returns a unique sentinel value to indicate end-of-iteration.
|
||||
*/
|
||||
protected final E done() {
|
||||
state = AT_END;
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.LongCursor;
|
||||
import com.carrotsearch.hppc.predicates.LongPredicate;
|
||||
import java.util.Arrays;
|
||||
|
||||
/** Common superclass for collections. */
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "AbstractKTypeCollection.java")
|
||||
abstract class AbstractLongCollection implements LongCollection {
|
||||
/** Default implementation uses a predicate for removal. */
|
||||
@Override
|
||||
public int removeAll(final LongLookupContainer c) {
|
||||
return this.removeAll(c::contains);
|
||||
}
|
||||
|
||||
/** Default implementation uses a predicate for retaining. */
|
||||
@Override
|
||||
public int retainAll(final LongLookupContainer c) {
|
||||
// We know c holds sub-types of long and we're not modifying c, so go unchecked.
|
||||
return this.removeAll(k -> !c.contains(k));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation redirects to {@link #removeAll(LongPredicate)} and negates the
|
||||
* predicate.
|
||||
*/
|
||||
@Override
|
||||
public int retainAll(final LongPredicate predicate) {
|
||||
return removeAll(value -> !predicate.apply(value));
|
||||
}
|
||||
|
||||
/** Default implementation of copying to an array. */
|
||||
@Override
|
||||
public long[] toArray() {
|
||||
|
||||
long[] array = (new long[size()]);
|
||||
int i = 0;
|
||||
for (LongCursor c : this) {
|
||||
array[i++] = c.value;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/** Convert the contents of this container to a human-friendly string. */
|
||||
@Override
|
||||
public String toString() {
|
||||
return Arrays.toString(this.toArray());
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.ObjectCursor;
|
||||
import com.carrotsearch.hppc.predicates.ObjectPredicate;
|
||||
import java.util.Arrays;
|
||||
|
||||
/** Common superclass for collections. */
|
||||
@SuppressWarnings("unchecked")
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "AbstractKTypeCollection.java")
|
||||
abstract class AbstractObjectCollection<KType> implements ObjectCollection<KType> {
|
||||
/** Default implementation uses a predicate for removal. */
|
||||
@Override
|
||||
public int removeAll(final ObjectLookupContainer<? super KType> c) {
|
||||
return this.removeAll(c::contains);
|
||||
}
|
||||
|
||||
/** Default implementation uses a predicate for retaining. */
|
||||
@Override
|
||||
public int retainAll(final ObjectLookupContainer<? super KType> c) {
|
||||
// We know c holds sub-types of Object and we're not modifying c, so go unchecked.
|
||||
return this.removeAll(k -> !c.contains(k));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation redirects to {@link #removeAll(ObjectPredicate)} and negates the
|
||||
* predicate.
|
||||
*/
|
||||
@Override
|
||||
public int retainAll(final ObjectPredicate<? super KType> predicate) {
|
||||
return removeAll(value -> !predicate.apply(value));
|
||||
}
|
||||
|
||||
/** Default implementation of copying to an array. */
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
|
||||
KType[] array = ((KType[]) new Object[size()]);
|
||||
int i = 0;
|
||||
for (ObjectCursor<KType> c : this) {
|
||||
array[i++] = c.value;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public <T> T[] toArray(Class<T> componentClass) {
|
||||
final int size = size();
|
||||
final T[] array = (T[]) java.lang.reflect.Array.newInstance(componentClass, size);
|
||||
int i = 0;
|
||||
for (ObjectCursor<KType> c : this) {
|
||||
array[i++] = (T) c.value;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/** Convert the contents of this container to a human-friendly string. */
|
||||
@Override
|
||||
public String toString() {
|
||||
return Arrays.toString(this.toArray());
|
||||
}
|
||||
|
||||
protected boolean equals(Object v1, Object v2) {
|
||||
return (v1 == v2) || (v1 != null && v1.equals(v2));
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.ShortCursor;
|
||||
import com.carrotsearch.hppc.predicates.ShortPredicate;
|
||||
import java.util.Arrays;
|
||||
|
||||
/** Common superclass for collections. */
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "AbstractKTypeCollection.java")
|
||||
abstract class AbstractShortCollection implements ShortCollection {
|
||||
/** Default implementation uses a predicate for removal. */
|
||||
@Override
|
||||
public int removeAll(final ShortLookupContainer c) {
|
||||
return this.removeAll(c::contains);
|
||||
}
|
||||
|
||||
/** Default implementation uses a predicate for retaining. */
|
||||
@Override
|
||||
public int retainAll(final ShortLookupContainer c) {
|
||||
// We know c holds sub-types of short and we're not modifying c, so go unchecked.
|
||||
return this.removeAll(k -> !c.contains(k));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation redirects to {@link #removeAll(ShortPredicate)} and negates the
|
||||
* predicate.
|
||||
*/
|
||||
@Override
|
||||
public int retainAll(final ShortPredicate predicate) {
|
||||
return removeAll(value -> !predicate.apply(value));
|
||||
}
|
||||
|
||||
/** Default implementation of copying to an array. */
|
||||
@Override
|
||||
public short[] toArray() {
|
||||
|
||||
short[] array = (new short[size()]);
|
||||
int i = 0;
|
||||
for (ShortCursor c : this) {
|
||||
array[i++] = c.value;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/** Convert the contents of this container to a human-friendly string. */
|
||||
@Override
|
||||
public String toString() {
|
||||
return Arrays.toString(this.toArray());
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* HPPC
|
||||
*
|
||||
* Copyright (C) 2010-2024 Carrot Search s.c. and contributors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Refer to the full license file "LICENSE.txt":
|
||||
* https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
|
||||
*/
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
/**
|
||||
* Anything that could be accounted for memory usage
|
||||
*
|
||||
* <p>Partly forked from Lucene tag releases/lucene-solr/8.5.1
|
||||
*/
|
||||
public interface Accountable {
|
||||
/**
|
||||
* Allocated memory estimation
|
||||
*
|
||||
* @return Ram allocated in bytes
|
||||
*/
|
||||
long ramBytesAllocated();
|
||||
|
||||
/**
|
||||
* Bytes that is actually been used
|
||||
*
|
||||
* @return Ram used in bytes
|
||||
*/
|
||||
long ramBytesUsed();
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* HPPC
|
||||
*
|
||||
* Copyright (C) 2010-2024 Carrot Search s.c. and contributors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Refer to the full license file "LICENSE.txt":
|
||||
* https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
|
||||
*/
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
/** Resizing (growth) strategy for array-backed buffers. */
|
||||
public interface ArraySizingStrategy extends Accountable {
|
||||
/**
|
||||
* @param currentBufferLength Current size of the array (buffer). This number should comply with
|
||||
* the strategy's policies (it is a result of initial rounding or further growCalls). It can
|
||||
* also be zero, indicating the growth from an empty buffer.
|
||||
* @param elementsCount Number of elements stored in the buffer.
|
||||
* @param expectedAdditions Expected number of additions (resize hint).
|
||||
* @return Must return a new size at least as big as to hold <code>
|
||||
* elementsCount + expectedAdditions</code>.
|
||||
* @throws BufferAllocationException If the sizing strategy cannot grow the buffer (for example
|
||||
* due to constraints or memory limits).
|
||||
*/
|
||||
int grow(int currentBufferLength, int elementsCount, int expectedAdditions)
|
||||
throws BufferAllocationException;
|
||||
}
|
@ -1,120 +0,0 @@
|
||||
/*
|
||||
* HPPC
|
||||
*
|
||||
* Copyright (C) 2010-2024 Carrot Search s.c. and contributors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Refer to the full license file "LICENSE.txt":
|
||||
* https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
|
||||
*/
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
/**
|
||||
* Bit mixing utilities. The purpose of these methods is to evenly distribute key space over int32
|
||||
* range.
|
||||
*/
|
||||
public final class BitMixer {
|
||||
|
||||
// Don't bother mixing very small key domains much.
|
||||
public static int mix(byte key) {
|
||||
return key * PHI_C32;
|
||||
}
|
||||
|
||||
public static int mix(short key) {
|
||||
return mixPhi(key);
|
||||
}
|
||||
|
||||
public static int mix(char key) {
|
||||
return mixPhi(key);
|
||||
}
|
||||
|
||||
// Better mix for larger key domains.
|
||||
public static int mix(int key) {
|
||||
return mix32(key);
|
||||
}
|
||||
|
||||
public static int mix(float key) {
|
||||
return mix32(Float.floatToIntBits(key));
|
||||
}
|
||||
|
||||
public static int mix(double key) {
|
||||
return (int) mix64(Double.doubleToLongBits(key));
|
||||
}
|
||||
|
||||
public static int mix(long key) {
|
||||
return (int) mix64(key);
|
||||
}
|
||||
|
||||
public static int mix(Object key) {
|
||||
return key == null ? 0 : mix32(key.hashCode());
|
||||
}
|
||||
|
||||
/** MH3's plain finalization step. */
|
||||
public static int mix32(int k) {
|
||||
k = (k ^ (k >>> 16)) * 0x85ebca6b;
|
||||
k = (k ^ (k >>> 13)) * 0xc2b2ae35;
|
||||
return k ^ (k >>> 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes David Stafford variant 9 of 64bit mix function (MH3 finalization step, with different
|
||||
* shifts and constants).
|
||||
*
|
||||
* <p>Variant 9 is picked because it contains two 32-bit shifts which could be possibly optimized
|
||||
* into better machine code.
|
||||
*
|
||||
* @see "http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html"
|
||||
*/
|
||||
public static long mix64(long z) {
|
||||
z = (z ^ (z >>> 32)) * 0x4cd6944c5cc20b6dL;
|
||||
z = (z ^ (z >>> 29)) * 0xfc12c5b19d3259e9L;
|
||||
return z ^ (z >>> 32);
|
||||
}
|
||||
|
||||
/*
|
||||
* Golden ratio bit mixers.
|
||||
*/
|
||||
|
||||
private static final int PHI_C32 = 0x9e3779b9;
|
||||
private static final long PHI_C64 = 0x9e3779b97f4a7c15L;
|
||||
|
||||
public static int mixPhi(byte k) {
|
||||
final int h = k * PHI_C32;
|
||||
return h ^ (h >>> 16);
|
||||
}
|
||||
|
||||
public static int mixPhi(char k) {
|
||||
final int h = k * PHI_C32;
|
||||
return h ^ (h >>> 16);
|
||||
}
|
||||
|
||||
public static int mixPhi(short k) {
|
||||
final int h = k * PHI_C32;
|
||||
return h ^ (h >>> 16);
|
||||
}
|
||||
|
||||
public static int mixPhi(int k) {
|
||||
final int h = k * PHI_C32;
|
||||
return h ^ (h >>> 16);
|
||||
}
|
||||
|
||||
public static int mixPhi(float k) {
|
||||
final int h = Float.floatToIntBits(k) * PHI_C32;
|
||||
return h ^ (h >>> 16);
|
||||
}
|
||||
|
||||
public static int mixPhi(double k) {
|
||||
final long h = Double.doubleToLongBits(k) * PHI_C64;
|
||||
return (int) (h ^ (h >>> 32));
|
||||
}
|
||||
|
||||
public static int mixPhi(long k) {
|
||||
final long h = k * PHI_C64;
|
||||
return (int) (h ^ (h >>> 32));
|
||||
}
|
||||
|
||||
public static int mixPhi(Object k) {
|
||||
final int h = (k == null ? 0 : k.hashCode() * PHI_C32);
|
||||
return h ^ (h >>> 16);
|
||||
}
|
||||
}
|
@ -1,952 +0,0 @@
|
||||
/*
|
||||
* HPPC
|
||||
*
|
||||
* Copyright (C) 2010-2024 Carrot Search s.c. and contributors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Refer to the full license file "LICENSE.txt":
|
||||
* https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
|
||||
*/
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.IntCursor;
|
||||
import com.carrotsearch.hppc.cursors.LongCursor;
|
||||
import com.carrotsearch.hppc.predicates.IntPredicate;
|
||||
import com.carrotsearch.hppc.predicates.LongPredicate;
|
||||
import com.carrotsearch.hppc.procedures.IntProcedure;
|
||||
import com.carrotsearch.hppc.procedures.LongProcedure;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* An "open" BitSet implementation that allows direct access to the array of words storing the bits.
|
||||
*
|
||||
* <p>Unlike {@link java.util.BitSet}, the fact that bits are packed into an array of longs is part
|
||||
* of the interface. This allows efficient implementation of other algorithms by someone other than
|
||||
* the author. It also allows one to efficiently implement alternate serialization or interchange
|
||||
* formats.
|
||||
*
|
||||
* <p>The index range for a bitset can easily exceed positive <code>int</code> range in Java
|
||||
* (0x7fffffff), so many methods in this class accept or return a <code>long</code>. There are
|
||||
* adapter methods that return views compatible with {@link LongLookupContainer} and {@link
|
||||
* IntLookupContainer} interfaces.
|
||||
*
|
||||
* @see #asIntLookupContainer()
|
||||
* @see #asLongLookupContainer()
|
||||
*/
|
||||
public class BitSet implements Cloneable {
|
||||
/** The initial default number of bits. */
|
||||
private static final long DEFAULT_NUM_BITS = 64;
|
||||
|
||||
/** Internal representation of bits in this bit set. */
|
||||
public long[] bits;
|
||||
|
||||
/** The number of words (longs) used in the {@link #bits} array. */
|
||||
public int wlen;
|
||||
|
||||
/** Constructs a bit set with the default capacity. */
|
||||
public BitSet() {
|
||||
this(DEFAULT_NUM_BITS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an BitSet large enough to hold numBits.
|
||||
*
|
||||
* @param numBits Number of bits
|
||||
*/
|
||||
public BitSet(long numBits) {
|
||||
bits = new long[bits2words(numBits)];
|
||||
wlen = bits.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an BitSet from an existing long[].
|
||||
*
|
||||
* <p>The first 64 bits are in long[0], with bit index 0 at the least significant bit, and bit
|
||||
* index 63 at the most significant. Given a bit index, the word containing it is long[index/64],
|
||||
* and it is at bit number index%64 within that word.
|
||||
*
|
||||
* <p>numWords are the number of elements in the array that contain set bits (non-zero longs).
|
||||
* numWords should be <= bits.length, and any existing words in the array at position >=
|
||||
* numWords should be zero.
|
||||
*
|
||||
* @param bits underlying bits buffer
|
||||
* @param numWords the number of elements in the array that contain set bits
|
||||
*/
|
||||
public BitSet(long[] bits, int numWords) {
|
||||
this.bits = bits;
|
||||
this.wlen = numWords;
|
||||
}
|
||||
|
||||
/**
|
||||
* Static constructor-like method similar to other (generic) collections.
|
||||
*
|
||||
* @return New instance.
|
||||
*/
|
||||
public static BitSet newInstance() {
|
||||
return new BitSet();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns an iterator over all set bits of this bitset. The iterator should be faster
|
||||
* than using a loop around {@link #nextSetBit(int)}.
|
||||
*/
|
||||
public BitSetIterator iterator() {
|
||||
return new BitSetIterator(bits, wlen);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the current capacity in bits (1 greater than the index of the last bit).
|
||||
*/
|
||||
public long capacity() {
|
||||
return bits.length << 6;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #cardinality()
|
||||
* @see java.util.BitSet#size()
|
||||
* @return Returns the current capacity of this set. Included for compatibility. This is
|
||||
* <b>not</b> equal to {@link #cardinality}.
|
||||
*/
|
||||
public long size() {
|
||||
return capacity();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.BitSet#length()
|
||||
* @return Returns the "logical size" of this {@code BitSet}: the index of the highest set bit in
|
||||
* the {@code BitSet} plus one.
|
||||
*/
|
||||
public long length() {
|
||||
trimTrailingZeros();
|
||||
if (wlen == 0) return 0;
|
||||
return (((long) wlen - 1) << 6) + (64 - Long.numberOfLeadingZeros(bits[wlen - 1]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns true if there are no set bits
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return cardinality() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param index The index.
|
||||
* @return Returns true or false for the specified bit index.
|
||||
*/
|
||||
public boolean get(int index) {
|
||||
int i = index >> 6; // div 64
|
||||
// signed shift will keep a negative index and force an
|
||||
// array-index-out-of-bounds-exception, removing the need for an explicit check.
|
||||
if (i >= bits.length) return false;
|
||||
|
||||
int bit = index & 0x3f; // mod 64
|
||||
long bitmask = 1L << bit;
|
||||
return (bits[i] & bitmask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param index The index.
|
||||
* @return Returns true or false for the specified bit index.
|
||||
*/
|
||||
public boolean get(long index) {
|
||||
int i = (int) (index >> 6); // div 64
|
||||
if (i >= bits.length) return false;
|
||||
int bit = (int) index & 0x3f; // mod 64
|
||||
long bitmask = 1L << bit;
|
||||
return (bits[i] & bitmask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a bit, expanding the set size if necessary.
|
||||
*
|
||||
* @param index the index to set
|
||||
*/
|
||||
public void set(long index) {
|
||||
int wordNum = expandingWordNum(index);
|
||||
int bit = (int) index & 0x3f;
|
||||
long bitmask = 1L << bit;
|
||||
bits[wordNum] |= bitmask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a range of bits, expanding the set size if necessary
|
||||
*
|
||||
* @param startIndex lower index
|
||||
* @param endIndex one-past the last bit to set
|
||||
*/
|
||||
public void set(long startIndex, long endIndex) {
|
||||
if (endIndex <= startIndex) return;
|
||||
|
||||
int startWord = (int) (startIndex >> 6);
|
||||
|
||||
// since endIndex is one past the end, this is index of the last
|
||||
// word to be changed.
|
||||
int endWord = expandingWordNum(endIndex - 1);
|
||||
|
||||
long startmask = -1L << startIndex;
|
||||
long endmask = -1L >>> -endIndex; // 64-(endIndex&0x3f) is the same as -endIndex
|
||||
// due to wrap
|
||||
|
||||
if (startWord == endWord) {
|
||||
bits[startWord] |= (startmask & endmask);
|
||||
return;
|
||||
}
|
||||
|
||||
bits[startWord] |= startmask;
|
||||
Arrays.fill(bits, startWord + 1, endWord, -1L);
|
||||
bits[endWord] |= endmask;
|
||||
}
|
||||
|
||||
protected int expandingWordNum(long index) {
|
||||
int wordNum = (int) (index >> 6);
|
||||
if (wordNum >= wlen) {
|
||||
ensureCapacity(index + 1);
|
||||
wlen = wordNum + 1;
|
||||
}
|
||||
return wordNum;
|
||||
}
|
||||
|
||||
/** Clears all bits. */
|
||||
public void clear() {
|
||||
Arrays.fill(bits, 0);
|
||||
this.wlen = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* clears a bit, allowing access beyond the current set size without changing the size.
|
||||
*
|
||||
* @param index the index to clear
|
||||
*/
|
||||
public void clear(long index) {
|
||||
int wordNum = (int) (index >> 6); // div 64
|
||||
if (wordNum >= wlen) return;
|
||||
int bit = (int) index & 0x3f; // mod 64
|
||||
long bitmask = 1L << bit;
|
||||
bits[wordNum] &= ~bitmask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears a range of bits. Clearing past the end does not change the size of the set.
|
||||
*
|
||||
* @param startIndex lower index
|
||||
* @param endIndex one-past the last bit to clear
|
||||
*/
|
||||
public void clear(int startIndex, int endIndex) {
|
||||
if (endIndex <= startIndex) return;
|
||||
|
||||
int startWord = (startIndex >> 6);
|
||||
if (startWord >= wlen) return;
|
||||
|
||||
// since endIndex is one past the end, this is index of the last
|
||||
// word to be changed.
|
||||
int endWord = ((endIndex - 1) >> 6);
|
||||
|
||||
long startmask = -1L << startIndex;
|
||||
long endmask = -1L >>> -endIndex; // 64-(endIndex&0x3f) is the same as -endIndex
|
||||
// due to wrap
|
||||
|
||||
// invert masks since we are clearing
|
||||
startmask = ~startmask;
|
||||
endmask = ~endmask;
|
||||
|
||||
if (startWord == endWord) {
|
||||
bits[startWord] &= (startmask | endmask);
|
||||
return;
|
||||
}
|
||||
|
||||
bits[startWord] &= startmask;
|
||||
|
||||
int middle = Math.min(wlen, endWord);
|
||||
Arrays.fill(bits, startWord + 1, middle, 0L);
|
||||
if (endWord < wlen) {
|
||||
bits[endWord] &= endmask;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears a range of bits. Clearing past the end does not change the size of the set.
|
||||
*
|
||||
* @param startIndex lower index
|
||||
* @param endIndex one-past the last bit to clear
|
||||
*/
|
||||
public void clear(long startIndex, long endIndex) {
|
||||
if (endIndex <= startIndex) return;
|
||||
|
||||
int startWord = (int) (startIndex >> 6);
|
||||
if (startWord >= wlen) return;
|
||||
|
||||
// since endIndex is one past the end, this is index of the last
|
||||
// word to be changed.
|
||||
int endWord = (int) ((endIndex - 1) >> 6);
|
||||
|
||||
long startmask = -1L << startIndex;
|
||||
long endmask = -1L >>> -endIndex; // 64-(endIndex&0x3f) is the same as -endIndex
|
||||
// due to wrap
|
||||
|
||||
// invert masks since we are clearing
|
||||
startmask = ~startmask;
|
||||
endmask = ~endmask;
|
||||
|
||||
if (startWord == endWord) {
|
||||
bits[startWord] &= (startmask | endmask);
|
||||
return;
|
||||
}
|
||||
|
||||
bits[startWord] &= startmask;
|
||||
|
||||
int middle = Math.min(wlen, endWord);
|
||||
Arrays.fill(bits, startWord + 1, middle, 0L);
|
||||
if (endWord < wlen) {
|
||||
bits[endWord] &= endmask;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a bit and returns the previous value. The index should be less than the BitSet size.
|
||||
*
|
||||
* @param index the index to set
|
||||
* @return previous state of the index
|
||||
*/
|
||||
public boolean getAndSet(int index) {
|
||||
int wordNum = index >> 6; // div 64
|
||||
int bit = index & 0x3f; // mod 64
|
||||
long bitmask = 1L << bit;
|
||||
boolean val = (bits[wordNum] & bitmask) != 0;
|
||||
bits[wordNum] |= bitmask;
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a bit and returns the previous value. The index should be less than the BitSet size.
|
||||
*
|
||||
* @param index the index to set
|
||||
* @return previous state of the index
|
||||
*/
|
||||
public boolean getAndSet(long index) {
|
||||
int wordNum = (int) (index >> 6); // div 64
|
||||
int bit = (int) index & 0x3f; // mod 64
|
||||
long bitmask = 1L << bit;
|
||||
boolean val = (bits[wordNum] & bitmask) != 0;
|
||||
bits[wordNum] |= bitmask;
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flips a bit, expanding the set size if necessary.
|
||||
*
|
||||
* @param index the index to flip
|
||||
*/
|
||||
public void flip(long index) {
|
||||
int wordNum = expandingWordNum(index);
|
||||
int bit = (int) index & 0x3f; // mod 64
|
||||
long bitmask = 1L << bit;
|
||||
bits[wordNum] ^= bitmask;
|
||||
}
|
||||
|
||||
/**
|
||||
* flips a bit and returns the resulting bit value. The index should be less than the BitSet size.
|
||||
*
|
||||
* @param index the index to flip
|
||||
* @return previous state of the index
|
||||
*/
|
||||
public boolean flipAndGet(int index) {
|
||||
int wordNum = index >> 6; // div 64
|
||||
int bit = index & 0x3f; // mod 64
|
||||
long bitmask = 1L << bit;
|
||||
bits[wordNum] ^= bitmask;
|
||||
return (bits[wordNum] & bitmask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* flips a bit and returns the resulting bit value. The index should be less than the BitSet size.
|
||||
*
|
||||
* @param index the index to flip
|
||||
* @return previous state of the index
|
||||
*/
|
||||
public boolean flipAndGet(long index) {
|
||||
int wordNum = (int) (index >> 6); // div 64
|
||||
int bit = (int) index & 0x3f; // mod 64
|
||||
long bitmask = 1L << bit;
|
||||
bits[wordNum] ^= bitmask;
|
||||
return (bits[wordNum] & bitmask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flips a range of bits, expanding the set size if necessary
|
||||
*
|
||||
* @param startIndex lower index
|
||||
* @param endIndex one-past the last bit to flip
|
||||
*/
|
||||
public void flip(long startIndex, long endIndex) {
|
||||
if (endIndex <= startIndex) return;
|
||||
int startWord = (int) (startIndex >> 6);
|
||||
|
||||
// since endIndex is one past the end, this is index of the last
|
||||
// word to be changed.
|
||||
int endWord = expandingWordNum(endIndex - 1);
|
||||
|
||||
long startmask = -1L << startIndex;
|
||||
long endmask = -1L >>> -endIndex; // 64-(endIndex&0x3f) is the same as -endIndex
|
||||
// due to wrap
|
||||
|
||||
if (startWord == endWord) {
|
||||
bits[startWord] ^= (startmask & endmask);
|
||||
return;
|
||||
}
|
||||
|
||||
bits[startWord] ^= startmask;
|
||||
|
||||
for (int i = startWord + 1; i < endWord; i++) {
|
||||
bits[i] = ~bits[i];
|
||||
}
|
||||
|
||||
bits[endWord] ^= endmask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of set bits
|
||||
*/
|
||||
public long cardinality() {
|
||||
return BitUtil.pop_array(bits, 0, wlen);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param a The first set
|
||||
* @param b The second set
|
||||
* @return Returns the popcount or cardinality of the intersection of the two sets. Neither set is
|
||||
* modified.
|
||||
*/
|
||||
public static long intersectionCount(BitSet a, BitSet b) {
|
||||
return BitUtil.pop_intersect(a.bits, b.bits, 0, Math.min(a.wlen, b.wlen));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param a The first set
|
||||
* @param b The second set
|
||||
* @return Returns the popcount or cardinality of the union of the two sets. Neither set is
|
||||
* modified.
|
||||
*/
|
||||
public static long unionCount(BitSet a, BitSet b) {
|
||||
long tot = BitUtil.pop_union(a.bits, b.bits, 0, Math.min(a.wlen, b.wlen));
|
||||
if (a.wlen < b.wlen) {
|
||||
tot += BitUtil.pop_array(b.bits, a.wlen, b.wlen - a.wlen);
|
||||
} else if (a.wlen > b.wlen) {
|
||||
tot += BitUtil.pop_array(a.bits, b.wlen, a.wlen - b.wlen);
|
||||
}
|
||||
return tot;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param a The first set
|
||||
* @param b The second set
|
||||
* @return Returns the popcount or cardinality of "a and not b" or "intersection(a, not(b))".
|
||||
* Neither set is modified.
|
||||
*/
|
||||
public static long andNotCount(BitSet a, BitSet b) {
|
||||
long tot = BitUtil.pop_andnot(a.bits, b.bits, 0, Math.min(a.wlen, b.wlen));
|
||||
if (a.wlen > b.wlen) {
|
||||
tot += BitUtil.pop_array(a.bits, b.wlen, a.wlen - b.wlen);
|
||||
}
|
||||
return tot;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param a The first set
|
||||
* @param b The second set
|
||||
* @return Returns the popcount or cardinality of the exclusive-or of the two sets. Neither set is
|
||||
* modified.
|
||||
*/
|
||||
public static long xorCount(BitSet a, BitSet b) {
|
||||
long tot = BitUtil.pop_xor(a.bits, b.bits, 0, Math.min(a.wlen, b.wlen));
|
||||
if (a.wlen < b.wlen) {
|
||||
tot += BitUtil.pop_array(b.bits, a.wlen, b.wlen - a.wlen);
|
||||
} else if (a.wlen > b.wlen) {
|
||||
tot += BitUtil.pop_array(a.bits, b.wlen, a.wlen - b.wlen);
|
||||
}
|
||||
return tot;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param index The index to start scanning from, inclusive.
|
||||
* @return Returns the index of the first set bit starting at the index specified. -1 is returned
|
||||
* if there are no more set bits.
|
||||
*/
|
||||
public int nextSetBit(int index) {
|
||||
int i = index >> 6;
|
||||
if (i >= wlen) return -1;
|
||||
int subIndex = index & 0x3f; // index within the word
|
||||
long word = bits[i] >> subIndex; // skip all the bits to the right of index
|
||||
|
||||
if (word != 0) {
|
||||
return (i << 6) + subIndex + Long.numberOfTrailingZeros(word);
|
||||
}
|
||||
|
||||
while (++i < wlen) {
|
||||
word = bits[i];
|
||||
if (word != 0) return (i << 6) + Long.numberOfTrailingZeros(word);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param index The index to start scanning from, inclusive.
|
||||
* @return Returns the index of the first set bit starting at the index specified. -1 is returned
|
||||
* if there are no more set bits.
|
||||
*/
|
||||
public long nextSetBit(long index) {
|
||||
int i = (int) (index >>> 6);
|
||||
if (i >= wlen) return -1;
|
||||
int subIndex = (int) index & 0x3f; // index within the word
|
||||
long word = bits[i] >>> subIndex; // skip all the bits to the right of index
|
||||
|
||||
if (word != 0) {
|
||||
return (((long) i) << 6) + (subIndex + Long.numberOfTrailingZeros(word));
|
||||
}
|
||||
|
||||
while (++i < wlen) {
|
||||
word = bits[i];
|
||||
if (word != 0) return (((long) i) << 6) + Long.numberOfTrailingZeros(word);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() {
|
||||
try {
|
||||
BitSet obs = (BitSet) super.clone();
|
||||
obs.bits = (long[]) obs.bits.clone(); // hopefully an array clone is as
|
||||
// fast(er) than arraycopy
|
||||
return obs;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* this = this AND other
|
||||
*
|
||||
* @param other The bitset to intersect with.
|
||||
*/
|
||||
public void intersect(BitSet other) {
|
||||
int newLen = Math.min(this.wlen, other.wlen);
|
||||
long[] thisArr = this.bits;
|
||||
long[] otherArr = other.bits;
|
||||
// testing against zero can be more efficient
|
||||
int pos = newLen;
|
||||
while (--pos >= 0) {
|
||||
thisArr[pos] &= otherArr[pos];
|
||||
}
|
||||
if (this.wlen > newLen) {
|
||||
// fill zeros from the new shorter length to the old length
|
||||
Arrays.fill(bits, newLen, this.wlen, 0);
|
||||
}
|
||||
this.wlen = newLen;
|
||||
}
|
||||
|
||||
/**
|
||||
* this = this OR other
|
||||
*
|
||||
* @param other The bitset to union with.
|
||||
*/
|
||||
public void union(BitSet other) {
|
||||
int newLen = Math.max(wlen, other.wlen);
|
||||
ensureCapacityWords(newLen);
|
||||
|
||||
long[] thisArr = this.bits;
|
||||
long[] otherArr = other.bits;
|
||||
int pos = Math.min(wlen, other.wlen);
|
||||
while (--pos >= 0) {
|
||||
thisArr[pos] |= otherArr[pos];
|
||||
}
|
||||
if (this.wlen < newLen) {
|
||||
System.arraycopy(otherArr, this.wlen, thisArr, this.wlen, newLen - this.wlen);
|
||||
}
|
||||
this.wlen = newLen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all elements set in other: this = this AND_NOT other
|
||||
*
|
||||
* @param other The other bitset.
|
||||
*/
|
||||
public void remove(BitSet other) {
|
||||
int idx = Math.min(wlen, other.wlen);
|
||||
long[] thisArr = this.bits;
|
||||
long[] otherArr = other.bits;
|
||||
while (--idx >= 0) {
|
||||
thisArr[idx] &= ~otherArr[idx];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* this = this XOR other
|
||||
*
|
||||
* @param other The other bitset.
|
||||
*/
|
||||
public void xor(BitSet other) {
|
||||
int newLen = Math.max(wlen, other.wlen);
|
||||
ensureCapacityWords(newLen);
|
||||
|
||||
long[] thisArr = this.bits;
|
||||
long[] otherArr = other.bits;
|
||||
int pos = Math.min(wlen, other.wlen);
|
||||
while (--pos >= 0) {
|
||||
thisArr[pos] ^= otherArr[pos];
|
||||
}
|
||||
if (this.wlen < newLen) {
|
||||
System.arraycopy(otherArr, this.wlen, thisArr, this.wlen, newLen - this.wlen);
|
||||
}
|
||||
this.wlen = newLen;
|
||||
}
|
||||
|
||||
// some BitSet compatibility methods
|
||||
|
||||
// ** see {@link intersect} */
|
||||
public void and(BitSet other) {
|
||||
intersect(other);
|
||||
}
|
||||
|
||||
// ** see {@link union} */
|
||||
public void or(BitSet other) {
|
||||
union(other);
|
||||
}
|
||||
|
||||
// ** see {@link andNot} */
|
||||
public void andNot(BitSet other) {
|
||||
remove(other);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param other The other bitset.
|
||||
* @return true if the sets have any elements in common
|
||||
*/
|
||||
public boolean intersects(BitSet other) {
|
||||
int pos = Math.min(this.wlen, other.wlen);
|
||||
long[] thisArr = this.bits;
|
||||
long[] otherArr = other.bits;
|
||||
while (--pos >= 0) {
|
||||
if ((thisArr[pos] & otherArr[pos]) != 0) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand the long[] with the size given as a number of words (64 bit longs). getNumWords() is
|
||||
* unchanged by this call.
|
||||
*
|
||||
* @param numWords The size to expand to (64-bit long words)
|
||||
*/
|
||||
public void ensureCapacityWords(int numWords) {
|
||||
if (bits.length < numWords) {
|
||||
bits = grow(bits, numWords);
|
||||
}
|
||||
}
|
||||
|
||||
public static long[] grow(long[] array, int minSize) {
|
||||
if (array.length < minSize) {
|
||||
long[] newArray = new long[getNextSize(minSize)];
|
||||
System.arraycopy(array, 0, newArray, 0, array.length);
|
||||
return newArray;
|
||||
} else return array;
|
||||
}
|
||||
|
||||
public static int getNextSize(int targetSize) {
|
||||
/*
|
||||
* This over-allocates proportional to the list size, making room for additional
|
||||
* growth. The over-allocation is mild, but is enough to give linear-time
|
||||
* amortized behavior over a long sequence of appends() in the presence of a
|
||||
* poorly-performing system realloc(). The growth pattern is: 0, 4, 8, 16, 25, 35,
|
||||
* 46, 58, 72, 88, ...
|
||||
*/
|
||||
return (targetSize >> 3) + (targetSize < 9 ? 3 : 6) + targetSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the long[] is big enough to hold numBits, expanding it if necessary. getNumWords()
|
||||
* is unchanged by this call.
|
||||
*
|
||||
* @param numBits The number of bits to expand to
|
||||
*/
|
||||
public void ensureCapacity(long numBits) {
|
||||
ensureCapacityWords(bits2words(numBits));
|
||||
}
|
||||
|
||||
/** Lowers {@link #wlen}, the number of words in use, by checking for trailing zero words. */
|
||||
public void trimTrailingZeros() {
|
||||
int idx = wlen - 1;
|
||||
while (idx >= 0 && bits[idx] == 0) idx--;
|
||||
wlen = idx + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* returns the number of 64 bit words it would take to hold numBits
|
||||
*/
|
||||
public static int bits2words(long numBits) {
|
||||
return (int) (((numBits - 1) >>> 6) + 1);
|
||||
}
|
||||
|
||||
/* returns true if both sets have the same bits set */
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof BitSet)) return false;
|
||||
|
||||
BitSet a;
|
||||
BitSet b = (BitSet) o;
|
||||
|
||||
// make a the larger set.
|
||||
if (b.wlen > this.wlen) {
|
||||
a = b;
|
||||
b = this;
|
||||
} else {
|
||||
a = this;
|
||||
}
|
||||
|
||||
// check for any set bits out of the range of b
|
||||
for (int i = a.wlen - 1; i >= b.wlen; i--) {
|
||||
if (a.bits[i] != 0) return false;
|
||||
}
|
||||
|
||||
for (int i = b.wlen - 1; i >= 0; i--) {
|
||||
if (a.bits[i] != b.bits[i]) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// Start with a zero hash and use a mix that results in zero if the input is zero.
|
||||
// This effectively truncates trailing zeros without an explicit check.
|
||||
long h = 0;
|
||||
for (int i = bits.length; --i >= 0; ) {
|
||||
h ^= bits[i];
|
||||
h = (h << 1) | (h >>> 63); // rotate left
|
||||
}
|
||||
|
||||
// fold leftmost bits into right and add a constant to prevent
|
||||
// empty sets from returning 0, which is too common.
|
||||
return (int) ((h >> 32) ^ h) + 0x98761234;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
long bit = nextSetBit(0);
|
||||
if (bit < 0) {
|
||||
return "{}";
|
||||
}
|
||||
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append("{");
|
||||
|
||||
builder.append(Long.toString(bit));
|
||||
while ((bit = nextSetBit(bit + 1)) >= 0) {
|
||||
builder.append(", ");
|
||||
builder.append(Long.toString(bit));
|
||||
}
|
||||
builder.append("}");
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a view over this bitset data compatible with {@link IntLookupContainer}. A new object
|
||||
* is always returned, but its methods reflect the current state of the bitset (the view is not a
|
||||
* snapshot).
|
||||
*
|
||||
* <p>Methods of the returned {@link IntLookupContainer} may throw a {@link RuntimeException} if
|
||||
* the cardinality of this bitset exceeds the int range.
|
||||
*
|
||||
* @return The view of this bitset as {@link IntLookupContainer}.
|
||||
*/
|
||||
public IntLookupContainer asIntLookupContainer() {
|
||||
return new IntLookupContainer() {
|
||||
@Override
|
||||
public int size() {
|
||||
return getCurrentCardinality();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return BitSet.this.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<IntCursor> iterator() {
|
||||
return new Iterator<IntCursor>() {
|
||||
private long nextBitSet = BitSet.this.nextSetBit(0);
|
||||
private final IntCursor cursor = new IntCursor();
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return nextBitSet >= 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntCursor next() {
|
||||
final long value = nextBitSet;
|
||||
if (value < 0) throw new NoSuchElementException();
|
||||
if (value > Integer.MAX_VALUE)
|
||||
throw new RuntimeException("BitSet range larger than maximum positive integer.");
|
||||
|
||||
nextBitSet = BitSet.this.nextSetBit(value + 1);
|
||||
cursor.index = cursor.value = (int) value;
|
||||
return cursor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] toArray() {
|
||||
final int[] data = new int[getCurrentCardinality()];
|
||||
final BitSetIterator i = BitSet.this.iterator();
|
||||
for (int j = 0, bit = i.nextSetBit(); bit >= 0; bit = i.nextSetBit()) {
|
||||
data[j++] = bit;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends IntPredicate> T forEach(T predicate) {
|
||||
final BitSetIterator i = BitSet.this.iterator();
|
||||
for (int bit = i.nextSetBit(); bit >= 0; bit = i.nextSetBit()) {
|
||||
if (predicate.apply(bit) == false) break;
|
||||
}
|
||||
|
||||
return predicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends IntProcedure> T forEach(T procedure) {
|
||||
final BitSetIterator i = BitSet.this.iterator();
|
||||
for (int bit = i.nextSetBit(); bit >= 0; bit = i.nextSetBit()) {
|
||||
procedure.apply(bit);
|
||||
}
|
||||
|
||||
return procedure;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(int index) {
|
||||
return index < 0 || BitSet.this.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds the bitset's cardinality to an integer or throws a {@link RuntimeException} if the
|
||||
* cardinality exceeds maximum int range.
|
||||
*/
|
||||
private int getCurrentCardinality() {
|
||||
long cardinality = BitSet.this.cardinality();
|
||||
if (cardinality > Integer.MAX_VALUE)
|
||||
throw new RuntimeException(
|
||||
"Bitset is larger than maximum positive integer: " + cardinality);
|
||||
return (int) cardinality;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a view over this bitset data compatible with {@link LongLookupContainer}. A new object
|
||||
* is always returned, but its methods reflect the current state of the bitset (the view is not a
|
||||
* snapshot).
|
||||
*
|
||||
* @return The view of this bitset as {@link LongLookupContainer}.
|
||||
*/
|
||||
public LongLookupContainer asLongLookupContainer() {
|
||||
return new LongLookupContainer() {
|
||||
@Override
|
||||
public int size() {
|
||||
return getCurrentCardinality();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return BitSet.this.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<LongCursor> iterator() {
|
||||
return new Iterator<LongCursor>() {
|
||||
private long nextBitSet = BitSet.this.nextSetBit(0);
|
||||
private final LongCursor cursor = new LongCursor();
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return nextBitSet >= 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LongCursor next() {
|
||||
final long value = nextBitSet;
|
||||
if (value < 0) throw new NoSuchElementException();
|
||||
|
||||
nextBitSet = BitSet.this.nextSetBit(value + 1);
|
||||
cursor.index = (int) value;
|
||||
cursor.value = value;
|
||||
return cursor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public long[] toArray() {
|
||||
final long[] data = new long[getCurrentCardinality()];
|
||||
final BitSet bset = BitSet.this;
|
||||
int j = 0;
|
||||
for (long bit = bset.nextSetBit((long) 0); bit >= 0; bit = bset.nextSetBit(bit + 1)) {
|
||||
data[j++] = bit;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends LongPredicate> T forEach(T predicate) {
|
||||
final BitSet bset = BitSet.this;
|
||||
for (long bit = bset.nextSetBit((long) 0); bit >= 0; bit = bset.nextSetBit(bit + 1)) {
|
||||
if (predicate.apply(bit) == false) break;
|
||||
}
|
||||
|
||||
return predicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends LongProcedure> T forEach(T procedure) {
|
||||
final BitSet bset = BitSet.this;
|
||||
for (long bit = bset.nextSetBit((long) 0); bit >= 0; bit = bset.nextSetBit(bit + 1)) {
|
||||
procedure.apply(bit);
|
||||
}
|
||||
|
||||
return procedure;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(long index) {
|
||||
return index < 0 || BitSet.this.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds the bitset's cardinality to an integer or throws a {@link RuntimeException} if the
|
||||
* cardinality exceeds maximum int range.
|
||||
*/
|
||||
private int getCurrentCardinality() {
|
||||
long cardinality = BitSet.this.cardinality();
|
||||
if (cardinality > Integer.MAX_VALUE)
|
||||
throw new RuntimeException(
|
||||
"Bitset is larger than maximum positive integer: " + cardinality);
|
||||
return (int) cardinality;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,356 +0,0 @@
|
||||
/*
|
||||
* HPPC
|
||||
*
|
||||
* Copyright (C) 2010-2024 Carrot Search s.c. and contributors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Refer to the full license file "LICENSE.txt":
|
||||
* https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
|
||||
*/
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
/**
|
||||
* An iterator to iterate over set bits in an BitSet. This is faster than nextSetBit() for iterating
|
||||
* over the complete set of bits, especially when the density of the bits set is high.
|
||||
*/
|
||||
public class BitSetIterator {
|
||||
// The General Idea: instead of having an array per byte that has
|
||||
// the offsets of the next set bit, that array could be
|
||||
// packed inside a 32 bit integer (8 4 bit numbers). That
|
||||
// should be faster than accessing an array for each index, and
|
||||
// the total array size is kept smaller (256*sizeof(int))=1K
|
||||
static final int[] bitlist = {
|
||||
0x0,
|
||||
0x1,
|
||||
0x2,
|
||||
0x21,
|
||||
0x3,
|
||||
0x31,
|
||||
0x32,
|
||||
0x321,
|
||||
0x4,
|
||||
0x41,
|
||||
0x42,
|
||||
0x421,
|
||||
0x43,
|
||||
0x431,
|
||||
0x432,
|
||||
0x4321,
|
||||
0x5,
|
||||
0x51,
|
||||
0x52,
|
||||
0x521,
|
||||
0x53,
|
||||
0x531,
|
||||
0x532,
|
||||
0x5321,
|
||||
0x54,
|
||||
0x541,
|
||||
0x542,
|
||||
0x5421,
|
||||
0x543,
|
||||
0x5431,
|
||||
0x5432,
|
||||
0x54321,
|
||||
0x6,
|
||||
0x61,
|
||||
0x62,
|
||||
0x621,
|
||||
0x63,
|
||||
0x631,
|
||||
0x632,
|
||||
0x6321,
|
||||
0x64,
|
||||
0x641,
|
||||
0x642,
|
||||
0x6421,
|
||||
0x643,
|
||||
0x6431,
|
||||
0x6432,
|
||||
0x64321,
|
||||
0x65,
|
||||
0x651,
|
||||
0x652,
|
||||
0x6521,
|
||||
0x653,
|
||||
0x6531,
|
||||
0x6532,
|
||||
0x65321,
|
||||
0x654,
|
||||
0x6541,
|
||||
0x6542,
|
||||
0x65421,
|
||||
0x6543,
|
||||
0x65431,
|
||||
0x65432,
|
||||
0x654321,
|
||||
0x7,
|
||||
0x71,
|
||||
0x72,
|
||||
0x721,
|
||||
0x73,
|
||||
0x731,
|
||||
0x732,
|
||||
0x7321,
|
||||
0x74,
|
||||
0x741,
|
||||
0x742,
|
||||
0x7421,
|
||||
0x743,
|
||||
0x7431,
|
||||
0x7432,
|
||||
0x74321,
|
||||
0x75,
|
||||
0x751,
|
||||
0x752,
|
||||
0x7521,
|
||||
0x753,
|
||||
0x7531,
|
||||
0x7532,
|
||||
0x75321,
|
||||
0x754,
|
||||
0x7541,
|
||||
0x7542,
|
||||
0x75421,
|
||||
0x7543,
|
||||
0x75431,
|
||||
0x75432,
|
||||
0x754321,
|
||||
0x76,
|
||||
0x761,
|
||||
0x762,
|
||||
0x7621,
|
||||
0x763,
|
||||
0x7631,
|
||||
0x7632,
|
||||
0x76321,
|
||||
0x764,
|
||||
0x7641,
|
||||
0x7642,
|
||||
0x76421,
|
||||
0x7643,
|
||||
0x76431,
|
||||
0x76432,
|
||||
0x764321,
|
||||
0x765,
|
||||
0x7651,
|
||||
0x7652,
|
||||
0x76521,
|
||||
0x7653,
|
||||
0x76531,
|
||||
0x76532,
|
||||
0x765321,
|
||||
0x7654,
|
||||
0x76541,
|
||||
0x76542,
|
||||
0x765421,
|
||||
0x76543,
|
||||
0x765431,
|
||||
0x765432,
|
||||
0x7654321,
|
||||
0x8,
|
||||
0x81,
|
||||
0x82,
|
||||
0x821,
|
||||
0x83,
|
||||
0x831,
|
||||
0x832,
|
||||
0x8321,
|
||||
0x84,
|
||||
0x841,
|
||||
0x842,
|
||||
0x8421,
|
||||
0x843,
|
||||
0x8431,
|
||||
0x8432,
|
||||
0x84321,
|
||||
0x85,
|
||||
0x851,
|
||||
0x852,
|
||||
0x8521,
|
||||
0x853,
|
||||
0x8531,
|
||||
0x8532,
|
||||
0x85321,
|
||||
0x854,
|
||||
0x8541,
|
||||
0x8542,
|
||||
0x85421,
|
||||
0x8543,
|
||||
0x85431,
|
||||
0x85432,
|
||||
0x854321,
|
||||
0x86,
|
||||
0x861,
|
||||
0x862,
|
||||
0x8621,
|
||||
0x863,
|
||||
0x8631,
|
||||
0x8632,
|
||||
0x86321,
|
||||
0x864,
|
||||
0x8641,
|
||||
0x8642,
|
||||
0x86421,
|
||||
0x8643,
|
||||
0x86431,
|
||||
0x86432,
|
||||
0x864321,
|
||||
0x865,
|
||||
0x8651,
|
||||
0x8652,
|
||||
0x86521,
|
||||
0x8653,
|
||||
0x86531,
|
||||
0x86532,
|
||||
0x865321,
|
||||
0x8654,
|
||||
0x86541,
|
||||
0x86542,
|
||||
0x865421,
|
||||
0x86543,
|
||||
0x865431,
|
||||
0x865432,
|
||||
0x8654321,
|
||||
0x87,
|
||||
0x871,
|
||||
0x872,
|
||||
0x8721,
|
||||
0x873,
|
||||
0x8731,
|
||||
0x8732,
|
||||
0x87321,
|
||||
0x874,
|
||||
0x8741,
|
||||
0x8742,
|
||||
0x87421,
|
||||
0x8743,
|
||||
0x87431,
|
||||
0x87432,
|
||||
0x874321,
|
||||
0x875,
|
||||
0x8751,
|
||||
0x8752,
|
||||
0x87521,
|
||||
0x8753,
|
||||
0x87531,
|
||||
0x87532,
|
||||
0x875321,
|
||||
0x8754,
|
||||
0x87541,
|
||||
0x87542,
|
||||
0x875421,
|
||||
0x87543,
|
||||
0x875431,
|
||||
0x875432,
|
||||
0x8754321,
|
||||
0x876,
|
||||
0x8761,
|
||||
0x8762,
|
||||
0x87621,
|
||||
0x8763,
|
||||
0x87631,
|
||||
0x87632,
|
||||
0x876321,
|
||||
0x8764,
|
||||
0x87641,
|
||||
0x87642,
|
||||
0x876421,
|
||||
0x87643,
|
||||
0x876431,
|
||||
0x876432,
|
||||
0x8764321,
|
||||
0x8765,
|
||||
0x87651,
|
||||
0x87652,
|
||||
0x876521,
|
||||
0x87653,
|
||||
0x876531,
|
||||
0x876532,
|
||||
0x8765321,
|
||||
0x87654,
|
||||
0x876541,
|
||||
0x876542,
|
||||
0x8765421,
|
||||
0x876543,
|
||||
0x8765431,
|
||||
0x8765432,
|
||||
0x87654321
|
||||
};
|
||||
|
||||
/**
|
||||
* *** the python code that generated bitlist def bits2int(val): arr=0 for shift in range(8,0,-1):
|
||||
* if val & 0x80: arr = (arr << 4) | shift val = val << 1 return arr
|
||||
*
|
||||
* <p>def int_table(): tbl = [ hex(bits2int(val)).strip('L') for val in range(256) ] return
|
||||
* ','.join(tbl) ****
|
||||
*/
|
||||
|
||||
// hmmm, what about an iterator that finds zeros though,
|
||||
// or a reverse iterator... should they be separate classes
|
||||
// for efficiency, or have a common root interface? (or
|
||||
// maybe both? could ask for a SetBitsIterator, etc...
|
||||
|
||||
private final long[] arr;
|
||||
|
||||
private final int words;
|
||||
private int i = -1;
|
||||
private long word;
|
||||
private int wordShift;
|
||||
private int indexArray;
|
||||
|
||||
public BitSetIterator(BitSet obs) {
|
||||
this(obs.bits, obs.wlen);
|
||||
}
|
||||
|
||||
public BitSetIterator(long[] bits, int numWords) {
|
||||
arr = bits;
|
||||
words = numWords;
|
||||
}
|
||||
|
||||
// 64 bit shifts
|
||||
private void shift() {
|
||||
if ((int) word == 0) {
|
||||
wordShift += 32;
|
||||
word = word >>> 32;
|
||||
}
|
||||
if ((word & 0x0000FFFF) == 0) {
|
||||
wordShift += 16;
|
||||
word >>>= 16;
|
||||
}
|
||||
if ((word & 0x000000FF) == 0) {
|
||||
wordShift += 8;
|
||||
word >>>= 8;
|
||||
}
|
||||
indexArray = bitlist[(int) word & 0xff];
|
||||
}
|
||||
|
||||
public static final int NO_MORE = -1;
|
||||
|
||||
public int nextSetBit() {
|
||||
if (indexArray == 0) {
|
||||
if (word != 0) {
|
||||
word >>>= 8;
|
||||
wordShift += 8;
|
||||
}
|
||||
|
||||
while (word == 0) {
|
||||
if (++i >= words) {
|
||||
return NO_MORE;
|
||||
}
|
||||
word = arr[i];
|
||||
wordShift = -1; // loop invariant code motion should move this
|
||||
}
|
||||
|
||||
// after the first time, should I go with a linear search, or
|
||||
// stick with the binary search in shift?
|
||||
shift();
|
||||
}
|
||||
|
||||
int bitIndex = (indexArray & 0x0f) + wordShift;
|
||||
indexArray >>>= 4;
|
||||
// should i<<6 be cached as a separate variable?
|
||||
// it would only save one cycle in the best circumstances.
|
||||
return (i << 6) + bitIndex;
|
||||
}
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
/*
|
||||
* HPPC
|
||||
*
|
||||
* Copyright (C) 2010-2024 Carrot Search s.c. and contributors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Refer to the full license file "LICENSE.txt":
|
||||
* https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
|
||||
*/
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
/** A variety of high efficiency bit twiddling routines. */
|
||||
final class BitUtil {
|
||||
private BitUtil() {} // no instance
|
||||
|
||||
// The pop methods used to rely on bit-manipulation tricks for speed but it
|
||||
// turns out that it is faster to use the Long.bitCount method (which is an
|
||||
// intrinsic since Java 6u18) in a naive loop, see LUCENE-2221
|
||||
|
||||
/** Returns the number of set bits in an array of longs. */
|
||||
public static long pop_array(long[] arr, int wordOffset, int numWords) {
|
||||
long popCount = 0;
|
||||
for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) {
|
||||
popCount += Long.bitCount(arr[i]);
|
||||
}
|
||||
return popCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the popcount or cardinality of the two sets after an intersection. Neither array is
|
||||
* modified.
|
||||
*/
|
||||
public static long pop_intersect(long[] arr1, long[] arr2, int wordOffset, int numWords) {
|
||||
long popCount = 0;
|
||||
for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) {
|
||||
popCount += Long.bitCount(arr1[i] & arr2[i]);
|
||||
}
|
||||
return popCount;
|
||||
}
|
||||
|
||||
/** Returns the popcount or cardinality of the union of two sets. Neither array is modified. */
|
||||
public static long pop_union(long[] arr1, long[] arr2, int wordOffset, int numWords) {
|
||||
long popCount = 0;
|
||||
for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) {
|
||||
popCount += Long.bitCount(arr1[i] | arr2[i]);
|
||||
}
|
||||
return popCount;
|
||||
}
|
||||
|
||||
/** Returns the popcount or cardinality of A & ~B. Neither array is modified. */
|
||||
public static long pop_andnot(long[] arr1, long[] arr2, int wordOffset, int numWords) {
|
||||
long popCount = 0;
|
||||
for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) {
|
||||
popCount += Long.bitCount(arr1[i] & ~arr2[i]);
|
||||
}
|
||||
return popCount;
|
||||
}
|
||||
|
||||
/** Returns the popcount or cardinality of A ^ B Neither array is modified. */
|
||||
public static long pop_xor(long[] arr1, long[] arr2, int wordOffset, int numWords) {
|
||||
long popCount = 0;
|
||||
for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) {
|
||||
popCount += Long.bitCount(arr1[i] ^ arr2[i]);
|
||||
}
|
||||
return popCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the next highest power of two, or the current value if it's already a power of two or
|
||||
* zero
|
||||
*/
|
||||
public static int nextHighestPowerOfTwo(int v) {
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
v++;
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the next highest power of two, or the current value if it's already a power of two or
|
||||
* zero
|
||||
*/
|
||||
public static long nextHighestPowerOfTwo(long v) {
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
v |= v >> 32;
|
||||
v++;
|
||||
return v;
|
||||
}
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
/*
|
||||
* HPPC
|
||||
*
|
||||
* Copyright (C) 2010-2024 Carrot Search s.c. and contributors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Refer to the full license file "LICENSE.txt":
|
||||
* https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
|
||||
*/
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Array resizing proportional to the current buffer size, optionally kept within the given minimum
|
||||
* and maximum growth limits. Java's {@link ArrayList} uses:
|
||||
*
|
||||
* <pre>
|
||||
* minGrow = 1
|
||||
* maxGrow = Integer.MAX_VALUE (unbounded)
|
||||
* growRatio = 1.5f
|
||||
* </pre>
|
||||
*/
|
||||
public final class BoundedProportionalArraySizingStrategy implements ArraySizingStrategy {
|
||||
|
||||
/** Instance of {@link BoundedProportionalArraySizingStrategy} with default values. */
|
||||
public static final BoundedProportionalArraySizingStrategy DEFAULT_INSTANCE =
|
||||
new BoundedProportionalArraySizingStrategy();
|
||||
|
||||
/**
|
||||
* Maximum allocable array length (approximately the largest positive integer decreased by the
|
||||
* array's object header).
|
||||
*/
|
||||
public static final int MAX_ARRAY_LENGTH =
|
||||
Integer.MAX_VALUE - /* aligned array header + slack */ 32;
|
||||
|
||||
/** Minimum grow count. */
|
||||
public static final int DEFAULT_MIN_GROW_COUNT = 10;
|
||||
|
||||
/** Maximum grow count (unbounded). */
|
||||
public static final int DEFAULT_MAX_GROW_COUNT = MAX_ARRAY_LENGTH;
|
||||
|
||||
/** Default resize is by half the current buffer's size. */
|
||||
public static final float DEFAULT_GROW_RATIO = 1.5f;
|
||||
|
||||
/** Minimum number of elements to grow, if limit exceeded. */
|
||||
public final int minGrowCount;
|
||||
|
||||
/** Maximum number of elements to grow, if limit exceeded. */
|
||||
public final int maxGrowCount;
|
||||
|
||||
/**
|
||||
* The current buffer length is multiplied by this ratio to get the first estimate for the new
|
||||
* size. To double the size of the current buffer, for example, set to <code>2</code>.
|
||||
*/
|
||||
public final float growRatio;
|
||||
|
||||
/** Create the default sizing strategy. */
|
||||
public BoundedProportionalArraySizingStrategy() {
|
||||
this(DEFAULT_MIN_GROW_COUNT, DEFAULT_MAX_GROW_COUNT, DEFAULT_GROW_RATIO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the sizing strategy with custom policies.
|
||||
*
|
||||
* @param minGrow Minimum number of elements to grow by when expanding.
|
||||
* @param maxGrow Maximum number of elements to grow by when expanding.
|
||||
* @param ratio The ratio of expansion compared to the previous buffer size.
|
||||
*/
|
||||
public BoundedProportionalArraySizingStrategy(int minGrow, int maxGrow, float ratio) {
|
||||
assert minGrow >= 1 : "Min grow must be >= 1.";
|
||||
assert maxGrow >= minGrow : "Max grow must be >= min grow.";
|
||||
assert ratio >= 1f : "Growth ratio must be >= 1 (was " + ratio + ").";
|
||||
|
||||
this.minGrowCount = minGrow;
|
||||
this.maxGrowCount = maxGrow;
|
||||
this.growRatio = ratio - 1.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grow according to {@link #growRatio}, {@link #minGrowCount} and {@link #maxGrowCount}.
|
||||
*
|
||||
* @param currentBufferLength The current length of the buffer.
|
||||
* @param elementsCount The number of elements stored in the buffer.
|
||||
* @param expectedAdditions The number of expected additions to the buffer.
|
||||
* @return New buffer size.
|
||||
*/
|
||||
public int grow(int currentBufferLength, int elementsCount, int expectedAdditions) {
|
||||
long growBy = (long) ((long) currentBufferLength * growRatio);
|
||||
growBy = Math.max(growBy, minGrowCount);
|
||||
growBy = Math.min(growBy, maxGrowCount);
|
||||
long growTo = Math.min(MAX_ARRAY_LENGTH, growBy + currentBufferLength);
|
||||
long newSize = Math.max((long) elementsCount + expectedAdditions, growTo);
|
||||
|
||||
if (newSize > MAX_ARRAY_LENGTH) {
|
||||
throw new BufferAllocationException(
|
||||
"Java array size exceeded (current length: %d, elements: %d, expected additions: %d)",
|
||||
currentBufferLength, elementsCount, expectedAdditions);
|
||||
}
|
||||
|
||||
return (int) newSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesAllocated() {
|
||||
// int: minGrowCount, maxGrowCount
|
||||
// float: growRatio
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER + Integer.BYTES * 2 + Float.BYTES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesUsed() {
|
||||
return ramBytesAllocated();
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* HPPC
|
||||
*
|
||||
* Copyright (C) 2010-2024 Carrot Search s.c. and contributors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Refer to the full license file "LICENSE.txt":
|
||||
* https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
|
||||
*/
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import java.util.IllegalFormatException;
|
||||
import java.util.Locale;
|
||||
|
||||
public class BufferAllocationException extends RuntimeException {
|
||||
public BufferAllocationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public BufferAllocationException(String message, Object... args) {
|
||||
this(message, null, args);
|
||||
}
|
||||
|
||||
public BufferAllocationException(String message, Throwable t, Object... args) {
|
||||
super(formatMessage(message, t, args), t);
|
||||
}
|
||||
|
||||
private static String formatMessage(String message, Throwable t, Object... args) {
|
||||
try {
|
||||
return String.format(Locale.ROOT, message, args);
|
||||
} catch (IllegalFormatException e) {
|
||||
BufferAllocationException substitute =
|
||||
new BufferAllocationException(message + " [ILLEGAL FORMAT, ARGS SUPPRESSED]");
|
||||
if (t != null) {
|
||||
substitute.addSuppressed(t);
|
||||
}
|
||||
substitute.addSuppressed(e);
|
||||
throw substitute;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,776 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import static com.carrotsearch.hppc.Containers.*;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.ByteCursor;
|
||||
import com.carrotsearch.hppc.predicates.BytePredicate;
|
||||
import com.carrotsearch.hppc.procedures.ByteProcedure;
|
||||
import java.util.*;
|
||||
|
||||
/** An array-backed {@link ByteDeque}. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeArrayDeque.java")
|
||||
public class ByteArrayDeque extends AbstractByteCollection
|
||||
implements ByteDeque, Preallocable, Cloneable, Accountable {
|
||||
|
||||
/** Reuse the same strategy instance. */
|
||||
private static final BoundedProportionalArraySizingStrategy DEFAULT_SIZING_STRATEGY =
|
||||
BoundedProportionalArraySizingStrategy.DEFAULT_INSTANCE;
|
||||
|
||||
/** Internal array for storing elements of the deque. */
|
||||
public byte[] buffer = ByteArrayList.EMPTY_ARRAY;
|
||||
|
||||
/**
|
||||
* The index of the element at the head of the deque or an arbitrary number equal to tail if the
|
||||
* deque is empty.
|
||||
*/
|
||||
public int head;
|
||||
|
||||
/** The index at which the next element would be added to the tail of the deque. */
|
||||
public int tail;
|
||||
|
||||
/** Buffer resizing strategy. */
|
||||
protected final ArraySizingStrategy resizer;
|
||||
|
||||
/** New instance with sane defaults. */
|
||||
public ByteArrayDeque() {
|
||||
this(DEFAULT_EXPECTED_ELEMENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
*/
|
||||
public ByteArrayDeque(int expectedElements) {
|
||||
this(expectedElements, DEFAULT_SIZING_STRATEGY);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
* @param resizer Underlying buffer sizing strategy.
|
||||
*/
|
||||
public ByteArrayDeque(int expectedElements, ArraySizingStrategy resizer) {
|
||||
assert resizer != null;
|
||||
this.resizer = resizer;
|
||||
ensureCapacity(expectedElements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deque from elements of another container, appending elements at the end of the
|
||||
* deque in the iteration order.
|
||||
*/
|
||||
public ByteArrayDeque(ByteContainer container) {
|
||||
this(container.size());
|
||||
addLast(container);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void addFirst(byte e1) {
|
||||
int h = oneLeft(head, buffer.length);
|
||||
if (h == tail) {
|
||||
ensureBufferSpace(1);
|
||||
h = oneLeft(head, buffer.length);
|
||||
}
|
||||
buffer[head = h] = e1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg-signature method for adding elements at the front of this deque.
|
||||
*
|
||||
* <p><b>This method is handy, but costly if used in tight loops (anonymous array passing)</b>
|
||||
*
|
||||
* @param elements The elements to add.
|
||||
*/
|
||||
public final void addFirst(byte... elements) {
|
||||
ensureBufferSpace(elements.length);
|
||||
for (byte k : elements) {
|
||||
addFirst(k);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given container to the front of this deque.
|
||||
*
|
||||
* @param container The container to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addFirst(ByteContainer container) {
|
||||
int size = container.size();
|
||||
ensureBufferSpace(size);
|
||||
|
||||
for (ByteCursor cursor : container) {
|
||||
addFirst(cursor.value);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given iterable to the front of this deque.
|
||||
*
|
||||
* @param iterable The iterable to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addFirst(Iterable<? extends ByteCursor> iterable) {
|
||||
int size = 0;
|
||||
for (ByteCursor cursor : iterable) {
|
||||
addFirst(cursor.value);
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void addLast(byte e1) {
|
||||
int t = oneRight(tail, buffer.length);
|
||||
if (head == t) {
|
||||
ensureBufferSpace(1);
|
||||
t = oneRight(tail, buffer.length);
|
||||
}
|
||||
buffer[tail] = e1;
|
||||
tail = t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg-signature method for adding elements at the end of this deque.
|
||||
*
|
||||
* <p><b>This method is handy, but costly if used in tight loops (anonymous array passing)</b>
|
||||
*
|
||||
* @param elements The elements to iterate over.
|
||||
*/
|
||||
public final void addLast(byte... elements) {
|
||||
ensureBufferSpace(1);
|
||||
for (byte k : elements) {
|
||||
addLast(k);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given container to the end of this deque.
|
||||
*
|
||||
* @param container The container to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addLast(ByteContainer container) {
|
||||
int size = container.size();
|
||||
ensureBufferSpace(size);
|
||||
|
||||
for (ByteCursor cursor : container) {
|
||||
addLast(cursor.value);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given iterable to the end of this deque.
|
||||
*
|
||||
* @param iterable The iterable to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addLast(Iterable<? extends ByteCursor> iterable) {
|
||||
int size = 0;
|
||||
for (ByteCursor cursor : iterable) {
|
||||
addLast(cursor.value);
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public byte removeFirst() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
final byte result = buffer[head];
|
||||
buffer[head] = ((byte) 0);
|
||||
head = oneRight(head, buffer.length);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public byte removeLast() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
tail = oneLeft(tail, buffer.length);
|
||||
final byte result = buffer[tail];
|
||||
buffer[tail] = ((byte) 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public byte getFirst() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
return buffer[head];
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public byte getLast() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
return buffer[oneLeft(tail, buffer.length)];
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeFirst(byte e1) {
|
||||
final int index = bufferIndexOf(e1);
|
||||
if (index >= 0) removeAtBufferIndex(index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index of the first (counting from head) element equal to <code>e1</code>. The index
|
||||
* points to the {@link #buffer} array.
|
||||
*
|
||||
* @param e1 The element to look for.
|
||||
* @return Returns the index of the first element equal to <code>e1</code> or <code>-1</code> if
|
||||
* not found.
|
||||
*/
|
||||
public int bufferIndexOf(byte e1) {
|
||||
final int last = tail;
|
||||
final int bufLen = buffer.length;
|
||||
for (int i = head; i != last; i = oneRight(i, bufLen)) {
|
||||
if (((e1) == (buffer[i]))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeLast(byte e1) {
|
||||
final int index = lastBufferIndexOf(e1);
|
||||
if (index >= 0) {
|
||||
removeAtBufferIndex(index);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index of the last (counting from tail) element equal to <code>e1</code>. The index
|
||||
* points to the {@link #buffer} array.
|
||||
*
|
||||
* @param e1 The element to look for.
|
||||
* @return Returns the index of the first element equal to <code>e1</code> or <code>-1</code> if
|
||||
* not found.
|
||||
*/
|
||||
public int lastBufferIndexOf(byte e1) {
|
||||
final int bufLen = buffer.length;
|
||||
final int last = oneLeft(head, bufLen);
|
||||
for (int i = oneLeft(tail, bufLen); i != last; i = oneLeft(i, bufLen)) {
|
||||
if (((e1) == (buffer[i]))) return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(byte e1) {
|
||||
int removed = 0;
|
||||
final int last = tail;
|
||||
final int bufLen = buffer.length;
|
||||
int from, to;
|
||||
for (from = to = head; from != last; from = oneRight(from, bufLen)) {
|
||||
if (((e1) == (buffer[from]))) {
|
||||
buffer[from] = ((byte) 0);
|
||||
removed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = ((byte) 0);
|
||||
}
|
||||
|
||||
to = oneRight(to, bufLen);
|
||||
}
|
||||
|
||||
tail = to;
|
||||
return removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the element at <code>index</code> in the internal {#link {@link #buffer} array,
|
||||
* returning its value.
|
||||
*
|
||||
* @param index Index of the element to remove. The index must be located between {@link #head}
|
||||
* and {@link #tail} in modulo {@link #buffer} arithmetic.
|
||||
*/
|
||||
public void removeAtBufferIndex(int index) {
|
||||
assert (head <= tail ? index >= head && index < tail : index >= head || index < tail)
|
||||
: "Index out of range (head=" + head + ", tail=" + tail + ", index=" + index + ").";
|
||||
|
||||
// Cache fields in locals (hopefully moved to registers).
|
||||
final byte[] buffer = this.buffer;
|
||||
final int bufLen = buffer.length;
|
||||
final int lastIndex = bufLen - 1;
|
||||
final int head = this.head;
|
||||
final int tail = this.tail;
|
||||
|
||||
final int leftChunk = Math.abs(index - head) % bufLen;
|
||||
final int rightChunk = Math.abs(tail - index) % bufLen;
|
||||
|
||||
if (leftChunk < rightChunk) {
|
||||
if (index >= head) {
|
||||
System.arraycopy(buffer, head, buffer, head + 1, leftChunk);
|
||||
} else {
|
||||
System.arraycopy(buffer, 0, buffer, 1, index);
|
||||
buffer[0] = buffer[lastIndex];
|
||||
System.arraycopy(buffer, head, buffer, head + 1, lastIndex - head);
|
||||
}
|
||||
buffer[head] = ((byte) 0);
|
||||
this.head = oneRight(head, bufLen);
|
||||
} else {
|
||||
if (index < tail) {
|
||||
System.arraycopy(buffer, index + 1, buffer, index, rightChunk);
|
||||
} else {
|
||||
System.arraycopy(buffer, index + 1, buffer, index, lastIndex - index);
|
||||
buffer[lastIndex] = buffer[0];
|
||||
System.arraycopy(buffer, 1, buffer, 0, tail);
|
||||
}
|
||||
buffer[tail] = ((byte) 0);
|
||||
this.tail = oneLeft(tail, bufLen);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int size() {
|
||||
if (head <= tail) return tail - head;
|
||||
else return (tail - head + buffer.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The internal array buffers are not released as a result of this call.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
if (head < tail) {
|
||||
Arrays.fill(buffer, head, tail, ((byte) 0));
|
||||
} else {
|
||||
Arrays.fill(buffer, 0, tail, ((byte) 0));
|
||||
Arrays.fill(buffer, head, buffer.length, ((byte) 0));
|
||||
}
|
||||
this.head = tail = 0;
|
||||
}
|
||||
|
||||
/** Release internal buffers of this deque and reallocate with the default buffer. */
|
||||
public void release() {
|
||||
this.head = tail = 0;
|
||||
buffer = ByteArrayList.EMPTY_ARRAY;
|
||||
ensureBufferSpace(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure this container can hold at least the given number of elements without resizing its
|
||||
* buffers.
|
||||
*
|
||||
* @param expectedElements The total number of elements, inclusive.
|
||||
*/
|
||||
@Override
|
||||
public void ensureCapacity(int expectedElements) {
|
||||
ensureBufferSpace(expectedElements - size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the internal buffer has enough free slots to store <code>expectedAdditions</code>.
|
||||
* Increases internal buffer size if needed.
|
||||
*/
|
||||
protected void ensureBufferSpace(int expectedAdditions) {
|
||||
final int bufferLen = buffer.length;
|
||||
final int elementsCount = size();
|
||||
|
||||
if (elementsCount + expectedAdditions >= bufferLen) {
|
||||
final int emptySlot = 1; // deque invariant: always an empty slot.
|
||||
final int newSize = resizer.grow(bufferLen, elementsCount + emptySlot, expectedAdditions);
|
||||
assert newSize >= (elementsCount + expectedAdditions + emptySlot)
|
||||
: "Resizer failed to"
|
||||
+ " return sensible new size: "
|
||||
+ newSize
|
||||
+ " <= "
|
||||
+ (elementsCount + expectedAdditions);
|
||||
|
||||
try {
|
||||
final byte[] newBuffer = (new byte[newSize]);
|
||||
if (bufferLen > 0) {
|
||||
toArray(newBuffer);
|
||||
tail = elementsCount;
|
||||
head = 0;
|
||||
}
|
||||
this.buffer = newBuffer;
|
||||
} catch (OutOfMemoryError e) {
|
||||
throw new BufferAllocationException(
|
||||
"Not enough memory to allocate new buffers: %,d -> %,d", e, bufferLen, newSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public byte[] toArray() {
|
||||
|
||||
final int size = size();
|
||||
return toArray((new byte[size]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies elements of this deque to an array. The content of the <code>target</code> array is
|
||||
* filled from index 0 (head of the queue) to index <code>size() - 1</code> (tail of the queue).
|
||||
*
|
||||
* @param target The target array must be large enough to hold all elements.
|
||||
* @return Returns the target argument for chaining.
|
||||
*/
|
||||
public byte[] toArray(byte[] target) {
|
||||
assert target.length >= size() : "Target array must be >= " + size();
|
||||
|
||||
if (head < tail) {
|
||||
// The contents is not wrapped around. Just copy.
|
||||
System.arraycopy(buffer, head, target, 0, size());
|
||||
} else if (head > tail) {
|
||||
// The contents is split. Merge elements from the following indexes:
|
||||
// [head...buffer.length - 1][0, tail - 1]
|
||||
final int rightCount = buffer.length - head;
|
||||
System.arraycopy(buffer, head, target, 0, rightCount);
|
||||
System.arraycopy(buffer, 0, target, rightCount, tail);
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone this object. The returned clone will reuse the same hash function and array resizing
|
||||
* strategy.
|
||||
*/
|
||||
@Override
|
||||
public ByteArrayDeque clone() {
|
||||
try {
|
||||
|
||||
ByteArrayDeque cloned = (ByteArrayDeque) super.clone();
|
||||
cloned.buffer = buffer.clone();
|
||||
return cloned;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Move one index to the left, wrapping around buffer. */
|
||||
protected static int oneLeft(int index, int modulus) {
|
||||
if (index >= 1) {
|
||||
return index - 1;
|
||||
}
|
||||
return modulus - 1;
|
||||
}
|
||||
|
||||
/** Move one index to the right, wrapping around buffer. */
|
||||
protected static int oneRight(int index, int modulus) {
|
||||
if (index + 1 == modulus) {
|
||||
return 0;
|
||||
}
|
||||
return index + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesAllocated() {
|
||||
// int: head, tail
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES * 2
|
||||
+ resizer.ramBytesAllocated()
|
||||
+ RamUsageEstimator.shallowSizeOfArray(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesUsed() {
|
||||
// int: head, tail
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES * 2
|
||||
+ resizer.ramBytesUsed()
|
||||
+ RamUsageEstimator.shallowUsedSizeOfArray(buffer, size());
|
||||
}
|
||||
|
||||
/** An iterator implementation for {@link ObjectArrayDeque#iterator}. */
|
||||
private final class ValueIterator extends AbstractIterator<ByteCursor> {
|
||||
private final ByteCursor cursor;
|
||||
private int remaining;
|
||||
|
||||
public ValueIterator() {
|
||||
cursor = new ByteCursor();
|
||||
cursor.index = oneLeft(head, buffer.length);
|
||||
this.remaining = size();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteCursor fetch() {
|
||||
if (remaining == 0) {
|
||||
return done();
|
||||
}
|
||||
|
||||
remaining--;
|
||||
cursor.value = buffer[cursor.index = oneRight(cursor.index, buffer.length)];
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
/** An iterator implementation for {@link ObjectArrayDeque#descendingIterator()}. */
|
||||
private final class DescendingValueIterator extends AbstractIterator<ByteCursor> {
|
||||
private final ByteCursor cursor;
|
||||
private int remaining;
|
||||
|
||||
public DescendingValueIterator() {
|
||||
cursor = new ByteCursor();
|
||||
cursor.index = tail;
|
||||
this.remaining = size();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteCursor fetch() {
|
||||
if (remaining == 0) return done();
|
||||
|
||||
remaining--;
|
||||
cursor.value = buffer[cursor.index = oneLeft(cursor.index, buffer.length)];
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a cursor over the values of this deque (in head to tail order). The iterator is
|
||||
* implemented as a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()} (to avoid boxing of primitive types). To read the current value (or index in
|
||||
* the deque's buffer) use the cursor's public fields. An example is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntValueCursor c : intDeque) {
|
||||
* System.out.println("buffer index=" + c.index + " value=" + c.value);
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public Iterator<ByteCursor> iterator() {
|
||||
return new ValueIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a cursor over the values of this deque (in tail to head order). The iterator is
|
||||
* implemented as a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()} (to avoid boxing of primitive types). To read the current value (or index in
|
||||
* the deque's buffer) use the cursor's public fields. An example is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (Iterator<IntCursor> i = intDeque.descendingIterator(); i.hasNext();) {
|
||||
* final IntCursor c = i.next();
|
||||
* System.out.println("buffer index=" + c.index + " value=" + c.value);
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public Iterator<ByteCursor> descendingIterator() {
|
||||
return new DescendingValueIterator();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends ByteProcedure> T forEach(T procedure) {
|
||||
forEach(procedure, head, tail);
|
||||
return procedure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>procedure</code> to a slice of the deque, <code>fromIndex</code>, inclusive, to
|
||||
* <code>toIndex</code>, exclusive.
|
||||
*/
|
||||
private void forEach(ByteProcedure procedure, int fromIndex, final int toIndex) {
|
||||
final byte[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
procedure.apply(buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends BytePredicate> T forEach(T predicate) {
|
||||
int fromIndex = head;
|
||||
int toIndex = tail;
|
||||
|
||||
final byte[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
if (!predicate.apply(buffer[i])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return predicate;
|
||||
}
|
||||
|
||||
/** Applies <code>procedure</code> to all elements of this deque, tail to head. */
|
||||
@Override
|
||||
public <T extends ByteProcedure> T descendingForEach(T procedure) {
|
||||
descendingForEach(procedure, head, tail);
|
||||
return procedure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>procedure</code> to a slice of the deque, <code>toIndex</code>, exclusive, down
|
||||
* to <code>fromIndex</code>, inclusive.
|
||||
*/
|
||||
private void descendingForEach(ByteProcedure procedure, int fromIndex, final int toIndex) {
|
||||
if (fromIndex == toIndex) return;
|
||||
|
||||
final byte[] buffer = this.buffer;
|
||||
int i = toIndex;
|
||||
do {
|
||||
i = oneLeft(i, buffer.length);
|
||||
procedure.apply(buffer[i]);
|
||||
} while (i != fromIndex);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends BytePredicate> T descendingForEach(T predicate) {
|
||||
descendingForEach(predicate, head, tail);
|
||||
return predicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>predicate</code> to a slice of the deque, <code>toIndex</code>, exclusive, down
|
||||
* to <code>fromIndex</code>, inclusive or until the predicate returns <code>false</code>.
|
||||
*/
|
||||
private void descendingForEach(BytePredicate predicate, int fromIndex, final int toIndex) {
|
||||
if (fromIndex == toIndex) return;
|
||||
|
||||
final byte[] buffer = this.buffer;
|
||||
int i = toIndex;
|
||||
do {
|
||||
i = oneLeft(i, buffer.length);
|
||||
if (!predicate.apply(buffer[i])) {
|
||||
break;
|
||||
}
|
||||
} while (i != fromIndex);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(BytePredicate predicate) {
|
||||
final byte[] buffer = this.buffer;
|
||||
final int last = tail;
|
||||
final int bufLen = buffer.length;
|
||||
int removed = 0;
|
||||
int from, to;
|
||||
from = to = head;
|
||||
try {
|
||||
for (from = to = head; from != last; from = oneRight(from, bufLen)) {
|
||||
if (predicate.apply(buffer[from])) {
|
||||
buffer[from] = ((byte) 0);
|
||||
removed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = ((byte) 0);
|
||||
}
|
||||
|
||||
to = oneRight(to, bufLen);
|
||||
}
|
||||
} finally {
|
||||
// Keep the deque in consistent state even if the predicate throws an exception.
|
||||
for (; from != last; from = oneRight(from, bufLen)) {
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = ((byte) 0);
|
||||
}
|
||||
|
||||
to = oneRight(to, bufLen);
|
||||
}
|
||||
tail = to;
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean contains(byte e) {
|
||||
int fromIndex = head;
|
||||
int toIndex = tail;
|
||||
|
||||
final byte[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
if (((e) == (buffer[i]))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = 1;
|
||||
int fromIndex = head;
|
||||
int toIndex = tail;
|
||||
|
||||
final byte[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
h = 31 * h + BitMixer.mix(this.buffer[i]);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> only if the other object is an instance of the same class and with
|
||||
* the same elements.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return (this == obj)
|
||||
|| (obj != null && getClass() == obj.getClass() && equalElements(getClass().cast(obj)));
|
||||
}
|
||||
|
||||
/** Compare order-aligned elements against another {@link ByteDeque}. */
|
||||
protected boolean equalElements(ByteArrayDeque other) {
|
||||
int max = size();
|
||||
if (other.size() != max) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Iterator<ByteCursor> i1 = this.iterator();
|
||||
Iterator<? extends ByteCursor> i2 = other.iterator();
|
||||
|
||||
while (i1.hasNext() && i2.hasNext()) {
|
||||
if (!((i1.next().value) == (i2.next().value))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return !i1.hasNext() && !i2.hasNext();
|
||||
}
|
||||
|
||||
/** Create a new deque by pushing a variable number of arguments to the end of it. */
|
||||
public static ByteArrayDeque from(byte... elements) {
|
||||
final ByteArrayDeque coll = new ByteArrayDeque(elements.length);
|
||||
coll.addLast(elements);
|
||||
return coll;
|
||||
}
|
||||
}
|
@ -1,579 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import static com.carrotsearch.hppc.Containers.*;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.BytePredicate;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.*;
|
||||
|
||||
/** An array-backed list of bytes. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeArrayList.java")
|
||||
public class ByteArrayList extends AbstractByteCollection
|
||||
implements ByteIndexedContainer, Preallocable, Cloneable, Accountable {
|
||||
/** An immutable empty buffer (array). */
|
||||
public static final byte[] EMPTY_ARRAY = new byte[0];
|
||||
|
||||
;
|
||||
|
||||
/** Reuse the same strategy instance. */
|
||||
private static final BoundedProportionalArraySizingStrategy DEFAULT_SIZING_STRATEGY =
|
||||
BoundedProportionalArraySizingStrategy.DEFAULT_INSTANCE;
|
||||
|
||||
/**
|
||||
* Internal array for storing the list. The array may be larger than the current size ({@link
|
||||
* #size()}).
|
||||
*/
|
||||
public byte[] buffer = EMPTY_ARRAY;
|
||||
|
||||
/** Current number of elements stored in {@link #buffer}. */
|
||||
public int elementsCount;
|
||||
|
||||
/** Buffer resizing strategy. */
|
||||
protected final ArraySizingStrategy resizer;
|
||||
|
||||
/** New instance with sane defaults. */
|
||||
public ByteArrayList() {
|
||||
this(DEFAULT_EXPECTED_ELEMENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
*/
|
||||
public ByteArrayList(int expectedElements) {
|
||||
this(expectedElements, DEFAULT_SIZING_STRATEGY);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
* @param resizer Underlying buffer sizing strategy.
|
||||
*/
|
||||
public ByteArrayList(int expectedElements, ArraySizingStrategy resizer) {
|
||||
assert resizer != null;
|
||||
this.resizer = resizer;
|
||||
buffer = Arrays.copyOf(buffer, expectedElements);
|
||||
}
|
||||
|
||||
/** Creates a new list from the elements of another container in its iteration order. */
|
||||
public ByteArrayList(ByteContainer container) {
|
||||
this(container.size());
|
||||
addAll(container);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void add(byte e1) {
|
||||
ensureBufferSpace(1);
|
||||
buffer[elementsCount++] = e1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends two elements at the end of the list. To add more than two elements, use <code>add
|
||||
* </code> (vararg-version) or access the buffer directly (tight loop).
|
||||
*/
|
||||
public void add(byte e1, byte e2) {
|
||||
ensureBufferSpace(2);
|
||||
buffer[elementsCount++] = e1;
|
||||
buffer[elementsCount++] = e2;
|
||||
}
|
||||
|
||||
/** Add all elements from a range of given array to the list. */
|
||||
public void add(byte[] elements, int start, int length) {
|
||||
assert length >= 0 : "Length must be >= 0";
|
||||
|
||||
ensureBufferSpace(length);
|
||||
System.arraycopy(elements, start, buffer, elementsCount, length);
|
||||
elementsCount += length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg-signature method for adding elements at the end of the list.
|
||||
*
|
||||
* <p><b>This method is handy, but costly if used in tight loops (anonymous array passing)</b>
|
||||
*/
|
||||
public final void add(byte... elements) {
|
||||
add(elements, 0, elements.length);
|
||||
}
|
||||
|
||||
/** Adds all elements from another container. */
|
||||
public int addAll(ByteContainer container) {
|
||||
final int size = container.size();
|
||||
ensureBufferSpace(size);
|
||||
|
||||
for (ByteCursor cursor : container) {
|
||||
add(cursor.value);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/** Adds all elements from another iterable. */
|
||||
public int addAll(Iterable<? extends ByteCursor> iterable) {
|
||||
int size = 0;
|
||||
for (ByteCursor cursor : iterable) {
|
||||
add(cursor.value);
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void insert(int index, byte e1) {
|
||||
assert (index >= 0 && index <= size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
|
||||
ensureBufferSpace(1);
|
||||
System.arraycopy(buffer, index, buffer, index + 1, elementsCount - index);
|
||||
buffer[index] = e1;
|
||||
elementsCount++;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public byte get(int index) {
|
||||
assert (index >= 0 && index < size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
return buffer[index];
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public byte set(int index, byte e1) {
|
||||
assert (index >= 0 && index < size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
final byte v = buffer[index];
|
||||
buffer[index] = e1;
|
||||
return v;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public byte removeAt(int index) {
|
||||
assert (index >= 0 && index < size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
final byte v = buffer[index];
|
||||
System.arraycopy(buffer, index + 1, buffer, index, --elementsCount - index);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public byte removeLast() {
|
||||
assert elementsCount > 0;
|
||||
|
||||
final byte v = buffer[--elementsCount];
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void removeRange(int fromIndex, int toIndex) {
|
||||
assert (fromIndex >= 0 && fromIndex <= size())
|
||||
: "Index " + fromIndex + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
assert (toIndex >= 0 && toIndex <= size())
|
||||
: "Index " + toIndex + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
assert fromIndex <= toIndex : "fromIndex must be <= toIndex: " + fromIndex + ", " + toIndex;
|
||||
|
||||
System.arraycopy(buffer, toIndex, buffer, fromIndex, elementsCount - toIndex);
|
||||
final int count = toIndex - fromIndex;
|
||||
elementsCount -= count;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean removeElement(byte e1) {
|
||||
return removeFirst(e1) != -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeFirst(byte e1) {
|
||||
final int index = indexOf(e1);
|
||||
if (index >= 0) removeAt(index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeLast(byte e1) {
|
||||
final int index = lastIndexOf(e1);
|
||||
if (index >= 0) removeAt(index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(byte e1) {
|
||||
int to = 0;
|
||||
for (int from = 0; from < elementsCount; from++) {
|
||||
if (((e1) == (buffer[from]))) {
|
||||
continue;
|
||||
}
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
}
|
||||
to++;
|
||||
}
|
||||
final int deleted = elementsCount - to;
|
||||
this.elementsCount = to;
|
||||
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean contains(byte e1) {
|
||||
return indexOf(e1) >= 0;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int indexOf(byte e1) {
|
||||
for (int i = 0; i < elementsCount; i++) {
|
||||
if (((e1) == (buffer[i]))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int lastIndexOf(byte e1) {
|
||||
for (int i = elementsCount - 1; i >= 0; i--) {
|
||||
if (((e1) == (buffer[i]))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return elementsCount == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure this container can hold at least the given number of elements without resizing its
|
||||
* buffers.
|
||||
*
|
||||
* @param expectedElements The total number of elements, inclusive.
|
||||
*/
|
||||
@Override
|
||||
public void ensureCapacity(int expectedElements) {
|
||||
final int bufferLen = (buffer == null ? 0 : buffer.length);
|
||||
if (expectedElements > bufferLen) {
|
||||
ensureBufferSpace(expectedElements - size());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the internal buffer has enough free slots to store <code>expectedAdditions</code>.
|
||||
* Increases internal buffer size if needed.
|
||||
*/
|
||||
protected void ensureBufferSpace(int expectedAdditions) {
|
||||
final int bufferLen = (buffer == null ? 0 : buffer.length);
|
||||
if (elementsCount + expectedAdditions > bufferLen) {
|
||||
final int newSize = resizer.grow(bufferLen, elementsCount, expectedAdditions);
|
||||
assert newSize >= elementsCount + expectedAdditions
|
||||
: "Resizer failed to"
|
||||
+ " return sensible new size: "
|
||||
+ newSize
|
||||
+ " <= "
|
||||
+ (elementsCount + expectedAdditions);
|
||||
|
||||
this.buffer = Arrays.copyOf(buffer, newSize);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate or expand the list to the new size. If the list is truncated, the buffer will not be
|
||||
* reallocated (use {@link #trimToSize()} if you need a truncated buffer), but the truncated
|
||||
* values will be reset to the default value (zero). If the list is expanded, the elements beyond
|
||||
* the current size are initialized with JVM-defaults (zero or <code>null</code> values).
|
||||
*/
|
||||
public void resize(int newSize) {
|
||||
if (newSize <= buffer.length) {
|
||||
if (newSize < elementsCount) {
|
||||
Arrays.fill(buffer, newSize, elementsCount, ((byte) 0));
|
||||
} else {
|
||||
Arrays.fill(buffer, elementsCount, newSize, ((byte) 0));
|
||||
}
|
||||
} else {
|
||||
ensureCapacity(newSize);
|
||||
}
|
||||
this.elementsCount = newSize;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int size() {
|
||||
return elementsCount;
|
||||
}
|
||||
|
||||
/** Trim the internal buffer to the current size. */
|
||||
public void trimToSize() {
|
||||
if (size() != this.buffer.length) {
|
||||
this.buffer = toArray();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of stored elements to zero. Releases and initializes the internal storage array
|
||||
* to default values. To clear the list without cleaning the buffer, simply set the {@link
|
||||
* #elementsCount} field to zero.
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
Arrays.fill(buffer, 0, elementsCount, ((byte) 0));
|
||||
this.elementsCount = 0;
|
||||
}
|
||||
|
||||
/** Sets the number of stored elements to zero and releases the internal storage array. */
|
||||
@Override
|
||||
public void release() {
|
||||
this.buffer = EMPTY_ARRAY;
|
||||
this.elementsCount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The returned array is sized to match exactly the number of elements of the stack.
|
||||
*/
|
||||
@Override
|
||||
public byte[] toArray() {
|
||||
|
||||
return Arrays.copyOf(buffer, elementsCount);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public ByteIndexedContainer sort() {
|
||||
Arrays.sort(buffer, 0, elementsCount);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public ByteIndexedContainer reverse() {
|
||||
for (int i = 0, mid = elementsCount >> 1, j = elementsCount - 1; i < mid; i++, j--) {
|
||||
byte tmp = buffer[i];
|
||||
buffer[i] = buffer[j];
|
||||
buffer[j] = tmp;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone this object. The returned clone will reuse the same hash function and array resizing
|
||||
* strategy.
|
||||
*/
|
||||
@Override
|
||||
public ByteArrayList clone() {
|
||||
try {
|
||||
|
||||
final ByteArrayList cloned = (ByteArrayList) super.clone();
|
||||
cloned.buffer = buffer.clone();
|
||||
return cloned;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = 1, max = elementsCount;
|
||||
for (int i = 0; i < max; i++) {
|
||||
h = 31 * h + BitMixer.mix(this.buffer[i]);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> only if the other object is an instance of the same class and with
|
||||
* the same elements.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return (this == obj)
|
||||
|| (obj != null && getClass() == obj.getClass() && equalElements(getClass().cast(obj)));
|
||||
}
|
||||
|
||||
/** Compare index-aligned elements against another {@link ByteIndexedContainer}. */
|
||||
protected boolean equalElements(ByteArrayList other) {
|
||||
int max = size();
|
||||
if (other.size() != max) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < max; i++) {
|
||||
if (!((get(i)) == (other.get(i)))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesAllocated() {
|
||||
// int: elementsCount
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES
|
||||
+ resizer.ramBytesAllocated()
|
||||
+ RamUsageEstimator.shallowSizeOfArray(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesUsed() {
|
||||
// int: elementsCount
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES
|
||||
+ resizer.ramBytesUsed()
|
||||
+ RamUsageEstimator.shallowUsedSizeOfArray(buffer, elementsCount);
|
||||
}
|
||||
|
||||
/** An iterator implementation for {@link ByteArrayList#iterator}. */
|
||||
static final class ValueIterator extends AbstractIterator<ByteCursor> {
|
||||
private final ByteCursor cursor;
|
||||
|
||||
private final byte[] buffer;
|
||||
private final int size;
|
||||
|
||||
public ValueIterator(byte[] buffer, int size) {
|
||||
this.cursor = new ByteCursor();
|
||||
this.cursor.index = -1;
|
||||
this.size = size;
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteCursor fetch() {
|
||||
if (cursor.index + 1 == size) return done();
|
||||
|
||||
cursor.value = buffer[++cursor.index];
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public Iterator<ByteCursor> iterator() {
|
||||
return new ValueIterator(buffer, size());
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends ByteProcedure> T forEach(T procedure) {
|
||||
return forEach(procedure, 0, size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>procedure</code> to a slice of the list, <code>fromIndex</code>, inclusive, to
|
||||
* <code>toIndex</code>, exclusive.
|
||||
*/
|
||||
public <T extends ByteProcedure> T forEach(T procedure, int fromIndex, final int toIndex) {
|
||||
assert (fromIndex >= 0 && fromIndex <= size())
|
||||
: "Index " + fromIndex + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
assert (toIndex >= 0 && toIndex <= size())
|
||||
: "Index " + toIndex + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
|
||||
assert fromIndex <= toIndex : "fromIndex must be <= toIndex: " + fromIndex + ", " + toIndex;
|
||||
|
||||
final byte[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i < toIndex; i++) {
|
||||
procedure.apply(buffer[i]);
|
||||
}
|
||||
|
||||
return procedure;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(BytePredicate predicate) {
|
||||
final byte[] buffer = this.buffer;
|
||||
final int elementsCount = this.elementsCount;
|
||||
int to = 0;
|
||||
int from = 0;
|
||||
try {
|
||||
for (; from < elementsCount; from++) {
|
||||
if (predicate.apply(buffer[from])) {
|
||||
buffer[from] = ((byte) 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = ((byte) 0);
|
||||
}
|
||||
to++;
|
||||
}
|
||||
} finally {
|
||||
// Keep the list in a consistent state, even if the predicate throws an exception.
|
||||
for (; from < elementsCount; from++) {
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = ((byte) 0);
|
||||
}
|
||||
to++;
|
||||
}
|
||||
|
||||
this.elementsCount = to;
|
||||
}
|
||||
|
||||
return elementsCount - to;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends BytePredicate> T forEach(T predicate) {
|
||||
return forEach(predicate, 0, size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>predicate</code> to a slice of the list, <code>fromIndex</code>, inclusive, to
|
||||
* <code>toIndex</code>, exclusive, or until predicate returns <code>false</code>.
|
||||
*/
|
||||
public <T extends BytePredicate> T forEach(T predicate, int fromIndex, final int toIndex) {
|
||||
assert (fromIndex >= 0 && fromIndex <= size())
|
||||
: "Index " + fromIndex + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
assert (toIndex >= 0 && toIndex <= size())
|
||||
: "Index " + toIndex + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
assert fromIndex <= toIndex : "fromIndex must be <= toIndex: " + fromIndex + ", " + toIndex;
|
||||
|
||||
final byte[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i < toIndex; i++) {
|
||||
if (!predicate.apply(buffer[i])) break;
|
||||
}
|
||||
|
||||
return predicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a list from a variable number of arguments or an array of <code>byte</code>. The
|
||||
* elements are copied from the argument to the internal buffer.
|
||||
*/
|
||||
public static ByteArrayList from(byte... elements) {
|
||||
final ByteArrayList list = new ByteArrayList(elements.length);
|
||||
list.add(elements);
|
||||
return list;
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
/**
|
||||
* Reused buffer visualization routines.
|
||||
*
|
||||
* @see ByteSet#visualizeKeyDistribution(int)
|
||||
* @see ByteVTypeMap#visualizeKeyDistribution(int)
|
||||
*/
|
||||
class ByteBufferVisualizer {
|
||||
static String visualizeKeyDistribution(byte[] buffer, int max, int characters) {
|
||||
final StringBuilder b = new StringBuilder();
|
||||
final char[] chars = ".123456789X".toCharArray();
|
||||
for (int i = 1, start = -1; i <= characters; i++) {
|
||||
int end = (int) ((long) i * max / characters);
|
||||
|
||||
if (start + 1 <= end) {
|
||||
int taken = 0;
|
||||
int slots = 0;
|
||||
for (int slot = start + 1; slot <= end; slot++, slots++) {
|
||||
if (!((buffer[slot]) == 0)) {
|
||||
taken++;
|
||||
}
|
||||
}
|
||||
b.append(chars[Math.min(chars.length - 1, taken * chars.length / slots)]);
|
||||
start = end;
|
||||
}
|
||||
}
|
||||
while (b.length() < characters) {
|
||||
b.append(' ');
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.predicates.BytePredicate;
|
||||
|
||||
/**
|
||||
* A collection allows basic, efficient operations on sets of elements (difference and
|
||||
* intersection).
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeCollection.java")
|
||||
public interface ByteCollection extends ByteContainer {
|
||||
/**
|
||||
* Removes all occurrences of <code>e</code> from this collection.
|
||||
*
|
||||
* @param e Element to be removed from this collection, if present.
|
||||
* @return The number of removed elements as a result of this call.
|
||||
*/
|
||||
public int removeAll(byte e);
|
||||
|
||||
/**
|
||||
* Removes all elements in this collection that are present in <code>c</code>.
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int removeAll(ByteLookupContainer c);
|
||||
|
||||
/**
|
||||
* Removes all elements in this collection for which the given predicate returns <code>true</code>
|
||||
* .
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int removeAll(BytePredicate predicate);
|
||||
|
||||
/**
|
||||
* Keeps all elements in this collection that are present in <code>c</code>. Runs in time
|
||||
* proportional to the number of elements in this collection. Equivalent of sets intersection.
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int retainAll(ByteLookupContainer c);
|
||||
|
||||
/**
|
||||
* Keeps all elements in this collection for which the given predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int retainAll(BytePredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all elements from this collection.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Removes all elements from the collection and additionally releases any internal buffers.
|
||||
* Typically, if the object is to be reused, a simple {@link #clear()} should be a better
|
||||
* alternative since it'll avoid reallocation.
|
||||
*
|
||||
* @see #clear()
|
||||
*/
|
||||
public void release();
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.ByteCursor;
|
||||
import com.carrotsearch.hppc.predicates.BytePredicate;
|
||||
import com.carrotsearch.hppc.procedures.ByteProcedure;
|
||||
import java.util.Iterator;
|
||||
|
||||
/** A generic container holding <code>byte</code>s. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeContainer.java")
|
||||
public interface ByteContainer extends Iterable<ByteCursor> {
|
||||
/**
|
||||
* Returns an iterator to a cursor traversing the collection. The order of traversal is not
|
||||
* defined. More than one cursor may be active at a time. The behavior of iterators is undefined
|
||||
* if structural changes are made to the underlying collection.
|
||||
*
|
||||
* <p>The iterator is implemented as a cursor and it returns <b>the same cursor instance</b> on
|
||||
* every call to {@link Iterator#next()} (to avoid boxing of primitive types). To read the current
|
||||
* list's value (or index in the list) use the cursor's public fields. An example is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (ByteCursor<byte> c : container) {
|
||||
* System.out.println("index=" + c.index + " value=" + c.value);
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public Iterator<ByteCursor> iterator();
|
||||
|
||||
/**
|
||||
* Lookup a given element in the container. This operation has no speed guarantees (may be linear
|
||||
* with respect to the size of this container).
|
||||
*
|
||||
* @return Returns <code>true</code> if this container has an element equal to <code>e</code>.
|
||||
*/
|
||||
public boolean contains(byte e);
|
||||
|
||||
/**
|
||||
* Return the current number of elements in this container. The time for calculating the
|
||||
* container's size may take <code>O(n)</code> time, although implementing classes should try to
|
||||
* maintain the current size and return in constant time.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/** Shortcut for <code>size() == 0</code>. */
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Copies all elements of this container to an array.
|
||||
*
|
||||
* <p>The returned array is always a copy, regardless of the storage used by the container.
|
||||
*/
|
||||
public byte[] toArray();
|
||||
|
||||
/**
|
||||
* Applies a <code>procedure</code> to all container elements. Returns the argument (any subclass
|
||||
* of {@link ByteProcedure}. This lets the caller to call methods of the argument by chaining the
|
||||
* call (even if the argument is an anonymous type) to retrieve computed values, for example
|
||||
* (IntContainer):
|
||||
*
|
||||
* <pre>
|
||||
* int count = container.forEach(new IntProcedure() {
|
||||
* int count; // this is a field declaration in an anonymous class.
|
||||
*
|
||||
* public void apply(int value) {
|
||||
* count++;
|
||||
* }
|
||||
* }).count;
|
||||
* </pre>
|
||||
*/
|
||||
public <T extends ByteProcedure> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a <code>predicate</code> to container elements as long, as the predicate returns <code>
|
||||
* true</code>. The iteration is interrupted otherwise.
|
||||
*/
|
||||
public <T extends BytePredicate> T forEach(T predicate);
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.ByteCursor;
|
||||
import com.carrotsearch.hppc.predicates.BytePredicate;
|
||||
import com.carrotsearch.hppc.procedures.ByteProcedure;
|
||||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* A linear collection that supports element insertion and removal at both ends.
|
||||
*
|
||||
* @see Deque
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeDeque.java")
|
||||
public interface ByteDeque extends ByteCollection {
|
||||
/**
|
||||
* Removes the first element that equals <code>e</code>.
|
||||
*
|
||||
* @return The deleted element's index or <code>-1</code> if the element was not found.
|
||||
*/
|
||||
public int removeFirst(byte e);
|
||||
|
||||
/**
|
||||
* Removes the last element that equals <code>e</code>.
|
||||
*
|
||||
* @return The deleted element's index or <code>-1</code> if the element was not found.
|
||||
*/
|
||||
public int removeLast(byte e);
|
||||
|
||||
/** Inserts the specified element at the front of this deque. */
|
||||
public void addFirst(byte e);
|
||||
|
||||
/** Inserts the specified element at the end of this deque. */
|
||||
public void addLast(byte e);
|
||||
|
||||
/**
|
||||
* Retrieves and removes the first element of this deque.
|
||||
*
|
||||
* @return the head (first) element of this deque.
|
||||
*/
|
||||
public byte removeFirst();
|
||||
|
||||
/**
|
||||
* Retrieves and removes the last element of this deque.
|
||||
*
|
||||
* @return the tail of this deque.
|
||||
*/
|
||||
public byte removeLast();
|
||||
|
||||
/**
|
||||
* Retrieves the first element of this deque but does not remove it.
|
||||
*
|
||||
* @return the head of this deque.
|
||||
*/
|
||||
public byte getFirst();
|
||||
|
||||
/**
|
||||
* Retrieves the last element of this deque but does not remove it.
|
||||
*
|
||||
* @return the head of this deque.
|
||||
*/
|
||||
public byte getLast();
|
||||
|
||||
/**
|
||||
* @return An iterator over elements in this deque in tail-to-head order.
|
||||
*/
|
||||
public Iterator<ByteCursor> descendingIterator();
|
||||
|
||||
/** Applies a <code>procedure</code> to all elements in tail-to-head order. */
|
||||
public <T extends ByteProcedure> T descendingForEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a <code>predicate</code> to container elements as long, as the predicate returns <code>
|
||||
* true</code>. The iteration is interrupted otherwise.
|
||||
*/
|
||||
public <T extends BytePredicate> T descendingForEach(T predicate);
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import java.util.RandomAccess;
|
||||
|
||||
/**
|
||||
* An indexed container provides random access to elements based on an <code>index</code>. Indexes
|
||||
* are zero-based.
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeIndexedContainer.java")
|
||||
public interface ByteIndexedContainer extends ByteCollection, RandomAccess {
|
||||
/**
|
||||
* Removes the first element that equals <code>e1</code>, returning whether an element has been
|
||||
* removed.
|
||||
*/
|
||||
public boolean removeElement(byte e1);
|
||||
|
||||
/**
|
||||
* Removes the first element that equals <code>e1</code>, returning its deleted position or <code>
|
||||
* -1</code> if the element was not found.
|
||||
*/
|
||||
public int removeFirst(byte e1);
|
||||
|
||||
/**
|
||||
* Removes the last element that equals <code>e1</code>, returning its deleted position or <code>
|
||||
* -1</code> if the element was not found.
|
||||
*/
|
||||
public int removeLast(byte e1);
|
||||
|
||||
/**
|
||||
* Returns the index of the first occurrence of the specified element in this list, or -1 if this
|
||||
* list does not contain the element.
|
||||
*/
|
||||
public int indexOf(byte e1);
|
||||
|
||||
/**
|
||||
* Returns the index of the last occurrence of the specified element in this list, or -1 if this
|
||||
* list does not contain the element.
|
||||
*/
|
||||
public int lastIndexOf(byte e1);
|
||||
|
||||
/** Adds an element to the end of this container (the last index is incremented by one). */
|
||||
public void add(byte e1);
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the specified position in this list.
|
||||
*
|
||||
* @param index The index at which the element should be inserted, shifting any existing and
|
||||
* subsequent elements to the right.
|
||||
*/
|
||||
public void insert(int index, byte e1);
|
||||
|
||||
/**
|
||||
* Replaces the element at the specified position in this list with the specified element.
|
||||
*
|
||||
* @return Returns the previous value in the list.
|
||||
*/
|
||||
public byte set(int index, byte e1);
|
||||
|
||||
/**
|
||||
* @return Returns the element at index <code>index</code> from the list.
|
||||
*/
|
||||
public byte get(int index);
|
||||
|
||||
/**
|
||||
* Removes the element at the specified position in this container and returns it.
|
||||
*
|
||||
* @see #removeFirst
|
||||
* @see #removeLast
|
||||
* @see #removeAll
|
||||
*/
|
||||
public byte removeAt(int index);
|
||||
|
||||
/** Removes and returns the last element of this container. This container must not be empty. */
|
||||
public byte removeLast();
|
||||
|
||||
/**
|
||||
* Removes from this container all of the elements with indexes between <code>fromIndex</code>,
|
||||
* inclusive, and <code>toIndex</code>, exclusive.
|
||||
*/
|
||||
public void removeRange(int fromIndex, int toIndex);
|
||||
|
||||
/** Returns this container elements as a stream. */
|
||||
|
||||
/** Sorts the elements in this container and returns this container. */
|
||||
public ByteIndexedContainer sort();
|
||||
|
||||
/** Reverses the elements in this container and returns this container. */
|
||||
public ByteIndexedContainer reverse();
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
/**
|
||||
* Marker interface for containers that can check if they contain a given object in at least time
|
||||
* <code>O(log n)</code> and ideally in amortized constant time <code>O(1)</code>.
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeLookupContainer.java")
|
||||
public interface ByteLookupContainer extends ByteContainer {
|
||||
public boolean contains(byte e);
|
||||
}
|
@ -1,137 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.ByteCursor;
|
||||
|
||||
/**
|
||||
* A subclass of {@link ByteArrayList} adding stack-related utility methods. The top of the stack is
|
||||
* at the <code>{@link #size()} - 1</code> element.
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeStack.java")
|
||||
public class ByteStack extends ByteArrayList {
|
||||
/** New instance with sane defaults. */
|
||||
public ByteStack() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
*/
|
||||
public ByteStack(int expectedElements) {
|
||||
super(expectedElements);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
* @param resizer Underlying buffer sizing strategy.
|
||||
*/
|
||||
public ByteStack(int expectedElements, ArraySizingStrategy resizer) {
|
||||
super(expectedElements, resizer);
|
||||
}
|
||||
|
||||
/** Create a stack by pushing all elements of another container to it. */
|
||||
public ByteStack(ByteContainer container) {
|
||||
super(container);
|
||||
}
|
||||
|
||||
/** Adds one byte to the stack. */
|
||||
public void push(byte e1) {
|
||||
ensureBufferSpace(1);
|
||||
buffer[elementsCount++] = e1;
|
||||
}
|
||||
|
||||
/** Adds two bytes to the stack. */
|
||||
public void push(byte e1, byte e2) {
|
||||
ensureBufferSpace(2);
|
||||
buffer[elementsCount++] = e1;
|
||||
buffer[elementsCount++] = e2;
|
||||
}
|
||||
|
||||
/** Adds three bytes to the stack. */
|
||||
public void push(byte e1, byte e2, byte e3) {
|
||||
ensureBufferSpace(3);
|
||||
buffer[elementsCount++] = e1;
|
||||
buffer[elementsCount++] = e2;
|
||||
buffer[elementsCount++] = e3;
|
||||
}
|
||||
|
||||
/** Adds four bytes to the stack. */
|
||||
public void push(byte e1, byte e2, byte e3, byte e4) {
|
||||
ensureBufferSpace(4);
|
||||
buffer[elementsCount++] = e1;
|
||||
buffer[elementsCount++] = e2;
|
||||
buffer[elementsCount++] = e3;
|
||||
buffer[elementsCount++] = e4;
|
||||
}
|
||||
|
||||
/** Add a range of array elements to the stack. */
|
||||
public void push(byte[] elements, int start, int len) {
|
||||
assert start >= 0 && len >= 0;
|
||||
|
||||
ensureBufferSpace(len);
|
||||
System.arraycopy(elements, start, buffer, elementsCount, len);
|
||||
elementsCount += len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg-signature method for pushing elements at the top of the stack.
|
||||
*
|
||||
* <p><b>This method is handy, but costly if used in tight loops (anonymous array passing)</b>
|
||||
*/
|
||||
public final void push(byte... elements) {
|
||||
push(elements, 0, elements.length);
|
||||
}
|
||||
|
||||
/** Pushes all elements from another container to the top of the stack. */
|
||||
public int pushAll(ByteContainer container) {
|
||||
return addAll(container);
|
||||
}
|
||||
|
||||
/** Pushes all elements from another iterable to the top of the stack. */
|
||||
public int pushAll(Iterable<? extends ByteCursor> iterable) {
|
||||
return addAll(iterable);
|
||||
}
|
||||
|
||||
/** Discard an arbitrary number of elements from the top of the stack. */
|
||||
public void discard(int count) {
|
||||
assert elementsCount >= count;
|
||||
|
||||
elementsCount -= count;
|
||||
}
|
||||
|
||||
/** Discard the top element from the stack. */
|
||||
public void discard() {
|
||||
assert elementsCount > 0;
|
||||
|
||||
elementsCount--;
|
||||
}
|
||||
|
||||
/** Remove the top element from the stack and return it. */
|
||||
public byte pop() {
|
||||
return removeLast();
|
||||
}
|
||||
|
||||
/** Peek at the top element on the stack. */
|
||||
public byte peek() {
|
||||
assert elementsCount > 0;
|
||||
return buffer[elementsCount - 1];
|
||||
}
|
||||
|
||||
/** Create a stack by pushing a variable number of arguments to it. */
|
||||
public static ByteStack from(byte... elements) {
|
||||
final ByteStack stack = new ByteStack(elements.length);
|
||||
stack.push(elements);
|
||||
return stack;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public ByteStack clone() {
|
||||
return (ByteStack) super.clone();
|
||||
}
|
||||
}
|
@ -1,776 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import static com.carrotsearch.hppc.Containers.*;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.CharCursor;
|
||||
import com.carrotsearch.hppc.predicates.CharPredicate;
|
||||
import com.carrotsearch.hppc.procedures.CharProcedure;
|
||||
import java.util.*;
|
||||
|
||||
/** An array-backed {@link CharDeque}. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeArrayDeque.java")
|
||||
public class CharArrayDeque extends AbstractCharCollection
|
||||
implements CharDeque, Preallocable, Cloneable, Accountable {
|
||||
|
||||
/** Reuse the same strategy instance. */
|
||||
private static final BoundedProportionalArraySizingStrategy DEFAULT_SIZING_STRATEGY =
|
||||
BoundedProportionalArraySizingStrategy.DEFAULT_INSTANCE;
|
||||
|
||||
/** Internal array for storing elements of the deque. */
|
||||
public char[] buffer = CharArrayList.EMPTY_ARRAY;
|
||||
|
||||
/**
|
||||
* The index of the element at the head of the deque or an arbitrary number equal to tail if the
|
||||
* deque is empty.
|
||||
*/
|
||||
public int head;
|
||||
|
||||
/** The index at which the next element would be added to the tail of the deque. */
|
||||
public int tail;
|
||||
|
||||
/** Buffer resizing strategy. */
|
||||
protected final ArraySizingStrategy resizer;
|
||||
|
||||
/** New instance with sane defaults. */
|
||||
public CharArrayDeque() {
|
||||
this(DEFAULT_EXPECTED_ELEMENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
*/
|
||||
public CharArrayDeque(int expectedElements) {
|
||||
this(expectedElements, DEFAULT_SIZING_STRATEGY);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
* @param resizer Underlying buffer sizing strategy.
|
||||
*/
|
||||
public CharArrayDeque(int expectedElements, ArraySizingStrategy resizer) {
|
||||
assert resizer != null;
|
||||
this.resizer = resizer;
|
||||
ensureCapacity(expectedElements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deque from elements of another container, appending elements at the end of the
|
||||
* deque in the iteration order.
|
||||
*/
|
||||
public CharArrayDeque(CharContainer container) {
|
||||
this(container.size());
|
||||
addLast(container);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void addFirst(char e1) {
|
||||
int h = oneLeft(head, buffer.length);
|
||||
if (h == tail) {
|
||||
ensureBufferSpace(1);
|
||||
h = oneLeft(head, buffer.length);
|
||||
}
|
||||
buffer[head = h] = e1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg-signature method for adding elements at the front of this deque.
|
||||
*
|
||||
* <p><b>This method is handy, but costly if used in tight loops (anonymous array passing)</b>
|
||||
*
|
||||
* @param elements The elements to add.
|
||||
*/
|
||||
public final void addFirst(char... elements) {
|
||||
ensureBufferSpace(elements.length);
|
||||
for (char k : elements) {
|
||||
addFirst(k);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given container to the front of this deque.
|
||||
*
|
||||
* @param container The container to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addFirst(CharContainer container) {
|
||||
int size = container.size();
|
||||
ensureBufferSpace(size);
|
||||
|
||||
for (CharCursor cursor : container) {
|
||||
addFirst(cursor.value);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given iterable to the front of this deque.
|
||||
*
|
||||
* @param iterable The iterable to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addFirst(Iterable<? extends CharCursor> iterable) {
|
||||
int size = 0;
|
||||
for (CharCursor cursor : iterable) {
|
||||
addFirst(cursor.value);
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void addLast(char e1) {
|
||||
int t = oneRight(tail, buffer.length);
|
||||
if (head == t) {
|
||||
ensureBufferSpace(1);
|
||||
t = oneRight(tail, buffer.length);
|
||||
}
|
||||
buffer[tail] = e1;
|
||||
tail = t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg-signature method for adding elements at the end of this deque.
|
||||
*
|
||||
* <p><b>This method is handy, but costly if used in tight loops (anonymous array passing)</b>
|
||||
*
|
||||
* @param elements The elements to iterate over.
|
||||
*/
|
||||
public final void addLast(char... elements) {
|
||||
ensureBufferSpace(1);
|
||||
for (char k : elements) {
|
||||
addLast(k);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given container to the end of this deque.
|
||||
*
|
||||
* @param container The container to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addLast(CharContainer container) {
|
||||
int size = container.size();
|
||||
ensureBufferSpace(size);
|
||||
|
||||
for (CharCursor cursor : container) {
|
||||
addLast(cursor.value);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given iterable to the end of this deque.
|
||||
*
|
||||
* @param iterable The iterable to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addLast(Iterable<? extends CharCursor> iterable) {
|
||||
int size = 0;
|
||||
for (CharCursor cursor : iterable) {
|
||||
addLast(cursor.value);
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public char removeFirst() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
final char result = buffer[head];
|
||||
buffer[head] = ((char) 0);
|
||||
head = oneRight(head, buffer.length);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public char removeLast() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
tail = oneLeft(tail, buffer.length);
|
||||
final char result = buffer[tail];
|
||||
buffer[tail] = ((char) 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public char getFirst() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
return buffer[head];
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public char getLast() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
return buffer[oneLeft(tail, buffer.length)];
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeFirst(char e1) {
|
||||
final int index = bufferIndexOf(e1);
|
||||
if (index >= 0) removeAtBufferIndex(index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index of the first (counting from head) element equal to <code>e1</code>. The index
|
||||
* points to the {@link #buffer} array.
|
||||
*
|
||||
* @param e1 The element to look for.
|
||||
* @return Returns the index of the first element equal to <code>e1</code> or <code>-1</code> if
|
||||
* not found.
|
||||
*/
|
||||
public int bufferIndexOf(char e1) {
|
||||
final int last = tail;
|
||||
final int bufLen = buffer.length;
|
||||
for (int i = head; i != last; i = oneRight(i, bufLen)) {
|
||||
if (((e1) == (buffer[i]))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeLast(char e1) {
|
||||
final int index = lastBufferIndexOf(e1);
|
||||
if (index >= 0) {
|
||||
removeAtBufferIndex(index);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index of the last (counting from tail) element equal to <code>e1</code>. The index
|
||||
* points to the {@link #buffer} array.
|
||||
*
|
||||
* @param e1 The element to look for.
|
||||
* @return Returns the index of the first element equal to <code>e1</code> or <code>-1</code> if
|
||||
* not found.
|
||||
*/
|
||||
public int lastBufferIndexOf(char e1) {
|
||||
final int bufLen = buffer.length;
|
||||
final int last = oneLeft(head, bufLen);
|
||||
for (int i = oneLeft(tail, bufLen); i != last; i = oneLeft(i, bufLen)) {
|
||||
if (((e1) == (buffer[i]))) return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(char e1) {
|
||||
int removed = 0;
|
||||
final int last = tail;
|
||||
final int bufLen = buffer.length;
|
||||
int from, to;
|
||||
for (from = to = head; from != last; from = oneRight(from, bufLen)) {
|
||||
if (((e1) == (buffer[from]))) {
|
||||
buffer[from] = ((char) 0);
|
||||
removed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = ((char) 0);
|
||||
}
|
||||
|
||||
to = oneRight(to, bufLen);
|
||||
}
|
||||
|
||||
tail = to;
|
||||
return removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the element at <code>index</code> in the internal {#link {@link #buffer} array,
|
||||
* returning its value.
|
||||
*
|
||||
* @param index Index of the element to remove. The index must be located between {@link #head}
|
||||
* and {@link #tail} in modulo {@link #buffer} arithmetic.
|
||||
*/
|
||||
public void removeAtBufferIndex(int index) {
|
||||
assert (head <= tail ? index >= head && index < tail : index >= head || index < tail)
|
||||
: "Index out of range (head=" + head + ", tail=" + tail + ", index=" + index + ").";
|
||||
|
||||
// Cache fields in locals (hopefully moved to registers).
|
||||
final char[] buffer = this.buffer;
|
||||
final int bufLen = buffer.length;
|
||||
final int lastIndex = bufLen - 1;
|
||||
final int head = this.head;
|
||||
final int tail = this.tail;
|
||||
|
||||
final int leftChunk = Math.abs(index - head) % bufLen;
|
||||
final int rightChunk = Math.abs(tail - index) % bufLen;
|
||||
|
||||
if (leftChunk < rightChunk) {
|
||||
if (index >= head) {
|
||||
System.arraycopy(buffer, head, buffer, head + 1, leftChunk);
|
||||
} else {
|
||||
System.arraycopy(buffer, 0, buffer, 1, index);
|
||||
buffer[0] = buffer[lastIndex];
|
||||
System.arraycopy(buffer, head, buffer, head + 1, lastIndex - head);
|
||||
}
|
||||
buffer[head] = ((char) 0);
|
||||
this.head = oneRight(head, bufLen);
|
||||
} else {
|
||||
if (index < tail) {
|
||||
System.arraycopy(buffer, index + 1, buffer, index, rightChunk);
|
||||
} else {
|
||||
System.arraycopy(buffer, index + 1, buffer, index, lastIndex - index);
|
||||
buffer[lastIndex] = buffer[0];
|
||||
System.arraycopy(buffer, 1, buffer, 0, tail);
|
||||
}
|
||||
buffer[tail] = ((char) 0);
|
||||
this.tail = oneLeft(tail, bufLen);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int size() {
|
||||
if (head <= tail) return tail - head;
|
||||
else return (tail - head + buffer.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The internal array buffers are not released as a result of this call.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
if (head < tail) {
|
||||
Arrays.fill(buffer, head, tail, ((char) 0));
|
||||
} else {
|
||||
Arrays.fill(buffer, 0, tail, ((char) 0));
|
||||
Arrays.fill(buffer, head, buffer.length, ((char) 0));
|
||||
}
|
||||
this.head = tail = 0;
|
||||
}
|
||||
|
||||
/** Release internal buffers of this deque and reallocate with the default buffer. */
|
||||
public void release() {
|
||||
this.head = tail = 0;
|
||||
buffer = CharArrayList.EMPTY_ARRAY;
|
||||
ensureBufferSpace(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure this container can hold at least the given number of elements without resizing its
|
||||
* buffers.
|
||||
*
|
||||
* @param expectedElements The total number of elements, inclusive.
|
||||
*/
|
||||
@Override
|
||||
public void ensureCapacity(int expectedElements) {
|
||||
ensureBufferSpace(expectedElements - size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the internal buffer has enough free slots to store <code>expectedAdditions</code>.
|
||||
* Increases internal buffer size if needed.
|
||||
*/
|
||||
protected void ensureBufferSpace(int expectedAdditions) {
|
||||
final int bufferLen = buffer.length;
|
||||
final int elementsCount = size();
|
||||
|
||||
if (elementsCount + expectedAdditions >= bufferLen) {
|
||||
final int emptySlot = 1; // deque invariant: always an empty slot.
|
||||
final int newSize = resizer.grow(bufferLen, elementsCount + emptySlot, expectedAdditions);
|
||||
assert newSize >= (elementsCount + expectedAdditions + emptySlot)
|
||||
: "Resizer failed to"
|
||||
+ " return sensible new size: "
|
||||
+ newSize
|
||||
+ " <= "
|
||||
+ (elementsCount + expectedAdditions);
|
||||
|
||||
try {
|
||||
final char[] newBuffer = (new char[newSize]);
|
||||
if (bufferLen > 0) {
|
||||
toArray(newBuffer);
|
||||
tail = elementsCount;
|
||||
head = 0;
|
||||
}
|
||||
this.buffer = newBuffer;
|
||||
} catch (OutOfMemoryError e) {
|
||||
throw new BufferAllocationException(
|
||||
"Not enough memory to allocate new buffers: %,d -> %,d", e, bufferLen, newSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public char[] toArray() {
|
||||
|
||||
final int size = size();
|
||||
return toArray((new char[size]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies elements of this deque to an array. The content of the <code>target</code> array is
|
||||
* filled from index 0 (head of the queue) to index <code>size() - 1</code> (tail of the queue).
|
||||
*
|
||||
* @param target The target array must be large enough to hold all elements.
|
||||
* @return Returns the target argument for chaining.
|
||||
*/
|
||||
public char[] toArray(char[] target) {
|
||||
assert target.length >= size() : "Target array must be >= " + size();
|
||||
|
||||
if (head < tail) {
|
||||
// The contents is not wrapped around. Just copy.
|
||||
System.arraycopy(buffer, head, target, 0, size());
|
||||
} else if (head > tail) {
|
||||
// The contents is split. Merge elements from the following indexes:
|
||||
// [head...buffer.length - 1][0, tail - 1]
|
||||
final int rightCount = buffer.length - head;
|
||||
System.arraycopy(buffer, head, target, 0, rightCount);
|
||||
System.arraycopy(buffer, 0, target, rightCount, tail);
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone this object. The returned clone will reuse the same hash function and array resizing
|
||||
* strategy.
|
||||
*/
|
||||
@Override
|
||||
public CharArrayDeque clone() {
|
||||
try {
|
||||
|
||||
CharArrayDeque cloned = (CharArrayDeque) super.clone();
|
||||
cloned.buffer = buffer.clone();
|
||||
return cloned;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Move one index to the left, wrapping around buffer. */
|
||||
protected static int oneLeft(int index, int modulus) {
|
||||
if (index >= 1) {
|
||||
return index - 1;
|
||||
}
|
||||
return modulus - 1;
|
||||
}
|
||||
|
||||
/** Move one index to the right, wrapping around buffer. */
|
||||
protected static int oneRight(int index, int modulus) {
|
||||
if (index + 1 == modulus) {
|
||||
return 0;
|
||||
}
|
||||
return index + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesAllocated() {
|
||||
// int: head, tail
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES * 2
|
||||
+ resizer.ramBytesAllocated()
|
||||
+ RamUsageEstimator.shallowSizeOfArray(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesUsed() {
|
||||
// int: head, tail
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES * 2
|
||||
+ resizer.ramBytesUsed()
|
||||
+ RamUsageEstimator.shallowUsedSizeOfArray(buffer, size());
|
||||
}
|
||||
|
||||
/** An iterator implementation for {@link ObjectArrayDeque#iterator}. */
|
||||
private final class ValueIterator extends AbstractIterator<CharCursor> {
|
||||
private final CharCursor cursor;
|
||||
private int remaining;
|
||||
|
||||
public ValueIterator() {
|
||||
cursor = new CharCursor();
|
||||
cursor.index = oneLeft(head, buffer.length);
|
||||
this.remaining = size();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CharCursor fetch() {
|
||||
if (remaining == 0) {
|
||||
return done();
|
||||
}
|
||||
|
||||
remaining--;
|
||||
cursor.value = buffer[cursor.index = oneRight(cursor.index, buffer.length)];
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
/** An iterator implementation for {@link ObjectArrayDeque#descendingIterator()}. */
|
||||
private final class DescendingValueIterator extends AbstractIterator<CharCursor> {
|
||||
private final CharCursor cursor;
|
||||
private int remaining;
|
||||
|
||||
public DescendingValueIterator() {
|
||||
cursor = new CharCursor();
|
||||
cursor.index = tail;
|
||||
this.remaining = size();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CharCursor fetch() {
|
||||
if (remaining == 0) return done();
|
||||
|
||||
remaining--;
|
||||
cursor.value = buffer[cursor.index = oneLeft(cursor.index, buffer.length)];
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a cursor over the values of this deque (in head to tail order). The iterator is
|
||||
* implemented as a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()} (to avoid boxing of primitive types). To read the current value (or index in
|
||||
* the deque's buffer) use the cursor's public fields. An example is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntValueCursor c : intDeque) {
|
||||
* System.out.println("buffer index=" + c.index + " value=" + c.value);
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public Iterator<CharCursor> iterator() {
|
||||
return new ValueIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a cursor over the values of this deque (in tail to head order). The iterator is
|
||||
* implemented as a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()} (to avoid boxing of primitive types). To read the current value (or index in
|
||||
* the deque's buffer) use the cursor's public fields. An example is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (Iterator<IntCursor> i = intDeque.descendingIterator(); i.hasNext();) {
|
||||
* final IntCursor c = i.next();
|
||||
* System.out.println("buffer index=" + c.index + " value=" + c.value);
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public Iterator<CharCursor> descendingIterator() {
|
||||
return new DescendingValueIterator();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends CharProcedure> T forEach(T procedure) {
|
||||
forEach(procedure, head, tail);
|
||||
return procedure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>procedure</code> to a slice of the deque, <code>fromIndex</code>, inclusive, to
|
||||
* <code>toIndex</code>, exclusive.
|
||||
*/
|
||||
private void forEach(CharProcedure procedure, int fromIndex, final int toIndex) {
|
||||
final char[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
procedure.apply(buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends CharPredicate> T forEach(T predicate) {
|
||||
int fromIndex = head;
|
||||
int toIndex = tail;
|
||||
|
||||
final char[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
if (!predicate.apply(buffer[i])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return predicate;
|
||||
}
|
||||
|
||||
/** Applies <code>procedure</code> to all elements of this deque, tail to head. */
|
||||
@Override
|
||||
public <T extends CharProcedure> T descendingForEach(T procedure) {
|
||||
descendingForEach(procedure, head, tail);
|
||||
return procedure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>procedure</code> to a slice of the deque, <code>toIndex</code>, exclusive, down
|
||||
* to <code>fromIndex</code>, inclusive.
|
||||
*/
|
||||
private void descendingForEach(CharProcedure procedure, int fromIndex, final int toIndex) {
|
||||
if (fromIndex == toIndex) return;
|
||||
|
||||
final char[] buffer = this.buffer;
|
||||
int i = toIndex;
|
||||
do {
|
||||
i = oneLeft(i, buffer.length);
|
||||
procedure.apply(buffer[i]);
|
||||
} while (i != fromIndex);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends CharPredicate> T descendingForEach(T predicate) {
|
||||
descendingForEach(predicate, head, tail);
|
||||
return predicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>predicate</code> to a slice of the deque, <code>toIndex</code>, exclusive, down
|
||||
* to <code>fromIndex</code>, inclusive or until the predicate returns <code>false</code>.
|
||||
*/
|
||||
private void descendingForEach(CharPredicate predicate, int fromIndex, final int toIndex) {
|
||||
if (fromIndex == toIndex) return;
|
||||
|
||||
final char[] buffer = this.buffer;
|
||||
int i = toIndex;
|
||||
do {
|
||||
i = oneLeft(i, buffer.length);
|
||||
if (!predicate.apply(buffer[i])) {
|
||||
break;
|
||||
}
|
||||
} while (i != fromIndex);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(CharPredicate predicate) {
|
||||
final char[] buffer = this.buffer;
|
||||
final int last = tail;
|
||||
final int bufLen = buffer.length;
|
||||
int removed = 0;
|
||||
int from, to;
|
||||
from = to = head;
|
||||
try {
|
||||
for (from = to = head; from != last; from = oneRight(from, bufLen)) {
|
||||
if (predicate.apply(buffer[from])) {
|
||||
buffer[from] = ((char) 0);
|
||||
removed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = ((char) 0);
|
||||
}
|
||||
|
||||
to = oneRight(to, bufLen);
|
||||
}
|
||||
} finally {
|
||||
// Keep the deque in consistent state even if the predicate throws an exception.
|
||||
for (; from != last; from = oneRight(from, bufLen)) {
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = ((char) 0);
|
||||
}
|
||||
|
||||
to = oneRight(to, bufLen);
|
||||
}
|
||||
tail = to;
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean contains(char e) {
|
||||
int fromIndex = head;
|
||||
int toIndex = tail;
|
||||
|
||||
final char[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
if (((e) == (buffer[i]))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = 1;
|
||||
int fromIndex = head;
|
||||
int toIndex = tail;
|
||||
|
||||
final char[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
h = 31 * h + BitMixer.mix(this.buffer[i]);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> only if the other object is an instance of the same class and with
|
||||
* the same elements.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return (this == obj)
|
||||
|| (obj != null && getClass() == obj.getClass() && equalElements(getClass().cast(obj)));
|
||||
}
|
||||
|
||||
/** Compare order-aligned elements against another {@link CharDeque}. */
|
||||
protected boolean equalElements(CharArrayDeque other) {
|
||||
int max = size();
|
||||
if (other.size() != max) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Iterator<CharCursor> i1 = this.iterator();
|
||||
Iterator<? extends CharCursor> i2 = other.iterator();
|
||||
|
||||
while (i1.hasNext() && i2.hasNext()) {
|
||||
if (!((i1.next().value) == (i2.next().value))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return !i1.hasNext() && !i2.hasNext();
|
||||
}
|
||||
|
||||
/** Create a new deque by pushing a variable number of arguments to the end of it. */
|
||||
public static CharArrayDeque from(char... elements) {
|
||||
final CharArrayDeque coll = new CharArrayDeque(elements.length);
|
||||
coll.addLast(elements);
|
||||
return coll;
|
||||
}
|
||||
}
|
@ -1,579 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import static com.carrotsearch.hppc.Containers.*;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.CharPredicate;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.*;
|
||||
|
||||
/** An array-backed list of chars. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeArrayList.java")
|
||||
public class CharArrayList extends AbstractCharCollection
|
||||
implements CharIndexedContainer, Preallocable, Cloneable, Accountable {
|
||||
/** An immutable empty buffer (array). */
|
||||
public static final char[] EMPTY_ARRAY = new char[0];
|
||||
|
||||
;
|
||||
|
||||
/** Reuse the same strategy instance. */
|
||||
private static final BoundedProportionalArraySizingStrategy DEFAULT_SIZING_STRATEGY =
|
||||
BoundedProportionalArraySizingStrategy.DEFAULT_INSTANCE;
|
||||
|
||||
/**
|
||||
* Internal array for storing the list. The array may be larger than the current size ({@link
|
||||
* #size()}).
|
||||
*/
|
||||
public char[] buffer = EMPTY_ARRAY;
|
||||
|
||||
/** Current number of elements stored in {@link #buffer}. */
|
||||
public int elementsCount;
|
||||
|
||||
/** Buffer resizing strategy. */
|
||||
protected final ArraySizingStrategy resizer;
|
||||
|
||||
/** New instance with sane defaults. */
|
||||
public CharArrayList() {
|
||||
this(DEFAULT_EXPECTED_ELEMENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
*/
|
||||
public CharArrayList(int expectedElements) {
|
||||
this(expectedElements, DEFAULT_SIZING_STRATEGY);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
* @param resizer Underlying buffer sizing strategy.
|
||||
*/
|
||||
public CharArrayList(int expectedElements, ArraySizingStrategy resizer) {
|
||||
assert resizer != null;
|
||||
this.resizer = resizer;
|
||||
buffer = Arrays.copyOf(buffer, expectedElements);
|
||||
}
|
||||
|
||||
/** Creates a new list from the elements of another container in its iteration order. */
|
||||
public CharArrayList(CharContainer container) {
|
||||
this(container.size());
|
||||
addAll(container);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void add(char e1) {
|
||||
ensureBufferSpace(1);
|
||||
buffer[elementsCount++] = e1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends two elements at the end of the list. To add more than two elements, use <code>add
|
||||
* </code> (vararg-version) or access the buffer directly (tight loop).
|
||||
*/
|
||||
public void add(char e1, char e2) {
|
||||
ensureBufferSpace(2);
|
||||
buffer[elementsCount++] = e1;
|
||||
buffer[elementsCount++] = e2;
|
||||
}
|
||||
|
||||
/** Add all elements from a range of given array to the list. */
|
||||
public void add(char[] elements, int start, int length) {
|
||||
assert length >= 0 : "Length must be >= 0";
|
||||
|
||||
ensureBufferSpace(length);
|
||||
System.arraycopy(elements, start, buffer, elementsCount, length);
|
||||
elementsCount += length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg-signature method for adding elements at the end of the list.
|
||||
*
|
||||
* <p><b>This method is handy, but costly if used in tight loops (anonymous array passing)</b>
|
||||
*/
|
||||
public final void add(char... elements) {
|
||||
add(elements, 0, elements.length);
|
||||
}
|
||||
|
||||
/** Adds all elements from another container. */
|
||||
public int addAll(CharContainer container) {
|
||||
final int size = container.size();
|
||||
ensureBufferSpace(size);
|
||||
|
||||
for (CharCursor cursor : container) {
|
||||
add(cursor.value);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/** Adds all elements from another iterable. */
|
||||
public int addAll(Iterable<? extends CharCursor> iterable) {
|
||||
int size = 0;
|
||||
for (CharCursor cursor : iterable) {
|
||||
add(cursor.value);
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void insert(int index, char e1) {
|
||||
assert (index >= 0 && index <= size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
|
||||
ensureBufferSpace(1);
|
||||
System.arraycopy(buffer, index, buffer, index + 1, elementsCount - index);
|
||||
buffer[index] = e1;
|
||||
elementsCount++;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public char get(int index) {
|
||||
assert (index >= 0 && index < size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
return buffer[index];
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public char set(int index, char e1) {
|
||||
assert (index >= 0 && index < size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
final char v = buffer[index];
|
||||
buffer[index] = e1;
|
||||
return v;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public char removeAt(int index) {
|
||||
assert (index >= 0 && index < size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
final char v = buffer[index];
|
||||
System.arraycopy(buffer, index + 1, buffer, index, --elementsCount - index);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public char removeLast() {
|
||||
assert elementsCount > 0;
|
||||
|
||||
final char v = buffer[--elementsCount];
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void removeRange(int fromIndex, int toIndex) {
|
||||
assert (fromIndex >= 0 && fromIndex <= size())
|
||||
: "Index " + fromIndex + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
assert (toIndex >= 0 && toIndex <= size())
|
||||
: "Index " + toIndex + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
assert fromIndex <= toIndex : "fromIndex must be <= toIndex: " + fromIndex + ", " + toIndex;
|
||||
|
||||
System.arraycopy(buffer, toIndex, buffer, fromIndex, elementsCount - toIndex);
|
||||
final int count = toIndex - fromIndex;
|
||||
elementsCount -= count;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean removeElement(char e1) {
|
||||
return removeFirst(e1) != -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeFirst(char e1) {
|
||||
final int index = indexOf(e1);
|
||||
if (index >= 0) removeAt(index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeLast(char e1) {
|
||||
final int index = lastIndexOf(e1);
|
||||
if (index >= 0) removeAt(index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(char e1) {
|
||||
int to = 0;
|
||||
for (int from = 0; from < elementsCount; from++) {
|
||||
if (((e1) == (buffer[from]))) {
|
||||
continue;
|
||||
}
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
}
|
||||
to++;
|
||||
}
|
||||
final int deleted = elementsCount - to;
|
||||
this.elementsCount = to;
|
||||
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean contains(char e1) {
|
||||
return indexOf(e1) >= 0;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int indexOf(char e1) {
|
||||
for (int i = 0; i < elementsCount; i++) {
|
||||
if (((e1) == (buffer[i]))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int lastIndexOf(char e1) {
|
||||
for (int i = elementsCount - 1; i >= 0; i--) {
|
||||
if (((e1) == (buffer[i]))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return elementsCount == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure this container can hold at least the given number of elements without resizing its
|
||||
* buffers.
|
||||
*
|
||||
* @param expectedElements The total number of elements, inclusive.
|
||||
*/
|
||||
@Override
|
||||
public void ensureCapacity(int expectedElements) {
|
||||
final int bufferLen = (buffer == null ? 0 : buffer.length);
|
||||
if (expectedElements > bufferLen) {
|
||||
ensureBufferSpace(expectedElements - size());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the internal buffer has enough free slots to store <code>expectedAdditions</code>.
|
||||
* Increases internal buffer size if needed.
|
||||
*/
|
||||
protected void ensureBufferSpace(int expectedAdditions) {
|
||||
final int bufferLen = (buffer == null ? 0 : buffer.length);
|
||||
if (elementsCount + expectedAdditions > bufferLen) {
|
||||
final int newSize = resizer.grow(bufferLen, elementsCount, expectedAdditions);
|
||||
assert newSize >= elementsCount + expectedAdditions
|
||||
: "Resizer failed to"
|
||||
+ " return sensible new size: "
|
||||
+ newSize
|
||||
+ " <= "
|
||||
+ (elementsCount + expectedAdditions);
|
||||
|
||||
this.buffer = Arrays.copyOf(buffer, newSize);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate or expand the list to the new size. If the list is truncated, the buffer will not be
|
||||
* reallocated (use {@link #trimToSize()} if you need a truncated buffer), but the truncated
|
||||
* values will be reset to the default value (zero). If the list is expanded, the elements beyond
|
||||
* the current size are initialized with JVM-defaults (zero or <code>null</code> values).
|
||||
*/
|
||||
public void resize(int newSize) {
|
||||
if (newSize <= buffer.length) {
|
||||
if (newSize < elementsCount) {
|
||||
Arrays.fill(buffer, newSize, elementsCount, ((char) 0));
|
||||
} else {
|
||||
Arrays.fill(buffer, elementsCount, newSize, ((char) 0));
|
||||
}
|
||||
} else {
|
||||
ensureCapacity(newSize);
|
||||
}
|
||||
this.elementsCount = newSize;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int size() {
|
||||
return elementsCount;
|
||||
}
|
||||
|
||||
/** Trim the internal buffer to the current size. */
|
||||
public void trimToSize() {
|
||||
if (size() != this.buffer.length) {
|
||||
this.buffer = toArray();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of stored elements to zero. Releases and initializes the internal storage array
|
||||
* to default values. To clear the list without cleaning the buffer, simply set the {@link
|
||||
* #elementsCount} field to zero.
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
Arrays.fill(buffer, 0, elementsCount, ((char) 0));
|
||||
this.elementsCount = 0;
|
||||
}
|
||||
|
||||
/** Sets the number of stored elements to zero and releases the internal storage array. */
|
||||
@Override
|
||||
public void release() {
|
||||
this.buffer = EMPTY_ARRAY;
|
||||
this.elementsCount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The returned array is sized to match exactly the number of elements of the stack.
|
||||
*/
|
||||
@Override
|
||||
public char[] toArray() {
|
||||
|
||||
return Arrays.copyOf(buffer, elementsCount);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public CharIndexedContainer sort() {
|
||||
Arrays.sort(buffer, 0, elementsCount);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public CharIndexedContainer reverse() {
|
||||
for (int i = 0, mid = elementsCount >> 1, j = elementsCount - 1; i < mid; i++, j--) {
|
||||
char tmp = buffer[i];
|
||||
buffer[i] = buffer[j];
|
||||
buffer[j] = tmp;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone this object. The returned clone will reuse the same hash function and array resizing
|
||||
* strategy.
|
||||
*/
|
||||
@Override
|
||||
public CharArrayList clone() {
|
||||
try {
|
||||
|
||||
final CharArrayList cloned = (CharArrayList) super.clone();
|
||||
cloned.buffer = buffer.clone();
|
||||
return cloned;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = 1, max = elementsCount;
|
||||
for (int i = 0; i < max; i++) {
|
||||
h = 31 * h + BitMixer.mix(this.buffer[i]);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> only if the other object is an instance of the same class and with
|
||||
* the same elements.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return (this == obj)
|
||||
|| (obj != null && getClass() == obj.getClass() && equalElements(getClass().cast(obj)));
|
||||
}
|
||||
|
||||
/** Compare index-aligned elements against another {@link CharIndexedContainer}. */
|
||||
protected boolean equalElements(CharArrayList other) {
|
||||
int max = size();
|
||||
if (other.size() != max) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < max; i++) {
|
||||
if (!((get(i)) == (other.get(i)))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesAllocated() {
|
||||
// int: elementsCount
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES
|
||||
+ resizer.ramBytesAllocated()
|
||||
+ RamUsageEstimator.shallowSizeOfArray(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesUsed() {
|
||||
// int: elementsCount
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES
|
||||
+ resizer.ramBytesUsed()
|
||||
+ RamUsageEstimator.shallowUsedSizeOfArray(buffer, elementsCount);
|
||||
}
|
||||
|
||||
/** An iterator implementation for {@link CharArrayList#iterator}. */
|
||||
static final class ValueIterator extends AbstractIterator<CharCursor> {
|
||||
private final CharCursor cursor;
|
||||
|
||||
private final char[] buffer;
|
||||
private final int size;
|
||||
|
||||
public ValueIterator(char[] buffer, int size) {
|
||||
this.cursor = new CharCursor();
|
||||
this.cursor.index = -1;
|
||||
this.size = size;
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CharCursor fetch() {
|
||||
if (cursor.index + 1 == size) return done();
|
||||
|
||||
cursor.value = buffer[++cursor.index];
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public Iterator<CharCursor> iterator() {
|
||||
return new ValueIterator(buffer, size());
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends CharProcedure> T forEach(T procedure) {
|
||||
return forEach(procedure, 0, size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>procedure</code> to a slice of the list, <code>fromIndex</code>, inclusive, to
|
||||
* <code>toIndex</code>, exclusive.
|
||||
*/
|
||||
public <T extends CharProcedure> T forEach(T procedure, int fromIndex, final int toIndex) {
|
||||
assert (fromIndex >= 0 && fromIndex <= size())
|
||||
: "Index " + fromIndex + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
assert (toIndex >= 0 && toIndex <= size())
|
||||
: "Index " + toIndex + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
|
||||
assert fromIndex <= toIndex : "fromIndex must be <= toIndex: " + fromIndex + ", " + toIndex;
|
||||
|
||||
final char[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i < toIndex; i++) {
|
||||
procedure.apply(buffer[i]);
|
||||
}
|
||||
|
||||
return procedure;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(CharPredicate predicate) {
|
||||
final char[] buffer = this.buffer;
|
||||
final int elementsCount = this.elementsCount;
|
||||
int to = 0;
|
||||
int from = 0;
|
||||
try {
|
||||
for (; from < elementsCount; from++) {
|
||||
if (predicate.apply(buffer[from])) {
|
||||
buffer[from] = ((char) 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = ((char) 0);
|
||||
}
|
||||
to++;
|
||||
}
|
||||
} finally {
|
||||
// Keep the list in a consistent state, even if the predicate throws an exception.
|
||||
for (; from < elementsCount; from++) {
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = ((char) 0);
|
||||
}
|
||||
to++;
|
||||
}
|
||||
|
||||
this.elementsCount = to;
|
||||
}
|
||||
|
||||
return elementsCount - to;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends CharPredicate> T forEach(T predicate) {
|
||||
return forEach(predicate, 0, size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>predicate</code> to a slice of the list, <code>fromIndex</code>, inclusive, to
|
||||
* <code>toIndex</code>, exclusive, or until predicate returns <code>false</code>.
|
||||
*/
|
||||
public <T extends CharPredicate> T forEach(T predicate, int fromIndex, final int toIndex) {
|
||||
assert (fromIndex >= 0 && fromIndex <= size())
|
||||
: "Index " + fromIndex + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
assert (toIndex >= 0 && toIndex <= size())
|
||||
: "Index " + toIndex + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
assert fromIndex <= toIndex : "fromIndex must be <= toIndex: " + fromIndex + ", " + toIndex;
|
||||
|
||||
final char[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i < toIndex; i++) {
|
||||
if (!predicate.apply(buffer[i])) break;
|
||||
}
|
||||
|
||||
return predicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a list from a variable number of arguments or an array of <code>char</code>. The
|
||||
* elements are copied from the argument to the internal buffer.
|
||||
*/
|
||||
public static CharArrayList from(char... elements) {
|
||||
final CharArrayList list = new CharArrayList(elements.length);
|
||||
list.add(elements);
|
||||
return list;
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
/**
|
||||
* Reused buffer visualization routines.
|
||||
*
|
||||
* @see CharSet#visualizeKeyDistribution(int)
|
||||
* @see CharVTypeMap#visualizeKeyDistribution(int)
|
||||
*/
|
||||
class CharBufferVisualizer {
|
||||
static String visualizeKeyDistribution(char[] buffer, int max, int characters) {
|
||||
final StringBuilder b = new StringBuilder();
|
||||
final char[] chars = ".123456789X".toCharArray();
|
||||
for (int i = 1, start = -1; i <= characters; i++) {
|
||||
int end = (int) ((long) i * max / characters);
|
||||
|
||||
if (start + 1 <= end) {
|
||||
int taken = 0;
|
||||
int slots = 0;
|
||||
for (int slot = start + 1; slot <= end; slot++, slots++) {
|
||||
if (!((buffer[slot]) == 0)) {
|
||||
taken++;
|
||||
}
|
||||
}
|
||||
b.append(chars[Math.min(chars.length - 1, taken * chars.length / slots)]);
|
||||
start = end;
|
||||
}
|
||||
}
|
||||
while (b.length() < characters) {
|
||||
b.append(' ');
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.*;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* An associative container from keys to (one or possibly more) values.
|
||||
*
|
||||
* @see CharContainer
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeVTypeAssociativeContainer.java")
|
||||
public interface CharByteAssociativeContainer extends Iterable<CharByteCursor> {
|
||||
/**
|
||||
* Returns a cursor over the entries (key-value pairs) in this map. The iterator is implemented as
|
||||
* a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()}. To read the current key and value use the cursor's public fields. An example
|
||||
* is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntShortCursor c : intShortMap) {
|
||||
* System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
|
||||
* }</pre>
|
||||
*
|
||||
* <p>The <code>index</code> field inside the cursor gives the internal index inside the
|
||||
* container's implementation. The interpretation of this index depends on to the container.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<CharByteCursor> iterator();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this container has an association to a value for the given key.
|
||||
*/
|
||||
public boolean containsKey(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the current size (number of assigned keys) in the container.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/**
|
||||
* @return Return <code>true</code> if this hash map contains no assigned keys.
|
||||
*/
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) present in a given container. An alias to:
|
||||
*
|
||||
* <pre>
|
||||
* keys().removeAll(container)
|
||||
* </pre>
|
||||
*
|
||||
* but with no additional overhead.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharContainer container);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharPredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharBytePredicate predicate);
|
||||
|
||||
/**
|
||||
* Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharByteProcedure}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*/
|
||||
public <T extends CharByteProcedure> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a given predicate to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharBytePredicate}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*
|
||||
* <p>The iteration is continued as long as the predicate returns <code>true</code>.
|
||||
*/
|
||||
public <T extends CharBytePredicate> T forEach(T predicate);
|
||||
|
||||
/**
|
||||
* Returns a collection of keys of this container. The returned collection is a view over the key
|
||||
* set and any modifications (if allowed) introduced to the collection will propagate to the
|
||||
* associative container immediately.
|
||||
*/
|
||||
public CharCollection keys();
|
||||
|
||||
/**
|
||||
* Returns a container view of all values present in this container. The returned collection is a
|
||||
* view over the key set and any modifications (if allowed) introduced to the collection will
|
||||
* propagate to the associative container immediately.
|
||||
*/
|
||||
public ByteContainer values();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,205 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.CharByteCursor;
|
||||
|
||||
/** An associative container with unique binding from keys to a single value. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeVTypeMap.java")
|
||||
public interface CharByteMap extends CharByteAssociativeContainer {
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the default value for the value
|
||||
* type, if the key is not associated with any value. For numeric value types, this default
|
||||
* value is 0, for object types it is {@code null}.
|
||||
*/
|
||||
public byte get(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the provided default value if the
|
||||
* key is not associated with any value.
|
||||
*/
|
||||
public byte getOrDefault(char key, byte defaultValue);
|
||||
|
||||
/**
|
||||
* Place a given key and value in the container.
|
||||
*
|
||||
* @return The value previously stored under the given key in the map is returned.
|
||||
*/
|
||||
public byte put(char key, byte value);
|
||||
|
||||
/**
|
||||
* If the specified key is not already associated with a value, associates it with the given
|
||||
* value.
|
||||
*
|
||||
* @return {@code true} if {@code key} did not exist and {@code value} was placed in the map,
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
public default boolean putIfAbsent(char key, byte value) {
|
||||
int keyIndex = indexOf(key);
|
||||
if (indexExists(keyIndex)) {
|
||||
return false;
|
||||
} else {
|
||||
indexInsert(keyIndex, key, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts all keys from another container to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(CharByteAssociativeContainer container);
|
||||
|
||||
/**
|
||||
* Puts all keys from an iterable cursor to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(Iterable<? extends CharByteCursor> iterable);
|
||||
|
||||
/**
|
||||
* If <code>key</code> exists, <code>putValue</code> is inserted into the map, otherwise any
|
||||
* existing value is incremented by <code>additionValue</code>.
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param putValue The value to put if <code>key</code> does not exist.
|
||||
* @param incrementValue The value to add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public byte putOrAdd(char key, byte putValue, byte incrementValue);
|
||||
|
||||
/**
|
||||
* An equivalent of calling
|
||||
*
|
||||
* <pre>
|
||||
* putOrAdd(key, additionValue, additionValue);
|
||||
* </pre>
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param additionValue The value to put or add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public byte addTo(char key, byte additionValue);
|
||||
|
||||
/**
|
||||
* Remove all values at the given key. The default value for the key type is returned if the value
|
||||
* does not exist in the map.
|
||||
*/
|
||||
public byte remove(char key);
|
||||
|
||||
/**
|
||||
* Compares the specified object with this set for equality. Returns {@code true} if and only if
|
||||
* the specified object is also a {@link CharByteMap} and both objects contains exactly the same
|
||||
* key-value pairs.
|
||||
*/
|
||||
public boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* @return A hash code of elements stored in the map. The hash code is defined as a sum of hash
|
||||
* codes of keys and values stored within the set). Because sum is commutative, this ensures
|
||||
* that different order of elements in a set does not affect the hash code.
|
||||
*/
|
||||
public int hashCode();
|
||||
|
||||
/**
|
||||
* Returns a logical "index" of a given key that can be used to speed up follow-up value setters
|
||||
* or getters in certain scenarios (conditional logic).
|
||||
*
|
||||
* <p>The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
|
||||
* contiguous.
|
||||
*
|
||||
* <p>The index is valid only between map modifications (it will not be affected by read-only
|
||||
* operations like iteration or value retrievals).
|
||||
*
|
||||
* @see #indexExists
|
||||
* @see #indexGet
|
||||
* @see #indexInsert
|
||||
* @see #indexReplace
|
||||
* @param key The key to locate in the map.
|
||||
* @return A non-negative value of the logical "index" of the key in the map or a negative value
|
||||
* if the key did not exist.
|
||||
*/
|
||||
public int indexOf(char key);
|
||||
|
||||
/**
|
||||
* @see #indexOf
|
||||
* @param index The index of a given key, as returned from {@link #indexOf}.
|
||||
* @return Returns <code>true</code> if the index corresponds to an existing key or false
|
||||
* otherwise. This is equivalent to checking whether the index is a positive value (existing
|
||||
* keys) or a negative value (non-existing keys).
|
||||
*/
|
||||
public boolean indexExists(int index);
|
||||
|
||||
/**
|
||||
* Returns the value associated with an existing key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the value currently associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public byte indexGet(int index);
|
||||
|
||||
/**
|
||||
* Replaces the value associated with an existing key and returns any previous value stored for
|
||||
* that key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public byte indexReplace(int index, byte newValue);
|
||||
|
||||
/**
|
||||
* Inserts a key-value pair for a key that is not present in the map. This method may help in
|
||||
* avoiding double recalculation of the key's hash.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
|
||||
* @throws AssertionError If assertions are enabled and the index corresponds to an existing key.
|
||||
*/
|
||||
public void indexInsert(int index, char key, byte value);
|
||||
|
||||
/**
|
||||
* Removes a key-value pair at an index previously acquired from {@link #indexOf}.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of the key to remove, as returned from {@link #indexOf}.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public byte indexRemove(int index);
|
||||
|
||||
/**
|
||||
* Clear all keys and values in the container.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Removes all elements from the collection and additionally releases any internal buffers.
|
||||
* Typically, if the object is to be reused, a simple {@link #clear()} should be a better
|
||||
* alternative since it'll avoid reallocation.
|
||||
*
|
||||
* @see #clear()
|
||||
*/
|
||||
public void release();
|
||||
|
||||
/**
|
||||
* Visually depict the distribution of keys.
|
||||
*
|
||||
* @param characters The number of characters to "squeeze" the entire buffer into.
|
||||
* @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
|
||||
* buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
|
||||
* between 1 and 9 is between.
|
||||
*/
|
||||
public String visualizeKeyDistribution(int characters);
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.*;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* An associative container from keys to (one or possibly more) values.
|
||||
*
|
||||
* @see CharContainer
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeVTypeAssociativeContainer.java")
|
||||
public interface CharCharAssociativeContainer extends Iterable<CharCharCursor> {
|
||||
/**
|
||||
* Returns a cursor over the entries (key-value pairs) in this map. The iterator is implemented as
|
||||
* a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()}. To read the current key and value use the cursor's public fields. An example
|
||||
* is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntShortCursor c : intShortMap) {
|
||||
* System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
|
||||
* }</pre>
|
||||
*
|
||||
* <p>The <code>index</code> field inside the cursor gives the internal index inside the
|
||||
* container's implementation. The interpretation of this index depends on to the container.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<CharCharCursor> iterator();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this container has an association to a value for the given key.
|
||||
*/
|
||||
public boolean containsKey(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the current size (number of assigned keys) in the container.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/**
|
||||
* @return Return <code>true</code> if this hash map contains no assigned keys.
|
||||
*/
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) present in a given container. An alias to:
|
||||
*
|
||||
* <pre>
|
||||
* keys().removeAll(container)
|
||||
* </pre>
|
||||
*
|
||||
* but with no additional overhead.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharContainer container);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharPredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharCharPredicate predicate);
|
||||
|
||||
/**
|
||||
* Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharCharProcedure}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*/
|
||||
public <T extends CharCharProcedure> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a given predicate to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharCharPredicate}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*
|
||||
* <p>The iteration is continued as long as the predicate returns <code>true</code>.
|
||||
*/
|
||||
public <T extends CharCharPredicate> T forEach(T predicate);
|
||||
|
||||
/**
|
||||
* Returns a collection of keys of this container. The returned collection is a view over the key
|
||||
* set and any modifications (if allowed) introduced to the collection will propagate to the
|
||||
* associative container immediately.
|
||||
*/
|
||||
public CharCollection keys();
|
||||
|
||||
/**
|
||||
* Returns a container view of all values present in this container. The returned collection is a
|
||||
* view over the key set and any modifications (if allowed) introduced to the collection will
|
||||
* propagate to the associative container immediately.
|
||||
*/
|
||||
public CharContainer values();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,205 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.CharCharCursor;
|
||||
|
||||
/** An associative container with unique binding from keys to a single value. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeVTypeMap.java")
|
||||
public interface CharCharMap extends CharCharAssociativeContainer {
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the default value for the value
|
||||
* type, if the key is not associated with any value. For numeric value types, this default
|
||||
* value is 0, for object types it is {@code null}.
|
||||
*/
|
||||
public char get(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the provided default value if the
|
||||
* key is not associated with any value.
|
||||
*/
|
||||
public char getOrDefault(char key, char defaultValue);
|
||||
|
||||
/**
|
||||
* Place a given key and value in the container.
|
||||
*
|
||||
* @return The value previously stored under the given key in the map is returned.
|
||||
*/
|
||||
public char put(char key, char value);
|
||||
|
||||
/**
|
||||
* If the specified key is not already associated with a value, associates it with the given
|
||||
* value.
|
||||
*
|
||||
* @return {@code true} if {@code key} did not exist and {@code value} was placed in the map,
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
public default boolean putIfAbsent(char key, char value) {
|
||||
int keyIndex = indexOf(key);
|
||||
if (indexExists(keyIndex)) {
|
||||
return false;
|
||||
} else {
|
||||
indexInsert(keyIndex, key, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts all keys from another container to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(CharCharAssociativeContainer container);
|
||||
|
||||
/**
|
||||
* Puts all keys from an iterable cursor to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(Iterable<? extends CharCharCursor> iterable);
|
||||
|
||||
/**
|
||||
* If <code>key</code> exists, <code>putValue</code> is inserted into the map, otherwise any
|
||||
* existing value is incremented by <code>additionValue</code>.
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param putValue The value to put if <code>key</code> does not exist.
|
||||
* @param incrementValue The value to add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public char putOrAdd(char key, char putValue, char incrementValue);
|
||||
|
||||
/**
|
||||
* An equivalent of calling
|
||||
*
|
||||
* <pre>
|
||||
* putOrAdd(key, additionValue, additionValue);
|
||||
* </pre>
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param additionValue The value to put or add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public char addTo(char key, char additionValue);
|
||||
|
||||
/**
|
||||
* Remove all values at the given key. The default value for the key type is returned if the value
|
||||
* does not exist in the map.
|
||||
*/
|
||||
public char remove(char key);
|
||||
|
||||
/**
|
||||
* Compares the specified object with this set for equality. Returns {@code true} if and only if
|
||||
* the specified object is also a {@link CharCharMap} and both objects contains exactly the same
|
||||
* key-value pairs.
|
||||
*/
|
||||
public boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* @return A hash code of elements stored in the map. The hash code is defined as a sum of hash
|
||||
* codes of keys and values stored within the set). Because sum is commutative, this ensures
|
||||
* that different order of elements in a set does not affect the hash code.
|
||||
*/
|
||||
public int hashCode();
|
||||
|
||||
/**
|
||||
* Returns a logical "index" of a given key that can be used to speed up follow-up value setters
|
||||
* or getters in certain scenarios (conditional logic).
|
||||
*
|
||||
* <p>The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
|
||||
* contiguous.
|
||||
*
|
||||
* <p>The index is valid only between map modifications (it will not be affected by read-only
|
||||
* operations like iteration or value retrievals).
|
||||
*
|
||||
* @see #indexExists
|
||||
* @see #indexGet
|
||||
* @see #indexInsert
|
||||
* @see #indexReplace
|
||||
* @param key The key to locate in the map.
|
||||
* @return A non-negative value of the logical "index" of the key in the map or a negative value
|
||||
* if the key did not exist.
|
||||
*/
|
||||
public int indexOf(char key);
|
||||
|
||||
/**
|
||||
* @see #indexOf
|
||||
* @param index The index of a given key, as returned from {@link #indexOf}.
|
||||
* @return Returns <code>true</code> if the index corresponds to an existing key or false
|
||||
* otherwise. This is equivalent to checking whether the index is a positive value (existing
|
||||
* keys) or a negative value (non-existing keys).
|
||||
*/
|
||||
public boolean indexExists(int index);
|
||||
|
||||
/**
|
||||
* Returns the value associated with an existing key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the value currently associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public char indexGet(int index);
|
||||
|
||||
/**
|
||||
* Replaces the value associated with an existing key and returns any previous value stored for
|
||||
* that key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public char indexReplace(int index, char newValue);
|
||||
|
||||
/**
|
||||
* Inserts a key-value pair for a key that is not present in the map. This method may help in
|
||||
* avoiding double recalculation of the key's hash.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
|
||||
* @throws AssertionError If assertions are enabled and the index corresponds to an existing key.
|
||||
*/
|
||||
public void indexInsert(int index, char key, char value);
|
||||
|
||||
/**
|
||||
* Removes a key-value pair at an index previously acquired from {@link #indexOf}.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of the key to remove, as returned from {@link #indexOf}.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public char indexRemove(int index);
|
||||
|
||||
/**
|
||||
* Clear all keys and values in the container.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Removes all elements from the collection and additionally releases any internal buffers.
|
||||
* Typically, if the object is to be reused, a simple {@link #clear()} should be a better
|
||||
* alternative since it'll avoid reallocation.
|
||||
*
|
||||
* @see #clear()
|
||||
*/
|
||||
public void release();
|
||||
|
||||
/**
|
||||
* Visually depict the distribution of keys.
|
||||
*
|
||||
* @param characters The number of characters to "squeeze" the entire buffer into.
|
||||
* @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
|
||||
* buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
|
||||
* between 1 and 9 is between.
|
||||
*/
|
||||
public String visualizeKeyDistribution(int characters);
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.predicates.CharPredicate;
|
||||
|
||||
/**
|
||||
* A collection allows basic, efficient operations on sets of elements (difference and
|
||||
* intersection).
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeCollection.java")
|
||||
public interface CharCollection extends CharContainer {
|
||||
/**
|
||||
* Removes all occurrences of <code>e</code> from this collection.
|
||||
*
|
||||
* @param e Element to be removed from this collection, if present.
|
||||
* @return The number of removed elements as a result of this call.
|
||||
*/
|
||||
public int removeAll(char e);
|
||||
|
||||
/**
|
||||
* Removes all elements in this collection that are present in <code>c</code>.
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int removeAll(CharLookupContainer c);
|
||||
|
||||
/**
|
||||
* Removes all elements in this collection for which the given predicate returns <code>true</code>
|
||||
* .
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int removeAll(CharPredicate predicate);
|
||||
|
||||
/**
|
||||
* Keeps all elements in this collection that are present in <code>c</code>. Runs in time
|
||||
* proportional to the number of elements in this collection. Equivalent of sets intersection.
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int retainAll(CharLookupContainer c);
|
||||
|
||||
/**
|
||||
* Keeps all elements in this collection for which the given predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int retainAll(CharPredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all elements from this collection.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Removes all elements from the collection and additionally releases any internal buffers.
|
||||
* Typically, if the object is to be reused, a simple {@link #clear()} should be a better
|
||||
* alternative since it'll avoid reallocation.
|
||||
*
|
||||
* @see #clear()
|
||||
*/
|
||||
public void release();
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.CharCursor;
|
||||
import com.carrotsearch.hppc.predicates.CharPredicate;
|
||||
import com.carrotsearch.hppc.procedures.CharProcedure;
|
||||
import java.util.Iterator;
|
||||
|
||||
/** A generic container holding <code>char</code>s. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeContainer.java")
|
||||
public interface CharContainer extends Iterable<CharCursor> {
|
||||
/**
|
||||
* Returns an iterator to a cursor traversing the collection. The order of traversal is not
|
||||
* defined. More than one cursor may be active at a time. The behavior of iterators is undefined
|
||||
* if structural changes are made to the underlying collection.
|
||||
*
|
||||
* <p>The iterator is implemented as a cursor and it returns <b>the same cursor instance</b> on
|
||||
* every call to {@link Iterator#next()} (to avoid boxing of primitive types). To read the current
|
||||
* list's value (or index in the list) use the cursor's public fields. An example is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (CharCursor<char> c : container) {
|
||||
* System.out.println("index=" + c.index + " value=" + c.value);
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public Iterator<CharCursor> iterator();
|
||||
|
||||
/**
|
||||
* Lookup a given element in the container. This operation has no speed guarantees (may be linear
|
||||
* with respect to the size of this container).
|
||||
*
|
||||
* @return Returns <code>true</code> if this container has an element equal to <code>e</code>.
|
||||
*/
|
||||
public boolean contains(char e);
|
||||
|
||||
/**
|
||||
* Return the current number of elements in this container. The time for calculating the
|
||||
* container's size may take <code>O(n)</code> time, although implementing classes should try to
|
||||
* maintain the current size and return in constant time.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/** Shortcut for <code>size() == 0</code>. */
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Copies all elements of this container to an array.
|
||||
*
|
||||
* <p>The returned array is always a copy, regardless of the storage used by the container.
|
||||
*/
|
||||
public char[] toArray();
|
||||
|
||||
/**
|
||||
* Applies a <code>procedure</code> to all container elements. Returns the argument (any subclass
|
||||
* of {@link CharProcedure}. This lets the caller to call methods of the argument by chaining the
|
||||
* call (even if the argument is an anonymous type) to retrieve computed values, for example
|
||||
* (IntContainer):
|
||||
*
|
||||
* <pre>
|
||||
* int count = container.forEach(new IntProcedure() {
|
||||
* int count; // this is a field declaration in an anonymous class.
|
||||
*
|
||||
* public void apply(int value) {
|
||||
* count++;
|
||||
* }
|
||||
* }).count;
|
||||
* </pre>
|
||||
*/
|
||||
public <T extends CharProcedure> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a <code>predicate</code> to container elements as long, as the predicate returns <code>
|
||||
* true</code>. The iteration is interrupted otherwise.
|
||||
*/
|
||||
public <T extends CharPredicate> T forEach(T predicate);
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.CharCursor;
|
||||
import com.carrotsearch.hppc.predicates.CharPredicate;
|
||||
import com.carrotsearch.hppc.procedures.CharProcedure;
|
||||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* A linear collection that supports element insertion and removal at both ends.
|
||||
*
|
||||
* @see Deque
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeDeque.java")
|
||||
public interface CharDeque extends CharCollection {
|
||||
/**
|
||||
* Removes the first element that equals <code>e</code>.
|
||||
*
|
||||
* @return The deleted element's index or <code>-1</code> if the element was not found.
|
||||
*/
|
||||
public int removeFirst(char e);
|
||||
|
||||
/**
|
||||
* Removes the last element that equals <code>e</code>.
|
||||
*
|
||||
* @return The deleted element's index or <code>-1</code> if the element was not found.
|
||||
*/
|
||||
public int removeLast(char e);
|
||||
|
||||
/** Inserts the specified element at the front of this deque. */
|
||||
public void addFirst(char e);
|
||||
|
||||
/** Inserts the specified element at the end of this deque. */
|
||||
public void addLast(char e);
|
||||
|
||||
/**
|
||||
* Retrieves and removes the first element of this deque.
|
||||
*
|
||||
* @return the head (first) element of this deque.
|
||||
*/
|
||||
public char removeFirst();
|
||||
|
||||
/**
|
||||
* Retrieves and removes the last element of this deque.
|
||||
*
|
||||
* @return the tail of this deque.
|
||||
*/
|
||||
public char removeLast();
|
||||
|
||||
/**
|
||||
* Retrieves the first element of this deque but does not remove it.
|
||||
*
|
||||
* @return the head of this deque.
|
||||
*/
|
||||
public char getFirst();
|
||||
|
||||
/**
|
||||
* Retrieves the last element of this deque but does not remove it.
|
||||
*
|
||||
* @return the head of this deque.
|
||||
*/
|
||||
public char getLast();
|
||||
|
||||
/**
|
||||
* @return An iterator over elements in this deque in tail-to-head order.
|
||||
*/
|
||||
public Iterator<CharCursor> descendingIterator();
|
||||
|
||||
/** Applies a <code>procedure</code> to all elements in tail-to-head order. */
|
||||
public <T extends CharProcedure> T descendingForEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a <code>predicate</code> to container elements as long, as the predicate returns <code>
|
||||
* true</code>. The iteration is interrupted otherwise.
|
||||
*/
|
||||
public <T extends CharPredicate> T descendingForEach(T predicate);
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.*;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* An associative container from keys to (one or possibly more) values.
|
||||
*
|
||||
* @see CharContainer
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeVTypeAssociativeContainer.java")
|
||||
public interface CharDoubleAssociativeContainer extends Iterable<CharDoubleCursor> {
|
||||
/**
|
||||
* Returns a cursor over the entries (key-value pairs) in this map. The iterator is implemented as
|
||||
* a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()}. To read the current key and value use the cursor's public fields. An example
|
||||
* is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntShortCursor c : intShortMap) {
|
||||
* System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
|
||||
* }</pre>
|
||||
*
|
||||
* <p>The <code>index</code> field inside the cursor gives the internal index inside the
|
||||
* container's implementation. The interpretation of this index depends on to the container.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<CharDoubleCursor> iterator();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this container has an association to a value for the given key.
|
||||
*/
|
||||
public boolean containsKey(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the current size (number of assigned keys) in the container.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/**
|
||||
* @return Return <code>true</code> if this hash map contains no assigned keys.
|
||||
*/
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) present in a given container. An alias to:
|
||||
*
|
||||
* <pre>
|
||||
* keys().removeAll(container)
|
||||
* </pre>
|
||||
*
|
||||
* but with no additional overhead.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharContainer container);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharPredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharDoublePredicate predicate);
|
||||
|
||||
/**
|
||||
* Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharDoubleProcedure}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*/
|
||||
public <T extends CharDoubleProcedure> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a given predicate to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharDoublePredicate}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*
|
||||
* <p>The iteration is continued as long as the predicate returns <code>true</code>.
|
||||
*/
|
||||
public <T extends CharDoublePredicate> T forEach(T predicate);
|
||||
|
||||
/**
|
||||
* Returns a collection of keys of this container. The returned collection is a view over the key
|
||||
* set and any modifications (if allowed) introduced to the collection will propagate to the
|
||||
* associative container immediately.
|
||||
*/
|
||||
public CharCollection keys();
|
||||
|
||||
/**
|
||||
* Returns a container view of all values present in this container. The returned collection is a
|
||||
* view over the key set and any modifications (if allowed) introduced to the collection will
|
||||
* propagate to the associative container immediately.
|
||||
*/
|
||||
public DoubleContainer values();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,205 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.CharDoubleCursor;
|
||||
|
||||
/** An associative container with unique binding from keys to a single value. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeVTypeMap.java")
|
||||
public interface CharDoubleMap extends CharDoubleAssociativeContainer {
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the default value for the value
|
||||
* type, if the key is not associated with any value. For numeric value types, this default
|
||||
* value is 0, for object types it is {@code null}.
|
||||
*/
|
||||
public double get(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the provided default value if the
|
||||
* key is not associated with any value.
|
||||
*/
|
||||
public double getOrDefault(char key, double defaultValue);
|
||||
|
||||
/**
|
||||
* Place a given key and value in the container.
|
||||
*
|
||||
* @return The value previously stored under the given key in the map is returned.
|
||||
*/
|
||||
public double put(char key, double value);
|
||||
|
||||
/**
|
||||
* If the specified key is not already associated with a value, associates it with the given
|
||||
* value.
|
||||
*
|
||||
* @return {@code true} if {@code key} did not exist and {@code value} was placed in the map,
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
public default boolean putIfAbsent(char key, double value) {
|
||||
int keyIndex = indexOf(key);
|
||||
if (indexExists(keyIndex)) {
|
||||
return false;
|
||||
} else {
|
||||
indexInsert(keyIndex, key, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts all keys from another container to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(CharDoubleAssociativeContainer container);
|
||||
|
||||
/**
|
||||
* Puts all keys from an iterable cursor to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(Iterable<? extends CharDoubleCursor> iterable);
|
||||
|
||||
/**
|
||||
* If <code>key</code> exists, <code>putValue</code> is inserted into the map, otherwise any
|
||||
* existing value is incremented by <code>additionValue</code>.
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param putValue The value to put if <code>key</code> does not exist.
|
||||
* @param incrementValue The value to add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public double putOrAdd(char key, double putValue, double incrementValue);
|
||||
|
||||
/**
|
||||
* An equivalent of calling
|
||||
*
|
||||
* <pre>
|
||||
* putOrAdd(key, additionValue, additionValue);
|
||||
* </pre>
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param additionValue The value to put or add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public double addTo(char key, double additionValue);
|
||||
|
||||
/**
|
||||
* Remove all values at the given key. The default value for the key type is returned if the value
|
||||
* does not exist in the map.
|
||||
*/
|
||||
public double remove(char key);
|
||||
|
||||
/**
|
||||
* Compares the specified object with this set for equality. Returns {@code true} if and only if
|
||||
* the specified object is also a {@link CharDoubleMap} and both objects contains exactly the same
|
||||
* key-value pairs.
|
||||
*/
|
||||
public boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* @return A hash code of elements stored in the map. The hash code is defined as a sum of hash
|
||||
* codes of keys and values stored within the set). Because sum is commutative, this ensures
|
||||
* that different order of elements in a set does not affect the hash code.
|
||||
*/
|
||||
public int hashCode();
|
||||
|
||||
/**
|
||||
* Returns a logical "index" of a given key that can be used to speed up follow-up value setters
|
||||
* or getters in certain scenarios (conditional logic).
|
||||
*
|
||||
* <p>The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
|
||||
* contiguous.
|
||||
*
|
||||
* <p>The index is valid only between map modifications (it will not be affected by read-only
|
||||
* operations like iteration or value retrievals).
|
||||
*
|
||||
* @see #indexExists
|
||||
* @see #indexGet
|
||||
* @see #indexInsert
|
||||
* @see #indexReplace
|
||||
* @param key The key to locate in the map.
|
||||
* @return A non-negative value of the logical "index" of the key in the map or a negative value
|
||||
* if the key did not exist.
|
||||
*/
|
||||
public int indexOf(char key);
|
||||
|
||||
/**
|
||||
* @see #indexOf
|
||||
* @param index The index of a given key, as returned from {@link #indexOf}.
|
||||
* @return Returns <code>true</code> if the index corresponds to an existing key or false
|
||||
* otherwise. This is equivalent to checking whether the index is a positive value (existing
|
||||
* keys) or a negative value (non-existing keys).
|
||||
*/
|
||||
public boolean indexExists(int index);
|
||||
|
||||
/**
|
||||
* Returns the value associated with an existing key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the value currently associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public double indexGet(int index);
|
||||
|
||||
/**
|
||||
* Replaces the value associated with an existing key and returns any previous value stored for
|
||||
* that key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public double indexReplace(int index, double newValue);
|
||||
|
||||
/**
|
||||
* Inserts a key-value pair for a key that is not present in the map. This method may help in
|
||||
* avoiding double recalculation of the key's hash.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
|
||||
* @throws AssertionError If assertions are enabled and the index corresponds to an existing key.
|
||||
*/
|
||||
public void indexInsert(int index, char key, double value);
|
||||
|
||||
/**
|
||||
* Removes a key-value pair at an index previously acquired from {@link #indexOf}.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of the key to remove, as returned from {@link #indexOf}.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public double indexRemove(int index);
|
||||
|
||||
/**
|
||||
* Clear all keys and values in the container.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Removes all elements from the collection and additionally releases any internal buffers.
|
||||
* Typically, if the object is to be reused, a simple {@link #clear()} should be a better
|
||||
* alternative since it'll avoid reallocation.
|
||||
*
|
||||
* @see #clear()
|
||||
*/
|
||||
public void release();
|
||||
|
||||
/**
|
||||
* Visually depict the distribution of keys.
|
||||
*
|
||||
* @param characters The number of characters to "squeeze" the entire buffer into.
|
||||
* @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
|
||||
* buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
|
||||
* between 1 and 9 is between.
|
||||
*/
|
||||
public String visualizeKeyDistribution(int characters);
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.*;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* An associative container from keys to (one or possibly more) values.
|
||||
*
|
||||
* @see CharContainer
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeVTypeAssociativeContainer.java")
|
||||
public interface CharFloatAssociativeContainer extends Iterable<CharFloatCursor> {
|
||||
/**
|
||||
* Returns a cursor over the entries (key-value pairs) in this map. The iterator is implemented as
|
||||
* a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()}. To read the current key and value use the cursor's public fields. An example
|
||||
* is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntShortCursor c : intShortMap) {
|
||||
* System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
|
||||
* }</pre>
|
||||
*
|
||||
* <p>The <code>index</code> field inside the cursor gives the internal index inside the
|
||||
* container's implementation. The interpretation of this index depends on to the container.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<CharFloatCursor> iterator();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this container has an association to a value for the given key.
|
||||
*/
|
||||
public boolean containsKey(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the current size (number of assigned keys) in the container.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/**
|
||||
* @return Return <code>true</code> if this hash map contains no assigned keys.
|
||||
*/
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) present in a given container. An alias to:
|
||||
*
|
||||
* <pre>
|
||||
* keys().removeAll(container)
|
||||
* </pre>
|
||||
*
|
||||
* but with no additional overhead.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharContainer container);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharPredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharFloatPredicate predicate);
|
||||
|
||||
/**
|
||||
* Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharFloatProcedure}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*/
|
||||
public <T extends CharFloatProcedure> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a given predicate to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharFloatPredicate}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*
|
||||
* <p>The iteration is continued as long as the predicate returns <code>true</code>.
|
||||
*/
|
||||
public <T extends CharFloatPredicate> T forEach(T predicate);
|
||||
|
||||
/**
|
||||
* Returns a collection of keys of this container. The returned collection is a view over the key
|
||||
* set and any modifications (if allowed) introduced to the collection will propagate to the
|
||||
* associative container immediately.
|
||||
*/
|
||||
public CharCollection keys();
|
||||
|
||||
/**
|
||||
* Returns a container view of all values present in this container. The returned collection is a
|
||||
* view over the key set and any modifications (if allowed) introduced to the collection will
|
||||
* propagate to the associative container immediately.
|
||||
*/
|
||||
public FloatContainer values();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,205 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.CharFloatCursor;
|
||||
|
||||
/** An associative container with unique binding from keys to a single value. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeVTypeMap.java")
|
||||
public interface CharFloatMap extends CharFloatAssociativeContainer {
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the default value for the value
|
||||
* type, if the key is not associated with any value. For numeric value types, this default
|
||||
* value is 0, for object types it is {@code null}.
|
||||
*/
|
||||
public float get(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the provided default value if the
|
||||
* key is not associated with any value.
|
||||
*/
|
||||
public float getOrDefault(char key, float defaultValue);
|
||||
|
||||
/**
|
||||
* Place a given key and value in the container.
|
||||
*
|
||||
* @return The value previously stored under the given key in the map is returned.
|
||||
*/
|
||||
public float put(char key, float value);
|
||||
|
||||
/**
|
||||
* If the specified key is not already associated with a value, associates it with the given
|
||||
* value.
|
||||
*
|
||||
* @return {@code true} if {@code key} did not exist and {@code value} was placed in the map,
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
public default boolean putIfAbsent(char key, float value) {
|
||||
int keyIndex = indexOf(key);
|
||||
if (indexExists(keyIndex)) {
|
||||
return false;
|
||||
} else {
|
||||
indexInsert(keyIndex, key, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts all keys from another container to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(CharFloatAssociativeContainer container);
|
||||
|
||||
/**
|
||||
* Puts all keys from an iterable cursor to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(Iterable<? extends CharFloatCursor> iterable);
|
||||
|
||||
/**
|
||||
* If <code>key</code> exists, <code>putValue</code> is inserted into the map, otherwise any
|
||||
* existing value is incremented by <code>additionValue</code>.
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param putValue The value to put if <code>key</code> does not exist.
|
||||
* @param incrementValue The value to add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public float putOrAdd(char key, float putValue, float incrementValue);
|
||||
|
||||
/**
|
||||
* An equivalent of calling
|
||||
*
|
||||
* <pre>
|
||||
* putOrAdd(key, additionValue, additionValue);
|
||||
* </pre>
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param additionValue The value to put or add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public float addTo(char key, float additionValue);
|
||||
|
||||
/**
|
||||
* Remove all values at the given key. The default value for the key type is returned if the value
|
||||
* does not exist in the map.
|
||||
*/
|
||||
public float remove(char key);
|
||||
|
||||
/**
|
||||
* Compares the specified object with this set for equality. Returns {@code true} if and only if
|
||||
* the specified object is also a {@link CharFloatMap} and both objects contains exactly the same
|
||||
* key-value pairs.
|
||||
*/
|
||||
public boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* @return A hash code of elements stored in the map. The hash code is defined as a sum of hash
|
||||
* codes of keys and values stored within the set). Because sum is commutative, this ensures
|
||||
* that different order of elements in a set does not affect the hash code.
|
||||
*/
|
||||
public int hashCode();
|
||||
|
||||
/**
|
||||
* Returns a logical "index" of a given key that can be used to speed up follow-up value setters
|
||||
* or getters in certain scenarios (conditional logic).
|
||||
*
|
||||
* <p>The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
|
||||
* contiguous.
|
||||
*
|
||||
* <p>The index is valid only between map modifications (it will not be affected by read-only
|
||||
* operations like iteration or value retrievals).
|
||||
*
|
||||
* @see #indexExists
|
||||
* @see #indexGet
|
||||
* @see #indexInsert
|
||||
* @see #indexReplace
|
||||
* @param key The key to locate in the map.
|
||||
* @return A non-negative value of the logical "index" of the key in the map or a negative value
|
||||
* if the key did not exist.
|
||||
*/
|
||||
public int indexOf(char key);
|
||||
|
||||
/**
|
||||
* @see #indexOf
|
||||
* @param index The index of a given key, as returned from {@link #indexOf}.
|
||||
* @return Returns <code>true</code> if the index corresponds to an existing key or false
|
||||
* otherwise. This is equivalent to checking whether the index is a positive value (existing
|
||||
* keys) or a negative value (non-existing keys).
|
||||
*/
|
||||
public boolean indexExists(int index);
|
||||
|
||||
/**
|
||||
* Returns the value associated with an existing key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the value currently associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public float indexGet(int index);
|
||||
|
||||
/**
|
||||
* Replaces the value associated with an existing key and returns any previous value stored for
|
||||
* that key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public float indexReplace(int index, float newValue);
|
||||
|
||||
/**
|
||||
* Inserts a key-value pair for a key that is not present in the map. This method may help in
|
||||
* avoiding double recalculation of the key's hash.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
|
||||
* @throws AssertionError If assertions are enabled and the index corresponds to an existing key.
|
||||
*/
|
||||
public void indexInsert(int index, char key, float value);
|
||||
|
||||
/**
|
||||
* Removes a key-value pair at an index previously acquired from {@link #indexOf}.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of the key to remove, as returned from {@link #indexOf}.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public float indexRemove(int index);
|
||||
|
||||
/**
|
||||
* Clear all keys and values in the container.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Removes all elements from the collection and additionally releases any internal buffers.
|
||||
* Typically, if the object is to be reused, a simple {@link #clear()} should be a better
|
||||
* alternative since it'll avoid reallocation.
|
||||
*
|
||||
* @see #clear()
|
||||
*/
|
||||
public void release();
|
||||
|
||||
/**
|
||||
* Visually depict the distribution of keys.
|
||||
*
|
||||
* @param characters The number of characters to "squeeze" the entire buffer into.
|
||||
* @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
|
||||
* buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
|
||||
* between 1 and 9 is between.
|
||||
*/
|
||||
public String visualizeKeyDistribution(int characters);
|
||||
}
|
@ -1,787 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import static com.carrotsearch.hppc.Containers.*;
|
||||
import static com.carrotsearch.hppc.HashContainers.*;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.*;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A hash set of <code>char</code>s, implemented using open addressing with linear probing for
|
||||
* collision resolution.
|
||||
*
|
||||
* @see <a href="{@docRoot}/overview-summary.html#interfaces">HPPC interfaces diagram</a>
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:16+0200", value = "KTypeHashSet.java")
|
||||
public class CharHashSet extends AbstractCharCollection
|
||||
implements CharLookupContainer, CharSet, Preallocable, Cloneable, Accountable {
|
||||
/** The hash array holding keys. */
|
||||
public char[] keys;
|
||||
|
||||
/**
|
||||
* The number of stored keys (assigned key slots), excluding the special "empty" key, if any.
|
||||
*
|
||||
* @see #size()
|
||||
* @see #hasEmptyKey
|
||||
*/
|
||||
protected int assigned;
|
||||
|
||||
/** Mask for slot scans in {@link #keys}. */
|
||||
protected int mask;
|
||||
|
||||
/** Expand (rehash) {@link #keys} when {@link #assigned} hits this value. */
|
||||
protected int resizeAt;
|
||||
|
||||
/** Special treatment for the "empty slot" key marker. */
|
||||
protected boolean hasEmptyKey;
|
||||
|
||||
/** The load factor for {@link #keys}. */
|
||||
protected double loadFactor;
|
||||
|
||||
/** Seed used to ensure the hash iteration order is different from an iteration to another. */
|
||||
protected int iterationSeed;
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @see #CharHashSet(int, double)
|
||||
*/
|
||||
public CharHashSet() {
|
||||
this(DEFAULT_EXPECTED_ELEMENTS, DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @see #CharHashSet(int, double)
|
||||
*/
|
||||
public CharHashSet(int expectedElements) {
|
||||
this(expectedElements, DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with the provided defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause a rehash
|
||||
* (inclusive).
|
||||
* @param loadFactor The load factor for internal buffers. Insane load factors (zero, full
|
||||
* capacity) are rejected by {@link #verifyLoadFactor(double)}.
|
||||
*/
|
||||
public CharHashSet(int expectedElements, double loadFactor) {
|
||||
this.loadFactor = verifyLoadFactor(loadFactor);
|
||||
iterationSeed = HashContainers.nextIterationSeed();
|
||||
ensureCapacity(expectedElements);
|
||||
}
|
||||
|
||||
/** New instance copying elements from another {@link CharContainer}. */
|
||||
public CharHashSet(CharContainer container) {
|
||||
this(container.size());
|
||||
addAll(container);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean add(char key) {
|
||||
if (((key) == 0)) {
|
||||
assert ((keys[mask + 1]) == 0);
|
||||
boolean added = !hasEmptyKey;
|
||||
hasEmptyKey = true;
|
||||
return added;
|
||||
} else {
|
||||
final char[] keys = this.keys;
|
||||
final int mask = this.mask;
|
||||
int slot = hashKey(key) & mask;
|
||||
|
||||
char existing;
|
||||
while (!((existing = keys[slot]) == 0)) {
|
||||
if (((key) == (existing))) {
|
||||
return false;
|
||||
}
|
||||
slot = (slot + 1) & mask;
|
||||
}
|
||||
|
||||
if (assigned == resizeAt) {
|
||||
allocateThenInsertThenRehash(slot, key);
|
||||
} else {
|
||||
keys[slot] = key;
|
||||
}
|
||||
|
||||
assigned++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all elements from the given list (vararg) to this set.
|
||||
*
|
||||
* @return Returns the number of elements actually added as a result of this call (not previously
|
||||
* present in the set).
|
||||
*/
|
||||
public final int addAll(char... elements) {
|
||||
ensureCapacity(elements.length);
|
||||
int count = 0;
|
||||
for (char e : elements) {
|
||||
if (add(e)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all elements from the given {@link CharContainer} to this set.
|
||||
*
|
||||
* @return Returns the number of elements actually added as a result of this call (not previously
|
||||
* present in the set).
|
||||
*/
|
||||
public int addAll(CharContainer container) {
|
||||
ensureCapacity(container.size());
|
||||
return addAll((Iterable<? extends CharCursor>) container);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all elements from the given iterable to this set.
|
||||
*
|
||||
* @return Returns the number of elements actually added as a result of this call (not previously
|
||||
* present in the set).
|
||||
*/
|
||||
public int addAll(Iterable<? extends CharCursor> iterable) {
|
||||
int count = 0;
|
||||
for (CharCursor cursor : iterable) {
|
||||
if (add(cursor.value)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public char[] toArray() {
|
||||
|
||||
final char[] cloned = (new char[size()]);
|
||||
int j = 0;
|
||||
if (hasEmptyKey) {
|
||||
cloned[j++] = ((char) 0);
|
||||
}
|
||||
|
||||
final char[] keys = this.keys;
|
||||
int seed = nextIterationSeed();
|
||||
int inc = iterationIncrement(seed);
|
||||
for (int i = 0, mask = this.mask, slot = seed & mask;
|
||||
i <= mask;
|
||||
i++, slot = (slot + inc) & mask) {
|
||||
char existing;
|
||||
if (!((existing = keys[slot]) == 0)) {
|
||||
cloned[j++] = existing;
|
||||
}
|
||||
}
|
||||
|
||||
return cloned;
|
||||
}
|
||||
|
||||
/** An alias for the (preferred) {@link #removeAll}. */
|
||||
public boolean remove(char key) {
|
||||
if (((key) == 0)) {
|
||||
boolean hadEmptyKey = hasEmptyKey;
|
||||
hasEmptyKey = false;
|
||||
return hadEmptyKey;
|
||||
} else {
|
||||
final char[] keys = this.keys;
|
||||
final int mask = this.mask;
|
||||
int slot = hashKey(key) & mask;
|
||||
|
||||
char existing;
|
||||
while (!((existing = keys[slot]) == 0)) {
|
||||
if (((key) == (existing))) {
|
||||
shiftConflictingKeys(slot);
|
||||
return true;
|
||||
}
|
||||
slot = (slot + 1) & mask;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(char key) {
|
||||
return remove(key) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all keys present in a given container.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharContainer other) {
|
||||
final int before = size();
|
||||
|
||||
// Try to iterate over the smaller set or over the container that isn't implementing
|
||||
// efficient contains() lookup.
|
||||
|
||||
if (other.size() >= size() && other instanceof CharLookupContainer) {
|
||||
if (hasEmptyKey && other.contains(((char) 0))) {
|
||||
hasEmptyKey = false;
|
||||
}
|
||||
|
||||
final char[] keys = this.keys;
|
||||
for (int slot = 0, max = this.mask; slot <= max; ) {
|
||||
char existing;
|
||||
if (!((existing = keys[slot]) == 0) && other.contains(existing)) {
|
||||
// Shift, do not increment slot.
|
||||
shiftConflictingKeys(slot);
|
||||
} else {
|
||||
slot++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (CharCursor c : other) {
|
||||
remove(c.value);
|
||||
}
|
||||
}
|
||||
|
||||
return before - size();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(CharPredicate predicate) {
|
||||
int before = size();
|
||||
|
||||
if (hasEmptyKey) {
|
||||
if (predicate.apply(((char) 0))) {
|
||||
hasEmptyKey = false;
|
||||
}
|
||||
}
|
||||
|
||||
final char[] keys = this.keys;
|
||||
for (int slot = 0, max = this.mask; slot <= max; ) {
|
||||
char existing;
|
||||
if (!((existing = keys[slot]) == 0)) {
|
||||
if (predicate.apply(existing)) {
|
||||
shiftConflictingKeys(slot);
|
||||
continue; // Repeat the check for the same slot i (shifted).
|
||||
}
|
||||
}
|
||||
slot++;
|
||||
}
|
||||
|
||||
return before - size();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean contains(char key) {
|
||||
if (((key) == 0)) {
|
||||
return hasEmptyKey;
|
||||
} else {
|
||||
final char[] keys = this.keys;
|
||||
final int mask = this.mask;
|
||||
int slot = hashKey(key) & mask;
|
||||
char existing;
|
||||
while (!((existing = keys[slot]) == 0)) {
|
||||
if (((key) == (existing))) {
|
||||
return true;
|
||||
}
|
||||
slot = (slot + 1) & mask;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void clear() {
|
||||
assigned = 0;
|
||||
hasEmptyKey = false;
|
||||
Arrays.fill(keys, ((char) 0));
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void release() {
|
||||
assigned = 0;
|
||||
hasEmptyKey = false;
|
||||
keys = null;
|
||||
ensureCapacity(Containers.DEFAULT_EXPECTED_ELEMENTS);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure this container can hold at least the given number of elements without resizing its
|
||||
* buffers.
|
||||
*
|
||||
* @param expectedElements The total number of elements, inclusive.
|
||||
*/
|
||||
@Override
|
||||
public void ensureCapacity(int expectedElements) {
|
||||
if (expectedElements > resizeAt || keys == null) {
|
||||
final char[] prevKeys = this.keys;
|
||||
allocateBuffers(minBufferSize(expectedElements, loadFactor));
|
||||
if (prevKeys != null && !isEmpty()) {
|
||||
rehash(prevKeys);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int size() {
|
||||
return assigned + (hasEmptyKey ? 1 : 0);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = hasEmptyKey ? 0xDEADBEEF : 0;
|
||||
final char[] keys = this.keys;
|
||||
for (int slot = mask; slot >= 0; slot--) {
|
||||
char existing;
|
||||
if (!((existing = keys[slot]) == 0)) {
|
||||
h += BitMixer.mix(existing);
|
||||
}
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return (this == obj)
|
||||
|| (obj != null && getClass() == obj.getClass() && sameKeys(getClass().cast(obj)));
|
||||
}
|
||||
|
||||
/** Return true if all keys of some other container exist in this container. */
|
||||
private boolean sameKeys(CharSet other) {
|
||||
if (other.size() != size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (CharCursor c : other) {
|
||||
if (!contains(c.value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public CharHashSet clone() {
|
||||
try {
|
||||
|
||||
CharHashSet cloned = (CharHashSet) super.clone();
|
||||
cloned.keys = keys.clone();
|
||||
cloned.hasEmptyKey = hasEmptyKey;
|
||||
cloned.iterationSeed = HashContainers.nextIterationSeed();
|
||||
return cloned;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public Iterator<CharCursor> iterator() {
|
||||
return new EntryIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesAllocated() {
|
||||
// int: assigned, mask, keyMixer, resizeAt
|
||||
// double: loadFactor
|
||||
// boolean: hasEmptyKey
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ 4 * Integer.BYTES
|
||||
+ Double.BYTES
|
||||
+ 1
|
||||
+ RamUsageEstimator.shallowSizeOfArray(keys);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesUsed() {
|
||||
// int: assigned, mask, keyMixer, resizeAt
|
||||
// double: loadFactor
|
||||
// boolean: hasEmptyKey
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ 4 * Integer.BYTES
|
||||
+ Double.BYTES
|
||||
+ 1
|
||||
+ RamUsageEstimator.shallowUsedSizeOfArray(keys, size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the next iteration seed used to build the iteration starting slot and offset
|
||||
* increment. This method does not need to be synchronized, what matters is that each thread gets
|
||||
* a sequence of varying seeds.
|
||||
*/
|
||||
protected int nextIterationSeed() {
|
||||
return iterationSeed = BitMixer.mixPhi(iterationSeed);
|
||||
}
|
||||
|
||||
/** An iterator implementation for {@link #iterator}. */
|
||||
protected final class EntryIterator extends AbstractIterator<CharCursor> {
|
||||
private final CharCursor cursor;
|
||||
private final int increment;
|
||||
private int index;
|
||||
private int slot;
|
||||
|
||||
public EntryIterator() {
|
||||
cursor = new CharCursor();
|
||||
int seed = nextIterationSeed();
|
||||
increment = iterationIncrement(seed);
|
||||
slot = seed & mask;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CharCursor fetch() {
|
||||
final int mask = CharHashSet.this.mask;
|
||||
while (index <= mask) {
|
||||
char existing;
|
||||
index++;
|
||||
slot = (slot + increment) & mask;
|
||||
if (!((existing = keys[slot]) == 0)) {
|
||||
cursor.index = slot;
|
||||
cursor.value = existing;
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
if (index == mask + 1 && hasEmptyKey) {
|
||||
cursor.index = index++;
|
||||
cursor.value = ((char) 0);
|
||||
return cursor;
|
||||
}
|
||||
|
||||
return done();
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends CharProcedure> T forEach(T procedure) {
|
||||
if (hasEmptyKey) {
|
||||
procedure.apply(((char) 0));
|
||||
}
|
||||
|
||||
final char[] keys = this.keys;
|
||||
int seed = nextIterationSeed();
|
||||
int inc = iterationIncrement(seed);
|
||||
for (int i = 0, mask = this.mask, slot = seed & mask;
|
||||
i <= mask;
|
||||
i++, slot = (slot + inc) & mask) {
|
||||
char existing;
|
||||
if (!((existing = keys[slot]) == 0)) {
|
||||
procedure.apply(existing);
|
||||
}
|
||||
}
|
||||
|
||||
return procedure;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends CharPredicate> T forEach(T predicate) {
|
||||
if (hasEmptyKey) {
|
||||
if (!predicate.apply(((char) 0))) {
|
||||
return predicate;
|
||||
}
|
||||
}
|
||||
|
||||
final char[] keys = this.keys;
|
||||
int seed = nextIterationSeed();
|
||||
int inc = iterationIncrement(seed);
|
||||
for (int i = 0, mask = this.mask, slot = seed & mask;
|
||||
i <= mask;
|
||||
i++, slot = (slot + inc) & mask) {
|
||||
char existing;
|
||||
if (!((existing = keys[slot]) == 0)) {
|
||||
if (!predicate.apply(existing)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return predicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a set from a variable number of arguments or an array of <code>char</code>. The elements
|
||||
* are copied from the argument to the internal buffer.
|
||||
*/
|
||||
public static CharHashSet from(char... elements) {
|
||||
final CharHashSet set = new CharHashSet(elements.length);
|
||||
set.addAll(elements);
|
||||
return set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hash code for the given key.
|
||||
*
|
||||
* <p>The output from this function should evenly distribute keys across the entire integer range.
|
||||
*/
|
||||
protected int hashKey(char key) {
|
||||
assert !((key) == 0); // Handled as a special case (empty slot marker).
|
||||
return BitMixer.mixPhi(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a logical "index" of a given key that can be used to speed up follow-up logic in
|
||||
* certain scenarios (conditional logic).
|
||||
*
|
||||
* <p>The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
|
||||
* contiguous.
|
||||
*
|
||||
* <p>The index is valid only between modifications (it will not be affected by read-only
|
||||
* operations).
|
||||
*
|
||||
* @see #indexExists
|
||||
* @see #indexGet
|
||||
* @see #indexInsert
|
||||
* @see #indexReplace
|
||||
* @param key The key to locate in the set.
|
||||
* @return A non-negative value of the logical "index" of the key in the set or a negative value
|
||||
* if the key did not exist.
|
||||
*/
|
||||
public int indexOf(char key) {
|
||||
final int mask = this.mask;
|
||||
if (((key) == 0)) {
|
||||
return hasEmptyKey ? mask + 1 : ~(mask + 1);
|
||||
} else {
|
||||
final char[] keys = this.keys;
|
||||
int slot = hashKey(key) & mask;
|
||||
|
||||
char existing;
|
||||
while (!((existing = keys[slot]) == 0)) {
|
||||
if (((key) == (existing))) {
|
||||
return slot;
|
||||
}
|
||||
slot = (slot + 1) & mask;
|
||||
}
|
||||
|
||||
return ~slot;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #indexOf
|
||||
* @param index The index of a given key, as returned from {@link #indexOf}.
|
||||
* @return Returns <code>true</code> if the index corresponds to an existing key or false
|
||||
* otherwise. This is equivalent to checking whether the index is a positive value (existing
|
||||
* keys) or a negative value (non-existing keys).
|
||||
*/
|
||||
public boolean indexExists(int index) {
|
||||
assert index < 0 || index <= mask || (index == mask + 1 && hasEmptyKey);
|
||||
|
||||
return index >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exact value of the existing key. This method makes sense for sets of objects which
|
||||
* define custom key-equality relationship.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the equivalent key currently stored in the set.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public char indexGet(int index) {
|
||||
assert index >= 0 : "The index must point at an existing key.";
|
||||
assert index <= mask || (index == mask + 1 && hasEmptyKey);
|
||||
|
||||
return keys[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the existing equivalent key with the given one and returns any previous value stored
|
||||
* for that key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @param equivalentKey The key to put in the set as a replacement. Must be equivalent to the key
|
||||
* currently stored at the provided index.
|
||||
* @return Returns the previous key stored in the set.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public char indexReplace(int index, char equivalentKey) {
|
||||
assert index >= 0 : "The index must point at an existing key.";
|
||||
assert index <= mask || (index == mask + 1 && hasEmptyKey);
|
||||
assert ((keys[index]) == (equivalentKey));
|
||||
|
||||
char previousValue = keys[index];
|
||||
keys[index] = equivalentKey;
|
||||
return previousValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a key for an index that is not present in the set. This method may help in avoiding
|
||||
* double recalculation of the key's hash.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public void indexInsert(int index, char key) {
|
||||
assert index < 0 : "The index must not point at an existing key.";
|
||||
|
||||
index = ~index;
|
||||
if (((key) == 0)) {
|
||||
assert index == mask + 1;
|
||||
assert ((keys[index]) == 0);
|
||||
hasEmptyKey = true;
|
||||
} else {
|
||||
assert ((keys[index]) == 0);
|
||||
|
||||
if (assigned == resizeAt) {
|
||||
allocateThenInsertThenRehash(index, key);
|
||||
} else {
|
||||
keys[index] = key;
|
||||
}
|
||||
|
||||
assigned++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a key at an index previously acquired from {@link #indexOf}.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of the key to remove, as returned from {@link #indexOf}.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public void indexRemove(int index) {
|
||||
assert index >= 0 : "The index must point at an existing key.";
|
||||
assert index <= mask || (index == mask + 1 && hasEmptyKey);
|
||||
|
||||
if (index > mask) {
|
||||
hasEmptyKey = false;
|
||||
} else {
|
||||
shiftConflictingKeys(index);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String visualizeKeyDistribution(int characters) {
|
||||
return CharBufferVisualizer.visualizeKeyDistribution(keys, mask, characters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate load factor range and return it. Override and suppress if you need insane load
|
||||
* factors.
|
||||
*/
|
||||
protected double verifyLoadFactor(double loadFactor) {
|
||||
checkLoadFactor(loadFactor, MIN_LOAD_FACTOR, MAX_LOAD_FACTOR);
|
||||
return loadFactor;
|
||||
}
|
||||
|
||||
/** Rehash from old buffers to new buffers. */
|
||||
protected void rehash(char[] fromKeys) {
|
||||
assert HashContainers.checkPowerOfTwo(fromKeys.length - 1);
|
||||
|
||||
// Rehash all stored keys into the new buffers.
|
||||
final char[] keys = this.keys;
|
||||
final int mask = this.mask;
|
||||
char existing;
|
||||
for (int i = fromKeys.length - 1; --i >= 0; ) {
|
||||
if (!((existing = fromKeys[i]) == 0)) {
|
||||
int slot = hashKey(existing) & mask;
|
||||
while (!((keys[slot]) == 0)) {
|
||||
slot = (slot + 1) & mask;
|
||||
}
|
||||
keys[slot] = existing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate new internal buffers. This method attempts to allocate and assign internal buffers
|
||||
* atomically (either allocations succeed or not).
|
||||
*/
|
||||
protected void allocateBuffers(int arraySize) {
|
||||
assert Integer.bitCount(arraySize) == 1;
|
||||
|
||||
// Ensure no change is done if we hit an OOM.
|
||||
char[] prevKeys = this.keys;
|
||||
try {
|
||||
int emptyElementSlot = 1;
|
||||
this.keys = (new char[arraySize + emptyElementSlot]);
|
||||
} catch (OutOfMemoryError e) {
|
||||
this.keys = prevKeys;
|
||||
throw new BufferAllocationException(
|
||||
"Not enough memory to allocate buffers for rehashing: %,d -> %,d",
|
||||
e, this.keys == null ? 0 : size(), arraySize);
|
||||
}
|
||||
|
||||
this.resizeAt = expandAtCount(arraySize, loadFactor);
|
||||
this.mask = arraySize - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is invoked when there is a new key to be inserted into the buffer but there is not
|
||||
* enough empty slots to do so.
|
||||
*
|
||||
* <p>New buffers are allocated. If this succeeds, we know we can proceed with rehashing so we
|
||||
* assign the pending element to the previous buffer (possibly violating the invariant of having
|
||||
* at least one empty slot) and rehash all keys, substituting new buffers at the end.
|
||||
*/
|
||||
protected void allocateThenInsertThenRehash(int slot, char pendingKey) {
|
||||
assert assigned == resizeAt && ((keys[slot]) == 0) && !((pendingKey) == 0);
|
||||
|
||||
// Try to allocate new buffers first. If we OOM, we leave in a consistent state.
|
||||
final char[] prevKeys = this.keys;
|
||||
allocateBuffers(nextBufferSize(mask + 1, size(), loadFactor));
|
||||
assert this.keys.length > prevKeys.length;
|
||||
|
||||
// We have succeeded at allocating new data so insert the pending key/value at
|
||||
// the free slot in the old arrays before rehashing.
|
||||
prevKeys[slot] = pendingKey;
|
||||
|
||||
// Rehash old keys, including the pending key.
|
||||
rehash(prevKeys);
|
||||
}
|
||||
|
||||
/** Shift all the slot-conflicting keys allocated to (and including) <code>slot</code>. */
|
||||
protected void shiftConflictingKeys(int gapSlot) {
|
||||
final char[] keys = this.keys;
|
||||
final int mask = this.mask;
|
||||
|
||||
// Perform shifts of conflicting keys to fill in the gap.
|
||||
int distance = 0;
|
||||
while (true) {
|
||||
final int slot = (gapSlot + (++distance)) & mask;
|
||||
final char existing = keys[slot];
|
||||
if (((existing) == 0)) {
|
||||
break;
|
||||
}
|
||||
|
||||
final int idealSlot = hashKey(existing);
|
||||
final int shift = (slot - idealSlot) & mask;
|
||||
if (shift >= distance) {
|
||||
// Entry at this position was originally at or before the gap slot.
|
||||
// Move the conflict-shifted entry to the gap's position and repeat the procedure
|
||||
// for any entries to the right of the current position, treating it
|
||||
// as the new gap.
|
||||
keys[gapSlot] = existing;
|
||||
gapSlot = slot;
|
||||
distance = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Mark the last found gap slot without a conflict as empty.
|
||||
keys[gapSlot] = ((char) 0);
|
||||
assigned--;
|
||||
}
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import java.util.RandomAccess;
|
||||
|
||||
/**
|
||||
* An indexed container provides random access to elements based on an <code>index</code>. Indexes
|
||||
* are zero-based.
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeIndexedContainer.java")
|
||||
public interface CharIndexedContainer extends CharCollection, RandomAccess {
|
||||
/**
|
||||
* Removes the first element that equals <code>e1</code>, returning whether an element has been
|
||||
* removed.
|
||||
*/
|
||||
public boolean removeElement(char e1);
|
||||
|
||||
/**
|
||||
* Removes the first element that equals <code>e1</code>, returning its deleted position or <code>
|
||||
* -1</code> if the element was not found.
|
||||
*/
|
||||
public int removeFirst(char e1);
|
||||
|
||||
/**
|
||||
* Removes the last element that equals <code>e1</code>, returning its deleted position or <code>
|
||||
* -1</code> if the element was not found.
|
||||
*/
|
||||
public int removeLast(char e1);
|
||||
|
||||
/**
|
||||
* Returns the index of the first occurrence of the specified element in this list, or -1 if this
|
||||
* list does not contain the element.
|
||||
*/
|
||||
public int indexOf(char e1);
|
||||
|
||||
/**
|
||||
* Returns the index of the last occurrence of the specified element in this list, or -1 if this
|
||||
* list does not contain the element.
|
||||
*/
|
||||
public int lastIndexOf(char e1);
|
||||
|
||||
/** Adds an element to the end of this container (the last index is incremented by one). */
|
||||
public void add(char e1);
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the specified position in this list.
|
||||
*
|
||||
* @param index The index at which the element should be inserted, shifting any existing and
|
||||
* subsequent elements to the right.
|
||||
*/
|
||||
public void insert(int index, char e1);
|
||||
|
||||
/**
|
||||
* Replaces the element at the specified position in this list with the specified element.
|
||||
*
|
||||
* @return Returns the previous value in the list.
|
||||
*/
|
||||
public char set(int index, char e1);
|
||||
|
||||
/**
|
||||
* @return Returns the element at index <code>index</code> from the list.
|
||||
*/
|
||||
public char get(int index);
|
||||
|
||||
/**
|
||||
* Removes the element at the specified position in this container and returns it.
|
||||
*
|
||||
* @see #removeFirst
|
||||
* @see #removeLast
|
||||
* @see #removeAll
|
||||
*/
|
||||
public char removeAt(int index);
|
||||
|
||||
/** Removes and returns the last element of this container. This container must not be empty. */
|
||||
public char removeLast();
|
||||
|
||||
/**
|
||||
* Removes from this container all of the elements with indexes between <code>fromIndex</code>,
|
||||
* inclusive, and <code>toIndex</code>, exclusive.
|
||||
*/
|
||||
public void removeRange(int fromIndex, int toIndex);
|
||||
|
||||
/** Returns this container elements as a stream. */
|
||||
|
||||
/** Sorts the elements in this container and returns this container. */
|
||||
public CharIndexedContainer sort();
|
||||
|
||||
/** Reverses the elements in this container and returns this container. */
|
||||
public CharIndexedContainer reverse();
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.*;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* An associative container from keys to (one or possibly more) values.
|
||||
*
|
||||
* @see CharContainer
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeVTypeAssociativeContainer.java")
|
||||
public interface CharIntAssociativeContainer extends Iterable<CharIntCursor> {
|
||||
/**
|
||||
* Returns a cursor over the entries (key-value pairs) in this map. The iterator is implemented as
|
||||
* a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()}. To read the current key and value use the cursor's public fields. An example
|
||||
* is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntShortCursor c : intShortMap) {
|
||||
* System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
|
||||
* }</pre>
|
||||
*
|
||||
* <p>The <code>index</code> field inside the cursor gives the internal index inside the
|
||||
* container's implementation. The interpretation of this index depends on to the container.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<CharIntCursor> iterator();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this container has an association to a value for the given key.
|
||||
*/
|
||||
public boolean containsKey(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the current size (number of assigned keys) in the container.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/**
|
||||
* @return Return <code>true</code> if this hash map contains no assigned keys.
|
||||
*/
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) present in a given container. An alias to:
|
||||
*
|
||||
* <pre>
|
||||
* keys().removeAll(container)
|
||||
* </pre>
|
||||
*
|
||||
* but with no additional overhead.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharContainer container);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharPredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharIntPredicate predicate);
|
||||
|
||||
/**
|
||||
* Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharIntProcedure}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*/
|
||||
public <T extends CharIntProcedure> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a given predicate to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharIntPredicate}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*
|
||||
* <p>The iteration is continued as long as the predicate returns <code>true</code>.
|
||||
*/
|
||||
public <T extends CharIntPredicate> T forEach(T predicate);
|
||||
|
||||
/**
|
||||
* Returns a collection of keys of this container. The returned collection is a view over the key
|
||||
* set and any modifications (if allowed) introduced to the collection will propagate to the
|
||||
* associative container immediately.
|
||||
*/
|
||||
public CharCollection keys();
|
||||
|
||||
/**
|
||||
* Returns a container view of all values present in this container. The returned collection is a
|
||||
* view over the key set and any modifications (if allowed) introduced to the collection will
|
||||
* propagate to the associative container immediately.
|
||||
*/
|
||||
public IntContainer values();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,205 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.CharIntCursor;
|
||||
|
||||
/** An associative container with unique binding from keys to a single value. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeVTypeMap.java")
|
||||
public interface CharIntMap extends CharIntAssociativeContainer {
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the default value for the value
|
||||
* type, if the key is not associated with any value. For numeric value types, this default
|
||||
* value is 0, for object types it is {@code null}.
|
||||
*/
|
||||
public int get(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the provided default value if the
|
||||
* key is not associated with any value.
|
||||
*/
|
||||
public int getOrDefault(char key, int defaultValue);
|
||||
|
||||
/**
|
||||
* Place a given key and value in the container.
|
||||
*
|
||||
* @return The value previously stored under the given key in the map is returned.
|
||||
*/
|
||||
public int put(char key, int value);
|
||||
|
||||
/**
|
||||
* If the specified key is not already associated with a value, associates it with the given
|
||||
* value.
|
||||
*
|
||||
* @return {@code true} if {@code key} did not exist and {@code value} was placed in the map,
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
public default boolean putIfAbsent(char key, int value) {
|
||||
int keyIndex = indexOf(key);
|
||||
if (indexExists(keyIndex)) {
|
||||
return false;
|
||||
} else {
|
||||
indexInsert(keyIndex, key, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts all keys from another container to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(CharIntAssociativeContainer container);
|
||||
|
||||
/**
|
||||
* Puts all keys from an iterable cursor to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(Iterable<? extends CharIntCursor> iterable);
|
||||
|
||||
/**
|
||||
* If <code>key</code> exists, <code>putValue</code> is inserted into the map, otherwise any
|
||||
* existing value is incremented by <code>additionValue</code>.
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param putValue The value to put if <code>key</code> does not exist.
|
||||
* @param incrementValue The value to add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public int putOrAdd(char key, int putValue, int incrementValue);
|
||||
|
||||
/**
|
||||
* An equivalent of calling
|
||||
*
|
||||
* <pre>
|
||||
* putOrAdd(key, additionValue, additionValue);
|
||||
* </pre>
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param additionValue The value to put or add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public int addTo(char key, int additionValue);
|
||||
|
||||
/**
|
||||
* Remove all values at the given key. The default value for the key type is returned if the value
|
||||
* does not exist in the map.
|
||||
*/
|
||||
public int remove(char key);
|
||||
|
||||
/**
|
||||
* Compares the specified object with this set for equality. Returns {@code true} if and only if
|
||||
* the specified object is also a {@link CharIntMap} and both objects contains exactly the same
|
||||
* key-value pairs.
|
||||
*/
|
||||
public boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* @return A hash code of elements stored in the map. The hash code is defined as a sum of hash
|
||||
* codes of keys and values stored within the set). Because sum is commutative, this ensures
|
||||
* that different order of elements in a set does not affect the hash code.
|
||||
*/
|
||||
public int hashCode();
|
||||
|
||||
/**
|
||||
* Returns a logical "index" of a given key that can be used to speed up follow-up value setters
|
||||
* or getters in certain scenarios (conditional logic).
|
||||
*
|
||||
* <p>The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
|
||||
* contiguous.
|
||||
*
|
||||
* <p>The index is valid only between map modifications (it will not be affected by read-only
|
||||
* operations like iteration or value retrievals).
|
||||
*
|
||||
* @see #indexExists
|
||||
* @see #indexGet
|
||||
* @see #indexInsert
|
||||
* @see #indexReplace
|
||||
* @param key The key to locate in the map.
|
||||
* @return A non-negative value of the logical "index" of the key in the map or a negative value
|
||||
* if the key did not exist.
|
||||
*/
|
||||
public int indexOf(char key);
|
||||
|
||||
/**
|
||||
* @see #indexOf
|
||||
* @param index The index of a given key, as returned from {@link #indexOf}.
|
||||
* @return Returns <code>true</code> if the index corresponds to an existing key or false
|
||||
* otherwise. This is equivalent to checking whether the index is a positive value (existing
|
||||
* keys) or a negative value (non-existing keys).
|
||||
*/
|
||||
public boolean indexExists(int index);
|
||||
|
||||
/**
|
||||
* Returns the value associated with an existing key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the value currently associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public int indexGet(int index);
|
||||
|
||||
/**
|
||||
* Replaces the value associated with an existing key and returns any previous value stored for
|
||||
* that key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public int indexReplace(int index, int newValue);
|
||||
|
||||
/**
|
||||
* Inserts a key-value pair for a key that is not present in the map. This method may help in
|
||||
* avoiding double recalculation of the key's hash.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
|
||||
* @throws AssertionError If assertions are enabled and the index corresponds to an existing key.
|
||||
*/
|
||||
public void indexInsert(int index, char key, int value);
|
||||
|
||||
/**
|
||||
* Removes a key-value pair at an index previously acquired from {@link #indexOf}.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of the key to remove, as returned from {@link #indexOf}.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public int indexRemove(int index);
|
||||
|
||||
/**
|
||||
* Clear all keys and values in the container.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Removes all elements from the collection and additionally releases any internal buffers.
|
||||
* Typically, if the object is to be reused, a simple {@link #clear()} should be a better
|
||||
* alternative since it'll avoid reallocation.
|
||||
*
|
||||
* @see #clear()
|
||||
*/
|
||||
public void release();
|
||||
|
||||
/**
|
||||
* Visually depict the distribution of keys.
|
||||
*
|
||||
* @param characters The number of characters to "squeeze" the entire buffer into.
|
||||
* @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
|
||||
* buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
|
||||
* between 1 and 9 is between.
|
||||
*/
|
||||
public String visualizeKeyDistribution(int characters);
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.*;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* An associative container from keys to (one or possibly more) values.
|
||||
*
|
||||
* @see CharContainer
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeVTypeAssociativeContainer.java")
|
||||
public interface CharLongAssociativeContainer extends Iterable<CharLongCursor> {
|
||||
/**
|
||||
* Returns a cursor over the entries (key-value pairs) in this map. The iterator is implemented as
|
||||
* a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()}. To read the current key and value use the cursor's public fields. An example
|
||||
* is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntShortCursor c : intShortMap) {
|
||||
* System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
|
||||
* }</pre>
|
||||
*
|
||||
* <p>The <code>index</code> field inside the cursor gives the internal index inside the
|
||||
* container's implementation. The interpretation of this index depends on to the container.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<CharLongCursor> iterator();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this container has an association to a value for the given key.
|
||||
*/
|
||||
public boolean containsKey(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the current size (number of assigned keys) in the container.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/**
|
||||
* @return Return <code>true</code> if this hash map contains no assigned keys.
|
||||
*/
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) present in a given container. An alias to:
|
||||
*
|
||||
* <pre>
|
||||
* keys().removeAll(container)
|
||||
* </pre>
|
||||
*
|
||||
* but with no additional overhead.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharContainer container);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharPredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharLongPredicate predicate);
|
||||
|
||||
/**
|
||||
* Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharLongProcedure}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*/
|
||||
public <T extends CharLongProcedure> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a given predicate to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharLongPredicate}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*
|
||||
* <p>The iteration is continued as long as the predicate returns <code>true</code>.
|
||||
*/
|
||||
public <T extends CharLongPredicate> T forEach(T predicate);
|
||||
|
||||
/**
|
||||
* Returns a collection of keys of this container. The returned collection is a view over the key
|
||||
* set and any modifications (if allowed) introduced to the collection will propagate to the
|
||||
* associative container immediately.
|
||||
*/
|
||||
public CharCollection keys();
|
||||
|
||||
/**
|
||||
* Returns a container view of all values present in this container. The returned collection is a
|
||||
* view over the key set and any modifications (if allowed) introduced to the collection will
|
||||
* propagate to the associative container immediately.
|
||||
*/
|
||||
public LongContainer values();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,205 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.CharLongCursor;
|
||||
|
||||
/** An associative container with unique binding from keys to a single value. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeVTypeMap.java")
|
||||
public interface CharLongMap extends CharLongAssociativeContainer {
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the default value for the value
|
||||
* type, if the key is not associated with any value. For numeric value types, this default
|
||||
* value is 0, for object types it is {@code null}.
|
||||
*/
|
||||
public long get(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the provided default value if the
|
||||
* key is not associated with any value.
|
||||
*/
|
||||
public long getOrDefault(char key, long defaultValue);
|
||||
|
||||
/**
|
||||
* Place a given key and value in the container.
|
||||
*
|
||||
* @return The value previously stored under the given key in the map is returned.
|
||||
*/
|
||||
public long put(char key, long value);
|
||||
|
||||
/**
|
||||
* If the specified key is not already associated with a value, associates it with the given
|
||||
* value.
|
||||
*
|
||||
* @return {@code true} if {@code key} did not exist and {@code value} was placed in the map,
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
public default boolean putIfAbsent(char key, long value) {
|
||||
int keyIndex = indexOf(key);
|
||||
if (indexExists(keyIndex)) {
|
||||
return false;
|
||||
} else {
|
||||
indexInsert(keyIndex, key, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts all keys from another container to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(CharLongAssociativeContainer container);
|
||||
|
||||
/**
|
||||
* Puts all keys from an iterable cursor to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(Iterable<? extends CharLongCursor> iterable);
|
||||
|
||||
/**
|
||||
* If <code>key</code> exists, <code>putValue</code> is inserted into the map, otherwise any
|
||||
* existing value is incremented by <code>additionValue</code>.
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param putValue The value to put if <code>key</code> does not exist.
|
||||
* @param incrementValue The value to add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public long putOrAdd(char key, long putValue, long incrementValue);
|
||||
|
||||
/**
|
||||
* An equivalent of calling
|
||||
*
|
||||
* <pre>
|
||||
* putOrAdd(key, additionValue, additionValue);
|
||||
* </pre>
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param additionValue The value to put or add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public long addTo(char key, long additionValue);
|
||||
|
||||
/**
|
||||
* Remove all values at the given key. The default value for the key type is returned if the value
|
||||
* does not exist in the map.
|
||||
*/
|
||||
public long remove(char key);
|
||||
|
||||
/**
|
||||
* Compares the specified object with this set for equality. Returns {@code true} if and only if
|
||||
* the specified object is also a {@link CharLongMap} and both objects contains exactly the same
|
||||
* key-value pairs.
|
||||
*/
|
||||
public boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* @return A hash code of elements stored in the map. The hash code is defined as a sum of hash
|
||||
* codes of keys and values stored within the set). Because sum is commutative, this ensures
|
||||
* that different order of elements in a set does not affect the hash code.
|
||||
*/
|
||||
public int hashCode();
|
||||
|
||||
/**
|
||||
* Returns a logical "index" of a given key that can be used to speed up follow-up value setters
|
||||
* or getters in certain scenarios (conditional logic).
|
||||
*
|
||||
* <p>The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
|
||||
* contiguous.
|
||||
*
|
||||
* <p>The index is valid only between map modifications (it will not be affected by read-only
|
||||
* operations like iteration or value retrievals).
|
||||
*
|
||||
* @see #indexExists
|
||||
* @see #indexGet
|
||||
* @see #indexInsert
|
||||
* @see #indexReplace
|
||||
* @param key The key to locate in the map.
|
||||
* @return A non-negative value of the logical "index" of the key in the map or a negative value
|
||||
* if the key did not exist.
|
||||
*/
|
||||
public int indexOf(char key);
|
||||
|
||||
/**
|
||||
* @see #indexOf
|
||||
* @param index The index of a given key, as returned from {@link #indexOf}.
|
||||
* @return Returns <code>true</code> if the index corresponds to an existing key or false
|
||||
* otherwise. This is equivalent to checking whether the index is a positive value (existing
|
||||
* keys) or a negative value (non-existing keys).
|
||||
*/
|
||||
public boolean indexExists(int index);
|
||||
|
||||
/**
|
||||
* Returns the value associated with an existing key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the value currently associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public long indexGet(int index);
|
||||
|
||||
/**
|
||||
* Replaces the value associated with an existing key and returns any previous value stored for
|
||||
* that key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public long indexReplace(int index, long newValue);
|
||||
|
||||
/**
|
||||
* Inserts a key-value pair for a key that is not present in the map. This method may help in
|
||||
* avoiding double recalculation of the key's hash.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
|
||||
* @throws AssertionError If assertions are enabled and the index corresponds to an existing key.
|
||||
*/
|
||||
public void indexInsert(int index, char key, long value);
|
||||
|
||||
/**
|
||||
* Removes a key-value pair at an index previously acquired from {@link #indexOf}.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of the key to remove, as returned from {@link #indexOf}.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public long indexRemove(int index);
|
||||
|
||||
/**
|
||||
* Clear all keys and values in the container.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Removes all elements from the collection and additionally releases any internal buffers.
|
||||
* Typically, if the object is to be reused, a simple {@link #clear()} should be a better
|
||||
* alternative since it'll avoid reallocation.
|
||||
*
|
||||
* @see #clear()
|
||||
*/
|
||||
public void release();
|
||||
|
||||
/**
|
||||
* Visually depict the distribution of keys.
|
||||
*
|
||||
* @param characters The number of characters to "squeeze" the entire buffer into.
|
||||
* @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
|
||||
* buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
|
||||
* between 1 and 9 is between.
|
||||
*/
|
||||
public String visualizeKeyDistribution(int characters);
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
/**
|
||||
* Marker interface for containers that can check if they contain a given object in at least time
|
||||
* <code>O(log n)</code> and ideally in amortized constant time <code>O(1)</code>.
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeLookupContainer.java")
|
||||
public interface CharLookupContainer extends CharContainer {
|
||||
public boolean contains(char e);
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.*;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* An associative container from keys to (one or possibly more) values.
|
||||
*
|
||||
* @see CharContainer
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeVTypeAssociativeContainer.java")
|
||||
public interface CharObjectAssociativeContainer<VType> extends Iterable<CharObjectCursor<VType>> {
|
||||
/**
|
||||
* Returns a cursor over the entries (key-value pairs) in this map. The iterator is implemented as
|
||||
* a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()}. To read the current key and value use the cursor's public fields. An example
|
||||
* is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntShortCursor c : intShortMap) {
|
||||
* System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
|
||||
* }</pre>
|
||||
*
|
||||
* <p>The <code>index</code> field inside the cursor gives the internal index inside the
|
||||
* container's implementation. The interpretation of this index depends on to the container.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<CharObjectCursor<VType>> iterator();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this container has an association to a value for the given key.
|
||||
*/
|
||||
public boolean containsKey(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the current size (number of assigned keys) in the container.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/**
|
||||
* @return Return <code>true</code> if this hash map contains no assigned keys.
|
||||
*/
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) present in a given container. An alias to:
|
||||
*
|
||||
* <pre>
|
||||
* keys().removeAll(container)
|
||||
* </pre>
|
||||
*
|
||||
* but with no additional overhead.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharContainer container);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharPredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharObjectPredicate<? super VType> predicate);
|
||||
|
||||
/**
|
||||
* Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharObjectProcedure}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*/
|
||||
public <T extends CharObjectProcedure<? super VType>> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a given predicate to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharObjectPredicate}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*
|
||||
* <p>The iteration is continued as long as the predicate returns <code>true</code>.
|
||||
*/
|
||||
public <T extends CharObjectPredicate<? super VType>> T forEach(T predicate);
|
||||
|
||||
/**
|
||||
* Returns a collection of keys of this container. The returned collection is a view over the key
|
||||
* set and any modifications (if allowed) introduced to the collection will propagate to the
|
||||
* associative container immediately.
|
||||
*/
|
||||
public CharCollection keys();
|
||||
|
||||
/**
|
||||
* Returns a container view of all values present in this container. The returned collection is a
|
||||
* view over the key set and any modifications (if allowed) introduced to the collection will
|
||||
* propagate to the associative container immediately.
|
||||
*/
|
||||
public ObjectContainer<VType> values();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,181 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.CharObjectCursor;
|
||||
|
||||
/** An associative container with unique binding from keys to a single value. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeVTypeMap.java")
|
||||
public interface CharObjectMap<VType> extends CharObjectAssociativeContainer<VType> {
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the default value for the value
|
||||
* type, if the key is not associated with any value. For numeric value types, this default
|
||||
* value is 0, for object types it is {@code null}.
|
||||
*/
|
||||
public VType get(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the provided default value if the
|
||||
* key is not associated with any value.
|
||||
*/
|
||||
public VType getOrDefault(char key, VType defaultValue);
|
||||
|
||||
/**
|
||||
* Place a given key and value in the container.
|
||||
*
|
||||
* @return The value previously stored under the given key in the map is returned.
|
||||
*/
|
||||
public VType put(char key, VType value);
|
||||
|
||||
/**
|
||||
* If the specified key is not already associated with a value, associates it with the given
|
||||
* value.
|
||||
*
|
||||
* @return {@code true} if {@code key} did not exist and {@code value} was placed in the map,
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
public default boolean putIfAbsent(char key, VType value) {
|
||||
int keyIndex = indexOf(key);
|
||||
if (indexExists(keyIndex)) {
|
||||
return false;
|
||||
} else {
|
||||
indexInsert(keyIndex, key, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts all keys from another container to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(CharObjectAssociativeContainer<? extends VType> container);
|
||||
|
||||
/**
|
||||
* Puts all keys from an iterable cursor to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(Iterable<? extends CharObjectCursor<? extends VType>> iterable);
|
||||
|
||||
/**
|
||||
* Remove all values at the given key. The default value for the key type is returned if the value
|
||||
* does not exist in the map.
|
||||
*/
|
||||
public VType remove(char key);
|
||||
|
||||
/**
|
||||
* Compares the specified object with this set for equality. Returns {@code true} if and only if
|
||||
* the specified object is also a {@link CharObjectMap} and both objects contains exactly the same
|
||||
* key-value pairs.
|
||||
*/
|
||||
public boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* @return A hash code of elements stored in the map. The hash code is defined as a sum of hash
|
||||
* codes of keys and values stored within the set). Because sum is commutative, this ensures
|
||||
* that different order of elements in a set does not affect the hash code.
|
||||
*/
|
||||
public int hashCode();
|
||||
|
||||
/**
|
||||
* Returns a logical "index" of a given key that can be used to speed up follow-up value setters
|
||||
* or getters in certain scenarios (conditional logic).
|
||||
*
|
||||
* <p>The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
|
||||
* contiguous.
|
||||
*
|
||||
* <p>The index is valid only between map modifications (it will not be affected by read-only
|
||||
* operations like iteration or value retrievals).
|
||||
*
|
||||
* @see #indexExists
|
||||
* @see #indexGet
|
||||
* @see #indexInsert
|
||||
* @see #indexReplace
|
||||
* @param key The key to locate in the map.
|
||||
* @return A non-negative value of the logical "index" of the key in the map or a negative value
|
||||
* if the key did not exist.
|
||||
*/
|
||||
public int indexOf(char key);
|
||||
|
||||
/**
|
||||
* @see #indexOf
|
||||
* @param index The index of a given key, as returned from {@link #indexOf}.
|
||||
* @return Returns <code>true</code> if the index corresponds to an existing key or false
|
||||
* otherwise. This is equivalent to checking whether the index is a positive value (existing
|
||||
* keys) or a negative value (non-existing keys).
|
||||
*/
|
||||
public boolean indexExists(int index);
|
||||
|
||||
/**
|
||||
* Returns the value associated with an existing key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the value currently associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public VType indexGet(int index);
|
||||
|
||||
/**
|
||||
* Replaces the value associated with an existing key and returns any previous value stored for
|
||||
* that key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public VType indexReplace(int index, VType newValue);
|
||||
|
||||
/**
|
||||
* Inserts a key-value pair for a key that is not present in the map. This method may help in
|
||||
* avoiding double recalculation of the key's hash.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
|
||||
* @throws AssertionError If assertions are enabled and the index corresponds to an existing key.
|
||||
*/
|
||||
public void indexInsert(int index, char key, VType value);
|
||||
|
||||
/**
|
||||
* Removes a key-value pair at an index previously acquired from {@link #indexOf}.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of the key to remove, as returned from {@link #indexOf}.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public VType indexRemove(int index);
|
||||
|
||||
/**
|
||||
* Clear all keys and values in the container.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Removes all elements from the collection and additionally releases any internal buffers.
|
||||
* Typically, if the object is to be reused, a simple {@link #clear()} should be a better
|
||||
* alternative since it'll avoid reallocation.
|
||||
*
|
||||
* @see #clear()
|
||||
*/
|
||||
public void release();
|
||||
|
||||
/**
|
||||
* Visually depict the distribution of keys.
|
||||
*
|
||||
* @param characters The number of characters to "squeeze" the entire buffer into.
|
||||
* @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
|
||||
* buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
|
||||
* between 1 and 9 is between.
|
||||
*/
|
||||
public String visualizeKeyDistribution(int characters);
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
/** A set of <code>char</code>s. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeSet.java")
|
||||
public interface CharSet extends CharCollection {
|
||||
/**
|
||||
* Adds <code>k</code> to the set.
|
||||
*
|
||||
* @return Returns <code>true</code> if this element was not part of the set before. Returns
|
||||
* <code>false</code> if an equal element is already part of the set, <b>does not replace the
|
||||
* existing element</b> with the argument.
|
||||
*/
|
||||
public boolean add(char k);
|
||||
|
||||
/**
|
||||
* Visually depict the distribution of keys.
|
||||
*
|
||||
* @param characters The number of characters to "squeeze" the entire buffer into.
|
||||
* @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
|
||||
* buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
|
||||
* between 1 and 9 is between.
|
||||
*/
|
||||
public String visualizeKeyDistribution(int characters);
|
||||
|
||||
/**
|
||||
* Adds all elements from the given {@link CharContainer} to this set.
|
||||
*
|
||||
* @return Returns the number of elements actually added as a result of this call (not previously
|
||||
* present in the set).
|
||||
* @since 0.9.1
|
||||
*/
|
||||
public int addAll(CharContainer container);
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.*;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* An associative container from keys to (one or possibly more) values.
|
||||
*
|
||||
* @see CharContainer
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeVTypeAssociativeContainer.java")
|
||||
public interface CharShortAssociativeContainer extends Iterable<CharShortCursor> {
|
||||
/**
|
||||
* Returns a cursor over the entries (key-value pairs) in this map. The iterator is implemented as
|
||||
* a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()}. To read the current key and value use the cursor's public fields. An example
|
||||
* is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntShortCursor c : intShortMap) {
|
||||
* System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
|
||||
* }</pre>
|
||||
*
|
||||
* <p>The <code>index</code> field inside the cursor gives the internal index inside the
|
||||
* container's implementation. The interpretation of this index depends on to the container.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<CharShortCursor> iterator();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this container has an association to a value for the given key.
|
||||
*/
|
||||
public boolean containsKey(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the current size (number of assigned keys) in the container.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/**
|
||||
* @return Return <code>true</code> if this hash map contains no assigned keys.
|
||||
*/
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) present in a given container. An alias to:
|
||||
*
|
||||
* <pre>
|
||||
* keys().removeAll(container)
|
||||
* </pre>
|
||||
*
|
||||
* but with no additional overhead.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharContainer container);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharPredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharShortPredicate predicate);
|
||||
|
||||
/**
|
||||
* Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharShortProcedure}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*/
|
||||
public <T extends CharShortProcedure> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a given predicate to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharShortPredicate}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*
|
||||
* <p>The iteration is continued as long as the predicate returns <code>true</code>.
|
||||
*/
|
||||
public <T extends CharShortPredicate> T forEach(T predicate);
|
||||
|
||||
/**
|
||||
* Returns a collection of keys of this container. The returned collection is a view over the key
|
||||
* set and any modifications (if allowed) introduced to the collection will propagate to the
|
||||
* associative container immediately.
|
||||
*/
|
||||
public CharCollection keys();
|
||||
|
||||
/**
|
||||
* Returns a container view of all values present in this container. The returned collection is a
|
||||
* view over the key set and any modifications (if allowed) introduced to the collection will
|
||||
* propagate to the associative container immediately.
|
||||
*/
|
||||
public ShortContainer values();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,205 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.CharShortCursor;
|
||||
|
||||
/** An associative container with unique binding from keys to a single value. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeVTypeMap.java")
|
||||
public interface CharShortMap extends CharShortAssociativeContainer {
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the default value for the value
|
||||
* type, if the key is not associated with any value. For numeric value types, this default
|
||||
* value is 0, for object types it is {@code null}.
|
||||
*/
|
||||
public short get(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the provided default value if the
|
||||
* key is not associated with any value.
|
||||
*/
|
||||
public short getOrDefault(char key, short defaultValue);
|
||||
|
||||
/**
|
||||
* Place a given key and value in the container.
|
||||
*
|
||||
* @return The value previously stored under the given key in the map is returned.
|
||||
*/
|
||||
public short put(char key, short value);
|
||||
|
||||
/**
|
||||
* If the specified key is not already associated with a value, associates it with the given
|
||||
* value.
|
||||
*
|
||||
* @return {@code true} if {@code key} did not exist and {@code value} was placed in the map,
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
public default boolean putIfAbsent(char key, short value) {
|
||||
int keyIndex = indexOf(key);
|
||||
if (indexExists(keyIndex)) {
|
||||
return false;
|
||||
} else {
|
||||
indexInsert(keyIndex, key, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts all keys from another container to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(CharShortAssociativeContainer container);
|
||||
|
||||
/**
|
||||
* Puts all keys from an iterable cursor to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(Iterable<? extends CharShortCursor> iterable);
|
||||
|
||||
/**
|
||||
* If <code>key</code> exists, <code>putValue</code> is inserted into the map, otherwise any
|
||||
* existing value is incremented by <code>additionValue</code>.
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param putValue The value to put if <code>key</code> does not exist.
|
||||
* @param incrementValue The value to add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public short putOrAdd(char key, short putValue, short incrementValue);
|
||||
|
||||
/**
|
||||
* An equivalent of calling
|
||||
*
|
||||
* <pre>
|
||||
* putOrAdd(key, additionValue, additionValue);
|
||||
* </pre>
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param additionValue The value to put or add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public short addTo(char key, short additionValue);
|
||||
|
||||
/**
|
||||
* Remove all values at the given key. The default value for the key type is returned if the value
|
||||
* does not exist in the map.
|
||||
*/
|
||||
public short remove(char key);
|
||||
|
||||
/**
|
||||
* Compares the specified object with this set for equality. Returns {@code true} if and only if
|
||||
* the specified object is also a {@link CharShortMap} and both objects contains exactly the same
|
||||
* key-value pairs.
|
||||
*/
|
||||
public boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* @return A hash code of elements stored in the map. The hash code is defined as a sum of hash
|
||||
* codes of keys and values stored within the set). Because sum is commutative, this ensures
|
||||
* that different order of elements in a set does not affect the hash code.
|
||||
*/
|
||||
public int hashCode();
|
||||
|
||||
/**
|
||||
* Returns a logical "index" of a given key that can be used to speed up follow-up value setters
|
||||
* or getters in certain scenarios (conditional logic).
|
||||
*
|
||||
* <p>The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
|
||||
* contiguous.
|
||||
*
|
||||
* <p>The index is valid only between map modifications (it will not be affected by read-only
|
||||
* operations like iteration or value retrievals).
|
||||
*
|
||||
* @see #indexExists
|
||||
* @see #indexGet
|
||||
* @see #indexInsert
|
||||
* @see #indexReplace
|
||||
* @param key The key to locate in the map.
|
||||
* @return A non-negative value of the logical "index" of the key in the map or a negative value
|
||||
* if the key did not exist.
|
||||
*/
|
||||
public int indexOf(char key);
|
||||
|
||||
/**
|
||||
* @see #indexOf
|
||||
* @param index The index of a given key, as returned from {@link #indexOf}.
|
||||
* @return Returns <code>true</code> if the index corresponds to an existing key or false
|
||||
* otherwise. This is equivalent to checking whether the index is a positive value (existing
|
||||
* keys) or a negative value (non-existing keys).
|
||||
*/
|
||||
public boolean indexExists(int index);
|
||||
|
||||
/**
|
||||
* Returns the value associated with an existing key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the value currently associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public short indexGet(int index);
|
||||
|
||||
/**
|
||||
* Replaces the value associated with an existing key and returns any previous value stored for
|
||||
* that key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public short indexReplace(int index, short newValue);
|
||||
|
||||
/**
|
||||
* Inserts a key-value pair for a key that is not present in the map. This method may help in
|
||||
* avoiding double recalculation of the key's hash.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
|
||||
* @throws AssertionError If assertions are enabled and the index corresponds to an existing key.
|
||||
*/
|
||||
public void indexInsert(int index, char key, short value);
|
||||
|
||||
/**
|
||||
* Removes a key-value pair at an index previously acquired from {@link #indexOf}.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of the key to remove, as returned from {@link #indexOf}.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public short indexRemove(int index);
|
||||
|
||||
/**
|
||||
* Clear all keys and values in the container.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Removes all elements from the collection and additionally releases any internal buffers.
|
||||
* Typically, if the object is to be reused, a simple {@link #clear()} should be a better
|
||||
* alternative since it'll avoid reallocation.
|
||||
*
|
||||
* @see #clear()
|
||||
*/
|
||||
public void release();
|
||||
|
||||
/**
|
||||
* Visually depict the distribution of keys.
|
||||
*
|
||||
* @param characters The number of characters to "squeeze" the entire buffer into.
|
||||
* @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
|
||||
* buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
|
||||
* between 1 and 9 is between.
|
||||
*/
|
||||
public String visualizeKeyDistribution(int characters);
|
||||
}
|
@ -1,137 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.CharCursor;
|
||||
|
||||
/**
|
||||
* A subclass of {@link CharArrayList} adding stack-related utility methods. The top of the stack is
|
||||
* at the <code>{@link #size()} - 1</code> element.
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeStack.java")
|
||||
public class CharStack extends CharArrayList {
|
||||
/** New instance with sane defaults. */
|
||||
public CharStack() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
*/
|
||||
public CharStack(int expectedElements) {
|
||||
super(expectedElements);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
* @param resizer Underlying buffer sizing strategy.
|
||||
*/
|
||||
public CharStack(int expectedElements, ArraySizingStrategy resizer) {
|
||||
super(expectedElements, resizer);
|
||||
}
|
||||
|
||||
/** Create a stack by pushing all elements of another container to it. */
|
||||
public CharStack(CharContainer container) {
|
||||
super(container);
|
||||
}
|
||||
|
||||
/** Adds one char to the stack. */
|
||||
public void push(char e1) {
|
||||
ensureBufferSpace(1);
|
||||
buffer[elementsCount++] = e1;
|
||||
}
|
||||
|
||||
/** Adds two chars to the stack. */
|
||||
public void push(char e1, char e2) {
|
||||
ensureBufferSpace(2);
|
||||
buffer[elementsCount++] = e1;
|
||||
buffer[elementsCount++] = e2;
|
||||
}
|
||||
|
||||
/** Adds three chars to the stack. */
|
||||
public void push(char e1, char e2, char e3) {
|
||||
ensureBufferSpace(3);
|
||||
buffer[elementsCount++] = e1;
|
||||
buffer[elementsCount++] = e2;
|
||||
buffer[elementsCount++] = e3;
|
||||
}
|
||||
|
||||
/** Adds four chars to the stack. */
|
||||
public void push(char e1, char e2, char e3, char e4) {
|
||||
ensureBufferSpace(4);
|
||||
buffer[elementsCount++] = e1;
|
||||
buffer[elementsCount++] = e2;
|
||||
buffer[elementsCount++] = e3;
|
||||
buffer[elementsCount++] = e4;
|
||||
}
|
||||
|
||||
/** Add a range of array elements to the stack. */
|
||||
public void push(char[] elements, int start, int len) {
|
||||
assert start >= 0 && len >= 0;
|
||||
|
||||
ensureBufferSpace(len);
|
||||
System.arraycopy(elements, start, buffer, elementsCount, len);
|
||||
elementsCount += len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg-signature method for pushing elements at the top of the stack.
|
||||
*
|
||||
* <p><b>This method is handy, but costly if used in tight loops (anonymous array passing)</b>
|
||||
*/
|
||||
public final void push(char... elements) {
|
||||
push(elements, 0, elements.length);
|
||||
}
|
||||
|
||||
/** Pushes all elements from another container to the top of the stack. */
|
||||
public int pushAll(CharContainer container) {
|
||||
return addAll(container);
|
||||
}
|
||||
|
||||
/** Pushes all elements from another iterable to the top of the stack. */
|
||||
public int pushAll(Iterable<? extends CharCursor> iterable) {
|
||||
return addAll(iterable);
|
||||
}
|
||||
|
||||
/** Discard an arbitrary number of elements from the top of the stack. */
|
||||
public void discard(int count) {
|
||||
assert elementsCount >= count;
|
||||
|
||||
elementsCount -= count;
|
||||
}
|
||||
|
||||
/** Discard the top element from the stack. */
|
||||
public void discard() {
|
||||
assert elementsCount > 0;
|
||||
|
||||
elementsCount--;
|
||||
}
|
||||
|
||||
/** Remove the top element from the stack and return it. */
|
||||
public char pop() {
|
||||
return removeLast();
|
||||
}
|
||||
|
||||
/** Peek at the top element on the stack. */
|
||||
public char peek() {
|
||||
assert elementsCount > 0;
|
||||
return buffer[elementsCount - 1];
|
||||
}
|
||||
|
||||
/** Create a stack by pushing a variable number of arguments to it. */
|
||||
public static CharStack from(char... elements) {
|
||||
final CharStack stack = new CharStack(elements.length);
|
||||
stack.push(elements);
|
||||
return stack;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public CharStack clone() {
|
||||
return (CharStack) super.clone();
|
||||
}
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* HPPC
|
||||
*
|
||||
* Copyright (C) 2010-2024 Carrot Search s.c. and contributors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Refer to the full license file "LICENSE.txt":
|
||||
* https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
|
||||
*/
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.internals.SuppressForbidden;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Constants used as defaults in containers.
|
||||
*
|
||||
* @see HashContainers
|
||||
*/
|
||||
public final class Containers {
|
||||
/** The default number of expected elements for containers. */
|
||||
public static final int DEFAULT_EXPECTED_ELEMENTS = 4;
|
||||
|
||||
/**
|
||||
* External initial seed value. We do not care about multiple assignments so not volatile.
|
||||
*
|
||||
* @see #randomSeed64()
|
||||
*/
|
||||
private static String testsSeedProperty;
|
||||
|
||||
/** Unique marker for {@link #testsSeedProperty}. */
|
||||
private static final String NOT_AVAILABLE = new String();
|
||||
|
||||
private Containers() {}
|
||||
|
||||
/**
|
||||
* Provides a (possibly) random initial seed for randomized stuff.
|
||||
*
|
||||
* <p>If <code>tests.seed</code> property is available and accessible, the returned value will be
|
||||
* derived from the value of that property and will be constant to ensure reproducibility in
|
||||
* presence of the randomized testing package.
|
||||
*
|
||||
* @see "https://github.com/carrotsearch/randomizedtesting"
|
||||
*/
|
||||
@SuppressForbidden
|
||||
public static long randomSeed64() {
|
||||
if (testsSeedProperty == null) {
|
||||
testsSeedProperty = System.getProperty("tests.seed", NOT_AVAILABLE);
|
||||
}
|
||||
|
||||
long initialSeed;
|
||||
if (testsSeedProperty != NOT_AVAILABLE) {
|
||||
initialSeed = testsSeedProperty.hashCode();
|
||||
} else {
|
||||
// Mix something that is changing over time (nanoTime)
|
||||
// ... with something that is thread-local and relatively unique
|
||||
// even for very short time-spans (new Object's address from a TLAB).
|
||||
initialSeed = System.nanoTime() ^ System.identityHashCode(new Object());
|
||||
}
|
||||
return BitMixer.mix64(initialSeed);
|
||||
}
|
||||
|
||||
/** Reset state for tests. */
|
||||
static void test$reset() {
|
||||
testsSeedProperty = null;
|
||||
}
|
||||
}
|
@ -1,776 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import static com.carrotsearch.hppc.Containers.*;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.DoubleCursor;
|
||||
import com.carrotsearch.hppc.predicates.DoublePredicate;
|
||||
import com.carrotsearch.hppc.procedures.DoubleProcedure;
|
||||
import java.util.*;
|
||||
|
||||
/** An array-backed {@link DoubleDeque}. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeArrayDeque.java")
|
||||
public class DoubleArrayDeque extends AbstractDoubleCollection
|
||||
implements DoubleDeque, Preallocable, Cloneable, Accountable {
|
||||
|
||||
/** Reuse the same strategy instance. */
|
||||
private static final BoundedProportionalArraySizingStrategy DEFAULT_SIZING_STRATEGY =
|
||||
BoundedProportionalArraySizingStrategy.DEFAULT_INSTANCE;
|
||||
|
||||
/** Internal array for storing elements of the deque. */
|
||||
public double[] buffer = DoubleArrayList.EMPTY_ARRAY;
|
||||
|
||||
/**
|
||||
* The index of the element at the head of the deque or an arbitrary number equal to tail if the
|
||||
* deque is empty.
|
||||
*/
|
||||
public int head;
|
||||
|
||||
/** The index at which the next element would be added to the tail of the deque. */
|
||||
public int tail;
|
||||
|
||||
/** Buffer resizing strategy. */
|
||||
protected final ArraySizingStrategy resizer;
|
||||
|
||||
/** New instance with sane defaults. */
|
||||
public DoubleArrayDeque() {
|
||||
this(DEFAULT_EXPECTED_ELEMENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
*/
|
||||
public DoubleArrayDeque(int expectedElements) {
|
||||
this(expectedElements, DEFAULT_SIZING_STRATEGY);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
* @param resizer Underlying buffer sizing strategy.
|
||||
*/
|
||||
public DoubleArrayDeque(int expectedElements, ArraySizingStrategy resizer) {
|
||||
assert resizer != null;
|
||||
this.resizer = resizer;
|
||||
ensureCapacity(expectedElements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deque from elements of another container, appending elements at the end of the
|
||||
* deque in the iteration order.
|
||||
*/
|
||||
public DoubleArrayDeque(DoubleContainer container) {
|
||||
this(container.size());
|
||||
addLast(container);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void addFirst(double e1) {
|
||||
int h = oneLeft(head, buffer.length);
|
||||
if (h == tail) {
|
||||
ensureBufferSpace(1);
|
||||
h = oneLeft(head, buffer.length);
|
||||
}
|
||||
buffer[head = h] = e1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg-signature method for adding elements at the front of this deque.
|
||||
*
|
||||
* <p><b>This method is handy, but costly if used in tight loops (anonymous array passing)</b>
|
||||
*
|
||||
* @param elements The elements to add.
|
||||
*/
|
||||
public final void addFirst(double... elements) {
|
||||
ensureBufferSpace(elements.length);
|
||||
for (double k : elements) {
|
||||
addFirst(k);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given container to the front of this deque.
|
||||
*
|
||||
* @param container The container to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addFirst(DoubleContainer container) {
|
||||
int size = container.size();
|
||||
ensureBufferSpace(size);
|
||||
|
||||
for (DoubleCursor cursor : container) {
|
||||
addFirst(cursor.value);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given iterable to the front of this deque.
|
||||
*
|
||||
* @param iterable The iterable to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addFirst(Iterable<? extends DoubleCursor> iterable) {
|
||||
int size = 0;
|
||||
for (DoubleCursor cursor : iterable) {
|
||||
addFirst(cursor.value);
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void addLast(double e1) {
|
||||
int t = oneRight(tail, buffer.length);
|
||||
if (head == t) {
|
||||
ensureBufferSpace(1);
|
||||
t = oneRight(tail, buffer.length);
|
||||
}
|
||||
buffer[tail] = e1;
|
||||
tail = t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg-signature method for adding elements at the end of this deque.
|
||||
*
|
||||
* <p><b>This method is handy, but costly if used in tight loops (anonymous array passing)</b>
|
||||
*
|
||||
* @param elements The elements to iterate over.
|
||||
*/
|
||||
public final void addLast(double... elements) {
|
||||
ensureBufferSpace(1);
|
||||
for (double k : elements) {
|
||||
addLast(k);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given container to the end of this deque.
|
||||
*
|
||||
* @param container The container to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addLast(DoubleContainer container) {
|
||||
int size = container.size();
|
||||
ensureBufferSpace(size);
|
||||
|
||||
for (DoubleCursor cursor : container) {
|
||||
addLast(cursor.value);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given iterable to the end of this deque.
|
||||
*
|
||||
* @param iterable The iterable to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addLast(Iterable<? extends DoubleCursor> iterable) {
|
||||
int size = 0;
|
||||
for (DoubleCursor cursor : iterable) {
|
||||
addLast(cursor.value);
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public double removeFirst() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
final double result = buffer[head];
|
||||
buffer[head] = 0d;
|
||||
head = oneRight(head, buffer.length);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public double removeLast() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
tail = oneLeft(tail, buffer.length);
|
||||
final double result = buffer[tail];
|
||||
buffer[tail] = 0d;
|
||||
return result;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public double getFirst() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
return buffer[head];
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public double getLast() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
return buffer[oneLeft(tail, buffer.length)];
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeFirst(double e1) {
|
||||
final int index = bufferIndexOf(e1);
|
||||
if (index >= 0) removeAtBufferIndex(index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index of the first (counting from head) element equal to <code>e1</code>. The index
|
||||
* points to the {@link #buffer} array.
|
||||
*
|
||||
* @param e1 The element to look for.
|
||||
* @return Returns the index of the first element equal to <code>e1</code> or <code>-1</code> if
|
||||
* not found.
|
||||
*/
|
||||
public int bufferIndexOf(double e1) {
|
||||
final int last = tail;
|
||||
final int bufLen = buffer.length;
|
||||
for (int i = head; i != last; i = oneRight(i, bufLen)) {
|
||||
if ((Double.doubleToLongBits(e1) == Double.doubleToLongBits(buffer[i]))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeLast(double e1) {
|
||||
final int index = lastBufferIndexOf(e1);
|
||||
if (index >= 0) {
|
||||
removeAtBufferIndex(index);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index of the last (counting from tail) element equal to <code>e1</code>. The index
|
||||
* points to the {@link #buffer} array.
|
||||
*
|
||||
* @param e1 The element to look for.
|
||||
* @return Returns the index of the first element equal to <code>e1</code> or <code>-1</code> if
|
||||
* not found.
|
||||
*/
|
||||
public int lastBufferIndexOf(double e1) {
|
||||
final int bufLen = buffer.length;
|
||||
final int last = oneLeft(head, bufLen);
|
||||
for (int i = oneLeft(tail, bufLen); i != last; i = oneLeft(i, bufLen)) {
|
||||
if ((Double.doubleToLongBits(e1) == Double.doubleToLongBits(buffer[i]))) return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(double e1) {
|
||||
int removed = 0;
|
||||
final int last = tail;
|
||||
final int bufLen = buffer.length;
|
||||
int from, to;
|
||||
for (from = to = head; from != last; from = oneRight(from, bufLen)) {
|
||||
if ((Double.doubleToLongBits(e1) == Double.doubleToLongBits(buffer[from]))) {
|
||||
buffer[from] = 0d;
|
||||
removed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = 0d;
|
||||
}
|
||||
|
||||
to = oneRight(to, bufLen);
|
||||
}
|
||||
|
||||
tail = to;
|
||||
return removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the element at <code>index</code> in the internal {#link {@link #buffer} array,
|
||||
* returning its value.
|
||||
*
|
||||
* @param index Index of the element to remove. The index must be located between {@link #head}
|
||||
* and {@link #tail} in modulo {@link #buffer} arithmetic.
|
||||
*/
|
||||
public void removeAtBufferIndex(int index) {
|
||||
assert (head <= tail ? index >= head && index < tail : index >= head || index < tail)
|
||||
: "Index out of range (head=" + head + ", tail=" + tail + ", index=" + index + ").";
|
||||
|
||||
// Cache fields in locals (hopefully moved to registers).
|
||||
final double[] buffer = this.buffer;
|
||||
final int bufLen = buffer.length;
|
||||
final int lastIndex = bufLen - 1;
|
||||
final int head = this.head;
|
||||
final int tail = this.tail;
|
||||
|
||||
final int leftChunk = Math.abs(index - head) % bufLen;
|
||||
final int rightChunk = Math.abs(tail - index) % bufLen;
|
||||
|
||||
if (leftChunk < rightChunk) {
|
||||
if (index >= head) {
|
||||
System.arraycopy(buffer, head, buffer, head + 1, leftChunk);
|
||||
} else {
|
||||
System.arraycopy(buffer, 0, buffer, 1, index);
|
||||
buffer[0] = buffer[lastIndex];
|
||||
System.arraycopy(buffer, head, buffer, head + 1, lastIndex - head);
|
||||
}
|
||||
buffer[head] = 0d;
|
||||
this.head = oneRight(head, bufLen);
|
||||
} else {
|
||||
if (index < tail) {
|
||||
System.arraycopy(buffer, index + 1, buffer, index, rightChunk);
|
||||
} else {
|
||||
System.arraycopy(buffer, index + 1, buffer, index, lastIndex - index);
|
||||
buffer[lastIndex] = buffer[0];
|
||||
System.arraycopy(buffer, 1, buffer, 0, tail);
|
||||
}
|
||||
buffer[tail] = 0d;
|
||||
this.tail = oneLeft(tail, bufLen);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int size() {
|
||||
if (head <= tail) return tail - head;
|
||||
else return (tail - head + buffer.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The internal array buffers are not released as a result of this call.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
if (head < tail) {
|
||||
Arrays.fill(buffer, head, tail, 0d);
|
||||
} else {
|
||||
Arrays.fill(buffer, 0, tail, 0d);
|
||||
Arrays.fill(buffer, head, buffer.length, 0d);
|
||||
}
|
||||
this.head = tail = 0;
|
||||
}
|
||||
|
||||
/** Release internal buffers of this deque and reallocate with the default buffer. */
|
||||
public void release() {
|
||||
this.head = tail = 0;
|
||||
buffer = DoubleArrayList.EMPTY_ARRAY;
|
||||
ensureBufferSpace(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure this container can hold at least the given number of elements without resizing its
|
||||
* buffers.
|
||||
*
|
||||
* @param expectedElements The total number of elements, inclusive.
|
||||
*/
|
||||
@Override
|
||||
public void ensureCapacity(int expectedElements) {
|
||||
ensureBufferSpace(expectedElements - size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the internal buffer has enough free slots to store <code>expectedAdditions</code>.
|
||||
* Increases internal buffer size if needed.
|
||||
*/
|
||||
protected void ensureBufferSpace(int expectedAdditions) {
|
||||
final int bufferLen = buffer.length;
|
||||
final int elementsCount = size();
|
||||
|
||||
if (elementsCount + expectedAdditions >= bufferLen) {
|
||||
final int emptySlot = 1; // deque invariant: always an empty slot.
|
||||
final int newSize = resizer.grow(bufferLen, elementsCount + emptySlot, expectedAdditions);
|
||||
assert newSize >= (elementsCount + expectedAdditions + emptySlot)
|
||||
: "Resizer failed to"
|
||||
+ " return sensible new size: "
|
||||
+ newSize
|
||||
+ " <= "
|
||||
+ (elementsCount + expectedAdditions);
|
||||
|
||||
try {
|
||||
final double[] newBuffer = (new double[newSize]);
|
||||
if (bufferLen > 0) {
|
||||
toArray(newBuffer);
|
||||
tail = elementsCount;
|
||||
head = 0;
|
||||
}
|
||||
this.buffer = newBuffer;
|
||||
} catch (OutOfMemoryError e) {
|
||||
throw new BufferAllocationException(
|
||||
"Not enough memory to allocate new buffers: %,d -> %,d", e, bufferLen, newSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public double[] toArray() {
|
||||
|
||||
final int size = size();
|
||||
return toArray((new double[size]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies elements of this deque to an array. The content of the <code>target</code> array is
|
||||
* filled from index 0 (head of the queue) to index <code>size() - 1</code> (tail of the queue).
|
||||
*
|
||||
* @param target The target array must be large enough to hold all elements.
|
||||
* @return Returns the target argument for chaining.
|
||||
*/
|
||||
public double[] toArray(double[] target) {
|
||||
assert target.length >= size() : "Target array must be >= " + size();
|
||||
|
||||
if (head < tail) {
|
||||
// The contents is not wrapped around. Just copy.
|
||||
System.arraycopy(buffer, head, target, 0, size());
|
||||
} else if (head > tail) {
|
||||
// The contents is split. Merge elements from the following indexes:
|
||||
// [head...buffer.length - 1][0, tail - 1]
|
||||
final int rightCount = buffer.length - head;
|
||||
System.arraycopy(buffer, head, target, 0, rightCount);
|
||||
System.arraycopy(buffer, 0, target, rightCount, tail);
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone this object. The returned clone will reuse the same hash function and array resizing
|
||||
* strategy.
|
||||
*/
|
||||
@Override
|
||||
public DoubleArrayDeque clone() {
|
||||
try {
|
||||
|
||||
DoubleArrayDeque cloned = (DoubleArrayDeque) super.clone();
|
||||
cloned.buffer = buffer.clone();
|
||||
return cloned;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Move one index to the left, wrapping around buffer. */
|
||||
protected static int oneLeft(int index, int modulus) {
|
||||
if (index >= 1) {
|
||||
return index - 1;
|
||||
}
|
||||
return modulus - 1;
|
||||
}
|
||||
|
||||
/** Move one index to the right, wrapping around buffer. */
|
||||
protected static int oneRight(int index, int modulus) {
|
||||
if (index + 1 == modulus) {
|
||||
return 0;
|
||||
}
|
||||
return index + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesAllocated() {
|
||||
// int: head, tail
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES * 2
|
||||
+ resizer.ramBytesAllocated()
|
||||
+ RamUsageEstimator.shallowSizeOfArray(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesUsed() {
|
||||
// int: head, tail
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES * 2
|
||||
+ resizer.ramBytesUsed()
|
||||
+ RamUsageEstimator.shallowUsedSizeOfArray(buffer, size());
|
||||
}
|
||||
|
||||
/** An iterator implementation for {@link ObjectArrayDeque#iterator}. */
|
||||
private final class ValueIterator extends AbstractIterator<DoubleCursor> {
|
||||
private final DoubleCursor cursor;
|
||||
private int remaining;
|
||||
|
||||
public ValueIterator() {
|
||||
cursor = new DoubleCursor();
|
||||
cursor.index = oneLeft(head, buffer.length);
|
||||
this.remaining = size();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DoubleCursor fetch() {
|
||||
if (remaining == 0) {
|
||||
return done();
|
||||
}
|
||||
|
||||
remaining--;
|
||||
cursor.value = buffer[cursor.index = oneRight(cursor.index, buffer.length)];
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
/** An iterator implementation for {@link ObjectArrayDeque#descendingIterator()}. */
|
||||
private final class DescendingValueIterator extends AbstractIterator<DoubleCursor> {
|
||||
private final DoubleCursor cursor;
|
||||
private int remaining;
|
||||
|
||||
public DescendingValueIterator() {
|
||||
cursor = new DoubleCursor();
|
||||
cursor.index = tail;
|
||||
this.remaining = size();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DoubleCursor fetch() {
|
||||
if (remaining == 0) return done();
|
||||
|
||||
remaining--;
|
||||
cursor.value = buffer[cursor.index = oneLeft(cursor.index, buffer.length)];
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a cursor over the values of this deque (in head to tail order). The iterator is
|
||||
* implemented as a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()} (to avoid boxing of primitive types). To read the current value (or index in
|
||||
* the deque's buffer) use the cursor's public fields. An example is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntValueCursor c : intDeque) {
|
||||
* System.out.println("buffer index=" + c.index + " value=" + c.value);
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public Iterator<DoubleCursor> iterator() {
|
||||
return new ValueIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a cursor over the values of this deque (in tail to head order). The iterator is
|
||||
* implemented as a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()} (to avoid boxing of primitive types). To read the current value (or index in
|
||||
* the deque's buffer) use the cursor's public fields. An example is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (Iterator<IntCursor> i = intDeque.descendingIterator(); i.hasNext();) {
|
||||
* final IntCursor c = i.next();
|
||||
* System.out.println("buffer index=" + c.index + " value=" + c.value);
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public Iterator<DoubleCursor> descendingIterator() {
|
||||
return new DescendingValueIterator();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends DoubleProcedure> T forEach(T procedure) {
|
||||
forEach(procedure, head, tail);
|
||||
return procedure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>procedure</code> to a slice of the deque, <code>fromIndex</code>, inclusive, to
|
||||
* <code>toIndex</code>, exclusive.
|
||||
*/
|
||||
private void forEach(DoubleProcedure procedure, int fromIndex, final int toIndex) {
|
||||
final double[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
procedure.apply(buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends DoublePredicate> T forEach(T predicate) {
|
||||
int fromIndex = head;
|
||||
int toIndex = tail;
|
||||
|
||||
final double[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
if (!predicate.apply(buffer[i])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return predicate;
|
||||
}
|
||||
|
||||
/** Applies <code>procedure</code> to all elements of this deque, tail to head. */
|
||||
@Override
|
||||
public <T extends DoubleProcedure> T descendingForEach(T procedure) {
|
||||
descendingForEach(procedure, head, tail);
|
||||
return procedure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>procedure</code> to a slice of the deque, <code>toIndex</code>, exclusive, down
|
||||
* to <code>fromIndex</code>, inclusive.
|
||||
*/
|
||||
private void descendingForEach(DoubleProcedure procedure, int fromIndex, final int toIndex) {
|
||||
if (fromIndex == toIndex) return;
|
||||
|
||||
final double[] buffer = this.buffer;
|
||||
int i = toIndex;
|
||||
do {
|
||||
i = oneLeft(i, buffer.length);
|
||||
procedure.apply(buffer[i]);
|
||||
} while (i != fromIndex);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends DoublePredicate> T descendingForEach(T predicate) {
|
||||
descendingForEach(predicate, head, tail);
|
||||
return predicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>predicate</code> to a slice of the deque, <code>toIndex</code>, exclusive, down
|
||||
* to <code>fromIndex</code>, inclusive or until the predicate returns <code>false</code>.
|
||||
*/
|
||||
private void descendingForEach(DoublePredicate predicate, int fromIndex, final int toIndex) {
|
||||
if (fromIndex == toIndex) return;
|
||||
|
||||
final double[] buffer = this.buffer;
|
||||
int i = toIndex;
|
||||
do {
|
||||
i = oneLeft(i, buffer.length);
|
||||
if (!predicate.apply(buffer[i])) {
|
||||
break;
|
||||
}
|
||||
} while (i != fromIndex);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(DoublePredicate predicate) {
|
||||
final double[] buffer = this.buffer;
|
||||
final int last = tail;
|
||||
final int bufLen = buffer.length;
|
||||
int removed = 0;
|
||||
int from, to;
|
||||
from = to = head;
|
||||
try {
|
||||
for (from = to = head; from != last; from = oneRight(from, bufLen)) {
|
||||
if (predicate.apply(buffer[from])) {
|
||||
buffer[from] = 0d;
|
||||
removed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = 0d;
|
||||
}
|
||||
|
||||
to = oneRight(to, bufLen);
|
||||
}
|
||||
} finally {
|
||||
// Keep the deque in consistent state even if the predicate throws an exception.
|
||||
for (; from != last; from = oneRight(from, bufLen)) {
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = 0d;
|
||||
}
|
||||
|
||||
to = oneRight(to, bufLen);
|
||||
}
|
||||
tail = to;
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean contains(double e) {
|
||||
int fromIndex = head;
|
||||
int toIndex = tail;
|
||||
|
||||
final double[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
if ((Double.doubleToLongBits(e) == Double.doubleToLongBits(buffer[i]))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = 1;
|
||||
int fromIndex = head;
|
||||
int toIndex = tail;
|
||||
|
||||
final double[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
h = 31 * h + BitMixer.mix(this.buffer[i]);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> only if the other object is an instance of the same class and with
|
||||
* the same elements.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return (this == obj)
|
||||
|| (obj != null && getClass() == obj.getClass() && equalElements(getClass().cast(obj)));
|
||||
}
|
||||
|
||||
/** Compare order-aligned elements against another {@link DoubleDeque}. */
|
||||
protected boolean equalElements(DoubleArrayDeque other) {
|
||||
int max = size();
|
||||
if (other.size() != max) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Iterator<DoubleCursor> i1 = this.iterator();
|
||||
Iterator<? extends DoubleCursor> i2 = other.iterator();
|
||||
|
||||
while (i1.hasNext() && i2.hasNext()) {
|
||||
if (!(Double.doubleToLongBits(i1.next().value) == Double.doubleToLongBits(i2.next().value))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return !i1.hasNext() && !i2.hasNext();
|
||||
}
|
||||
|
||||
/** Create a new deque by pushing a variable number of arguments to the end of it. */
|
||||
public static DoubleArrayDeque from(double... elements) {
|
||||
final DoubleArrayDeque coll = new DoubleArrayDeque(elements.length);
|
||||
coll.addLast(elements);
|
||||
return coll;
|
||||
}
|
||||
}
|
@ -1,586 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import static com.carrotsearch.hppc.Containers.*;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.DoublePredicate;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.*;
|
||||
import java.util.stream.DoubleStream;
|
||||
|
||||
/** An array-backed list of doubles. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeArrayList.java")
|
||||
public class DoubleArrayList extends AbstractDoubleCollection
|
||||
implements DoubleIndexedContainer, Preallocable, Cloneable, Accountable {
|
||||
/** An immutable empty buffer (array). */
|
||||
public static final double[] EMPTY_ARRAY = new double[0];
|
||||
|
||||
;
|
||||
|
||||
/** Reuse the same strategy instance. */
|
||||
private static final BoundedProportionalArraySizingStrategy DEFAULT_SIZING_STRATEGY =
|
||||
BoundedProportionalArraySizingStrategy.DEFAULT_INSTANCE;
|
||||
|
||||
/**
|
||||
* Internal array for storing the list. The array may be larger than the current size ({@link
|
||||
* #size()}).
|
||||
*/
|
||||
public double[] buffer = EMPTY_ARRAY;
|
||||
|
||||
/** Current number of elements stored in {@link #buffer}. */
|
||||
public int elementsCount;
|
||||
|
||||
/** Buffer resizing strategy. */
|
||||
protected final ArraySizingStrategy resizer;
|
||||
|
||||
/** New instance with sane defaults. */
|
||||
public DoubleArrayList() {
|
||||
this(DEFAULT_EXPECTED_ELEMENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
*/
|
||||
public DoubleArrayList(int expectedElements) {
|
||||
this(expectedElements, DEFAULT_SIZING_STRATEGY);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
* @param resizer Underlying buffer sizing strategy.
|
||||
*/
|
||||
public DoubleArrayList(int expectedElements, ArraySizingStrategy resizer) {
|
||||
assert resizer != null;
|
||||
this.resizer = resizer;
|
||||
buffer = Arrays.copyOf(buffer, expectedElements);
|
||||
}
|
||||
|
||||
/** Creates a new list from the elements of another container in its iteration order. */
|
||||
public DoubleArrayList(DoubleContainer container) {
|
||||
this(container.size());
|
||||
addAll(container);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void add(double e1) {
|
||||
ensureBufferSpace(1);
|
||||
buffer[elementsCount++] = e1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends two elements at the end of the list. To add more than two elements, use <code>add
|
||||
* </code> (vararg-version) or access the buffer directly (tight loop).
|
||||
*/
|
||||
public void add(double e1, double e2) {
|
||||
ensureBufferSpace(2);
|
||||
buffer[elementsCount++] = e1;
|
||||
buffer[elementsCount++] = e2;
|
||||
}
|
||||
|
||||
/** Add all elements from a range of given array to the list. */
|
||||
public void add(double[] elements, int start, int length) {
|
||||
assert length >= 0 : "Length must be >= 0";
|
||||
|
||||
ensureBufferSpace(length);
|
||||
System.arraycopy(elements, start, buffer, elementsCount, length);
|
||||
elementsCount += length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg-signature method for adding elements at the end of the list.
|
||||
*
|
||||
* <p><b>This method is handy, but costly if used in tight loops (anonymous array passing)</b>
|
||||
*/
|
||||
public final void add(double... elements) {
|
||||
add(elements, 0, elements.length);
|
||||
}
|
||||
|
||||
/** Adds all elements from another container. */
|
||||
public int addAll(DoubleContainer container) {
|
||||
final int size = container.size();
|
||||
ensureBufferSpace(size);
|
||||
|
||||
for (DoubleCursor cursor : container) {
|
||||
add(cursor.value);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/** Adds all elements from another iterable. */
|
||||
public int addAll(Iterable<? extends DoubleCursor> iterable) {
|
||||
int size = 0;
|
||||
for (DoubleCursor cursor : iterable) {
|
||||
add(cursor.value);
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void insert(int index, double e1) {
|
||||
assert (index >= 0 && index <= size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
|
||||
ensureBufferSpace(1);
|
||||
System.arraycopy(buffer, index, buffer, index + 1, elementsCount - index);
|
||||
buffer[index] = e1;
|
||||
elementsCount++;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public double get(int index) {
|
||||
assert (index >= 0 && index < size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
return buffer[index];
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public double set(int index, double e1) {
|
||||
assert (index >= 0 && index < size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
final double v = buffer[index];
|
||||
buffer[index] = e1;
|
||||
return v;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public double removeAt(int index) {
|
||||
assert (index >= 0 && index < size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
final double v = buffer[index];
|
||||
System.arraycopy(buffer, index + 1, buffer, index, --elementsCount - index);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public double removeLast() {
|
||||
assert elementsCount > 0;
|
||||
|
||||
final double v = buffer[--elementsCount];
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void removeRange(int fromIndex, int toIndex) {
|
||||
assert (fromIndex >= 0 && fromIndex <= size())
|
||||
: "Index " + fromIndex + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
assert (toIndex >= 0 && toIndex <= size())
|
||||
: "Index " + toIndex + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
assert fromIndex <= toIndex : "fromIndex must be <= toIndex: " + fromIndex + ", " + toIndex;
|
||||
|
||||
System.arraycopy(buffer, toIndex, buffer, fromIndex, elementsCount - toIndex);
|
||||
final int count = toIndex - fromIndex;
|
||||
elementsCount -= count;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean removeElement(double e1) {
|
||||
return removeFirst(e1) != -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeFirst(double e1) {
|
||||
final int index = indexOf(e1);
|
||||
if (index >= 0) removeAt(index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeLast(double e1) {
|
||||
final int index = lastIndexOf(e1);
|
||||
if (index >= 0) removeAt(index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(double e1) {
|
||||
int to = 0;
|
||||
for (int from = 0; from < elementsCount; from++) {
|
||||
if ((Double.doubleToLongBits(e1) == Double.doubleToLongBits(buffer[from]))) {
|
||||
continue;
|
||||
}
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
}
|
||||
to++;
|
||||
}
|
||||
final int deleted = elementsCount - to;
|
||||
this.elementsCount = to;
|
||||
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean contains(double e1) {
|
||||
return indexOf(e1) >= 0;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int indexOf(double e1) {
|
||||
for (int i = 0; i < elementsCount; i++) {
|
||||
if ((Double.doubleToLongBits(e1) == Double.doubleToLongBits(buffer[i]))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int lastIndexOf(double e1) {
|
||||
for (int i = elementsCount - 1; i >= 0; i--) {
|
||||
if ((Double.doubleToLongBits(e1) == Double.doubleToLongBits(buffer[i]))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return elementsCount == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure this container can hold at least the given number of elements without resizing its
|
||||
* buffers.
|
||||
*
|
||||
* @param expectedElements The total number of elements, inclusive.
|
||||
*/
|
||||
@Override
|
||||
public void ensureCapacity(int expectedElements) {
|
||||
final int bufferLen = (buffer == null ? 0 : buffer.length);
|
||||
if (expectedElements > bufferLen) {
|
||||
ensureBufferSpace(expectedElements - size());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the internal buffer has enough free slots to store <code>expectedAdditions</code>.
|
||||
* Increases internal buffer size if needed.
|
||||
*/
|
||||
protected void ensureBufferSpace(int expectedAdditions) {
|
||||
final int bufferLen = (buffer == null ? 0 : buffer.length);
|
||||
if (elementsCount + expectedAdditions > bufferLen) {
|
||||
final int newSize = resizer.grow(bufferLen, elementsCount, expectedAdditions);
|
||||
assert newSize >= elementsCount + expectedAdditions
|
||||
: "Resizer failed to"
|
||||
+ " return sensible new size: "
|
||||
+ newSize
|
||||
+ " <= "
|
||||
+ (elementsCount + expectedAdditions);
|
||||
|
||||
this.buffer = Arrays.copyOf(buffer, newSize);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate or expand the list to the new size. If the list is truncated, the buffer will not be
|
||||
* reallocated (use {@link #trimToSize()} if you need a truncated buffer), but the truncated
|
||||
* values will be reset to the default value (zero). If the list is expanded, the elements beyond
|
||||
* the current size are initialized with JVM-defaults (zero or <code>null</code> values).
|
||||
*/
|
||||
public void resize(int newSize) {
|
||||
if (newSize <= buffer.length) {
|
||||
if (newSize < elementsCount) {
|
||||
Arrays.fill(buffer, newSize, elementsCount, 0d);
|
||||
} else {
|
||||
Arrays.fill(buffer, elementsCount, newSize, 0d);
|
||||
}
|
||||
} else {
|
||||
ensureCapacity(newSize);
|
||||
}
|
||||
this.elementsCount = newSize;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int size() {
|
||||
return elementsCount;
|
||||
}
|
||||
|
||||
/** Trim the internal buffer to the current size. */
|
||||
public void trimToSize() {
|
||||
if (size() != this.buffer.length) {
|
||||
this.buffer = toArray();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of stored elements to zero. Releases and initializes the internal storage array
|
||||
* to default values. To clear the list without cleaning the buffer, simply set the {@link
|
||||
* #elementsCount} field to zero.
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
Arrays.fill(buffer, 0, elementsCount, 0d);
|
||||
this.elementsCount = 0;
|
||||
}
|
||||
|
||||
/** Sets the number of stored elements to zero and releases the internal storage array. */
|
||||
@Override
|
||||
public void release() {
|
||||
this.buffer = EMPTY_ARRAY;
|
||||
this.elementsCount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The returned array is sized to match exactly the number of elements of the stack.
|
||||
*/
|
||||
@Override
|
||||
public double[] toArray() {
|
||||
|
||||
return Arrays.copyOf(buffer, elementsCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DoubleStream stream() {
|
||||
|
||||
return Arrays.stream(buffer, 0, size());
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public DoubleIndexedContainer sort() {
|
||||
Arrays.sort(buffer, 0, elementsCount);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public DoubleIndexedContainer reverse() {
|
||||
for (int i = 0, mid = elementsCount >> 1, j = elementsCount - 1; i < mid; i++, j--) {
|
||||
double tmp = buffer[i];
|
||||
buffer[i] = buffer[j];
|
||||
buffer[j] = tmp;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone this object. The returned clone will reuse the same hash function and array resizing
|
||||
* strategy.
|
||||
*/
|
||||
@Override
|
||||
public DoubleArrayList clone() {
|
||||
try {
|
||||
|
||||
final DoubleArrayList cloned = (DoubleArrayList) super.clone();
|
||||
cloned.buffer = buffer.clone();
|
||||
return cloned;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = 1, max = elementsCount;
|
||||
for (int i = 0; i < max; i++) {
|
||||
h = 31 * h + BitMixer.mix(this.buffer[i]);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> only if the other object is an instance of the same class and with
|
||||
* the same elements.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return (this == obj)
|
||||
|| (obj != null && getClass() == obj.getClass() && equalElements(getClass().cast(obj)));
|
||||
}
|
||||
|
||||
/** Compare index-aligned elements against another {@link DoubleIndexedContainer}. */
|
||||
protected boolean equalElements(DoubleArrayList other) {
|
||||
int max = size();
|
||||
if (other.size() != max) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < max; i++) {
|
||||
if (!(Double.doubleToLongBits(get(i)) == Double.doubleToLongBits(other.get(i)))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesAllocated() {
|
||||
// int: elementsCount
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES
|
||||
+ resizer.ramBytesAllocated()
|
||||
+ RamUsageEstimator.shallowSizeOfArray(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesUsed() {
|
||||
// int: elementsCount
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES
|
||||
+ resizer.ramBytesUsed()
|
||||
+ RamUsageEstimator.shallowUsedSizeOfArray(buffer, elementsCount);
|
||||
}
|
||||
|
||||
/** An iterator implementation for {@link DoubleArrayList#iterator}. */
|
||||
static final class ValueIterator extends AbstractIterator<DoubleCursor> {
|
||||
private final DoubleCursor cursor;
|
||||
|
||||
private final double[] buffer;
|
||||
private final int size;
|
||||
|
||||
public ValueIterator(double[] buffer, int size) {
|
||||
this.cursor = new DoubleCursor();
|
||||
this.cursor.index = -1;
|
||||
this.size = size;
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DoubleCursor fetch() {
|
||||
if (cursor.index + 1 == size) return done();
|
||||
|
||||
cursor.value = buffer[++cursor.index];
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public Iterator<DoubleCursor> iterator() {
|
||||
return new ValueIterator(buffer, size());
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends DoubleProcedure> T forEach(T procedure) {
|
||||
return forEach(procedure, 0, size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>procedure</code> to a slice of the list, <code>fromIndex</code>, inclusive, to
|
||||
* <code>toIndex</code>, exclusive.
|
||||
*/
|
||||
public <T extends DoubleProcedure> T forEach(T procedure, int fromIndex, final int toIndex) {
|
||||
assert (fromIndex >= 0 && fromIndex <= size())
|
||||
: "Index " + fromIndex + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
assert (toIndex >= 0 && toIndex <= size())
|
||||
: "Index " + toIndex + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
|
||||
assert fromIndex <= toIndex : "fromIndex must be <= toIndex: " + fromIndex + ", " + toIndex;
|
||||
|
||||
final double[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i < toIndex; i++) {
|
||||
procedure.apply(buffer[i]);
|
||||
}
|
||||
|
||||
return procedure;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(DoublePredicate predicate) {
|
||||
final double[] buffer = this.buffer;
|
||||
final int elementsCount = this.elementsCount;
|
||||
int to = 0;
|
||||
int from = 0;
|
||||
try {
|
||||
for (; from < elementsCount; from++) {
|
||||
if (predicate.apply(buffer[from])) {
|
||||
buffer[from] = 0d;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = 0d;
|
||||
}
|
||||
to++;
|
||||
}
|
||||
} finally {
|
||||
// Keep the list in a consistent state, even if the predicate throws an exception.
|
||||
for (; from < elementsCount; from++) {
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = 0d;
|
||||
}
|
||||
to++;
|
||||
}
|
||||
|
||||
this.elementsCount = to;
|
||||
}
|
||||
|
||||
return elementsCount - to;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends DoublePredicate> T forEach(T predicate) {
|
||||
return forEach(predicate, 0, size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>predicate</code> to a slice of the list, <code>fromIndex</code>, inclusive, to
|
||||
* <code>toIndex</code>, exclusive, or until predicate returns <code>false</code>.
|
||||
*/
|
||||
public <T extends DoublePredicate> T forEach(T predicate, int fromIndex, final int toIndex) {
|
||||
assert (fromIndex >= 0 && fromIndex <= size())
|
||||
: "Index " + fromIndex + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
assert (toIndex >= 0 && toIndex <= size())
|
||||
: "Index " + toIndex + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
assert fromIndex <= toIndex : "fromIndex must be <= toIndex: " + fromIndex + ", " + toIndex;
|
||||
|
||||
final double[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i < toIndex; i++) {
|
||||
if (!predicate.apply(buffer[i])) break;
|
||||
}
|
||||
|
||||
return predicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a list from a variable number of arguments or an array of <code>double</code>. The
|
||||
* elements are copied from the argument to the internal buffer.
|
||||
*/
|
||||
public static DoubleArrayList from(double... elements) {
|
||||
final DoubleArrayList list = new DoubleArrayList(elements.length);
|
||||
list.add(elements);
|
||||
return list;
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
/**
|
||||
* Reused buffer visualization routines.
|
||||
*
|
||||
* @see DoubleSet#visualizeKeyDistribution(int)
|
||||
* @see DoubleVTypeMap#visualizeKeyDistribution(int)
|
||||
*/
|
||||
class DoubleBufferVisualizer {
|
||||
static String visualizeKeyDistribution(double[] buffer, int max, int characters) {
|
||||
final StringBuilder b = new StringBuilder();
|
||||
final char[] chars = ".123456789X".toCharArray();
|
||||
for (int i = 1, start = -1; i <= characters; i++) {
|
||||
int end = (int) ((long) i * max / characters);
|
||||
|
||||
if (start + 1 <= end) {
|
||||
int taken = 0;
|
||||
int slots = 0;
|
||||
for (int slot = start + 1; slot <= end; slot++, slots++) {
|
||||
if (!(Double.doubleToLongBits(buffer[slot]) == 0)) {
|
||||
taken++;
|
||||
}
|
||||
}
|
||||
b.append(chars[Math.min(chars.length - 1, taken * chars.length / slots)]);
|
||||
start = end;
|
||||
}
|
||||
}
|
||||
while (b.length() < characters) {
|
||||
b.append(' ');
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.predicates.DoublePredicate;
|
||||
|
||||
/**
|
||||
* A collection allows basic, efficient operations on sets of elements (difference and
|
||||
* intersection).
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeCollection.java")
|
||||
public interface DoubleCollection extends DoubleContainer {
|
||||
/**
|
||||
* Removes all occurrences of <code>e</code> from this collection.
|
||||
*
|
||||
* @param e Element to be removed from this collection, if present.
|
||||
* @return The number of removed elements as a result of this call.
|
||||
*/
|
||||
public int removeAll(double e);
|
||||
|
||||
/**
|
||||
* Removes all elements in this collection that are present in <code>c</code>.
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int removeAll(DoubleLookupContainer c);
|
||||
|
||||
/**
|
||||
* Removes all elements in this collection for which the given predicate returns <code>true</code>
|
||||
* .
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int removeAll(DoublePredicate predicate);
|
||||
|
||||
/**
|
||||
* Keeps all elements in this collection that are present in <code>c</code>. Runs in time
|
||||
* proportional to the number of elements in this collection. Equivalent of sets intersection.
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int retainAll(DoubleLookupContainer c);
|
||||
|
||||
/**
|
||||
* Keeps all elements in this collection for which the given predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int retainAll(DoublePredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all elements from this collection.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Removes all elements from the collection and additionally releases any internal buffers.
|
||||
* Typically, if the object is to be reused, a simple {@link #clear()} should be a better
|
||||
* alternative since it'll avoid reallocation.
|
||||
*
|
||||
* @see #clear()
|
||||
*/
|
||||
public void release();
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.DoubleCursor;
|
||||
import com.carrotsearch.hppc.predicates.DoublePredicate;
|
||||
import com.carrotsearch.hppc.procedures.DoubleProcedure;
|
||||
import java.util.Iterator;
|
||||
|
||||
/** A generic container holding <code>double</code>s. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeContainer.java")
|
||||
public interface DoubleContainer extends Iterable<DoubleCursor> {
|
||||
/**
|
||||
* Returns an iterator to a cursor traversing the collection. The order of traversal is not
|
||||
* defined. More than one cursor may be active at a time. The behavior of iterators is undefined
|
||||
* if structural changes are made to the underlying collection.
|
||||
*
|
||||
* <p>The iterator is implemented as a cursor and it returns <b>the same cursor instance</b> on
|
||||
* every call to {@link Iterator#next()} (to avoid boxing of primitive types). To read the current
|
||||
* list's value (or index in the list) use the cursor's public fields. An example is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (DoubleCursor<double> c : container) {
|
||||
* System.out.println("index=" + c.index + " value=" + c.value);
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public Iterator<DoubleCursor> iterator();
|
||||
|
||||
/**
|
||||
* Lookup a given element in the container. This operation has no speed guarantees (may be linear
|
||||
* with respect to the size of this container).
|
||||
*
|
||||
* @return Returns <code>true</code> if this container has an element equal to <code>e</code>.
|
||||
*/
|
||||
public boolean contains(double e);
|
||||
|
||||
/**
|
||||
* Return the current number of elements in this container. The time for calculating the
|
||||
* container's size may take <code>O(n)</code> time, although implementing classes should try to
|
||||
* maintain the current size and return in constant time.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/** Shortcut for <code>size() == 0</code>. */
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Copies all elements of this container to an array.
|
||||
*
|
||||
* <p>The returned array is always a copy, regardless of the storage used by the container.
|
||||
*/
|
||||
public double[] toArray();
|
||||
|
||||
/**
|
||||
* Applies a <code>procedure</code> to all container elements. Returns the argument (any subclass
|
||||
* of {@link DoubleProcedure}. This lets the caller to call methods of the argument by chaining
|
||||
* the call (even if the argument is an anonymous type) to retrieve computed values, for example
|
||||
* (IntContainer):
|
||||
*
|
||||
* <pre>
|
||||
* int count = container.forEach(new IntProcedure() {
|
||||
* int count; // this is a field declaration in an anonymous class.
|
||||
*
|
||||
* public void apply(int value) {
|
||||
* count++;
|
||||
* }
|
||||
* }).count;
|
||||
* </pre>
|
||||
*/
|
||||
public <T extends DoubleProcedure> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a <code>predicate</code> to container elements as long, as the predicate returns <code>
|
||||
* true</code>. The iteration is interrupted otherwise.
|
||||
*/
|
||||
public <T extends DoublePredicate> T forEach(T predicate);
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.DoubleCursor;
|
||||
import com.carrotsearch.hppc.predicates.DoublePredicate;
|
||||
import com.carrotsearch.hppc.procedures.DoubleProcedure;
|
||||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* A linear collection that supports element insertion and removal at both ends.
|
||||
*
|
||||
* @see Deque
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeDeque.java")
|
||||
public interface DoubleDeque extends DoubleCollection {
|
||||
/**
|
||||
* Removes the first element that equals <code>e</code>.
|
||||
*
|
||||
* @return The deleted element's index or <code>-1</code> if the element was not found.
|
||||
*/
|
||||
public int removeFirst(double e);
|
||||
|
||||
/**
|
||||
* Removes the last element that equals <code>e</code>.
|
||||
*
|
||||
* @return The deleted element's index or <code>-1</code> if the element was not found.
|
||||
*/
|
||||
public int removeLast(double e);
|
||||
|
||||
/** Inserts the specified element at the front of this deque. */
|
||||
public void addFirst(double e);
|
||||
|
||||
/** Inserts the specified element at the end of this deque. */
|
||||
public void addLast(double e);
|
||||
|
||||
/**
|
||||
* Retrieves and removes the first element of this deque.
|
||||
*
|
||||
* @return the head (first) element of this deque.
|
||||
*/
|
||||
public double removeFirst();
|
||||
|
||||
/**
|
||||
* Retrieves and removes the last element of this deque.
|
||||
*
|
||||
* @return the tail of this deque.
|
||||
*/
|
||||
public double removeLast();
|
||||
|
||||
/**
|
||||
* Retrieves the first element of this deque but does not remove it.
|
||||
*
|
||||
* @return the head of this deque.
|
||||
*/
|
||||
public double getFirst();
|
||||
|
||||
/**
|
||||
* Retrieves the last element of this deque but does not remove it.
|
||||
*
|
||||
* @return the head of this deque.
|
||||
*/
|
||||
public double getLast();
|
||||
|
||||
/**
|
||||
* @return An iterator over elements in this deque in tail-to-head order.
|
||||
*/
|
||||
public Iterator<DoubleCursor> descendingIterator();
|
||||
|
||||
/** Applies a <code>procedure</code> to all elements in tail-to-head order. */
|
||||
public <T extends DoubleProcedure> T descendingForEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a <code>predicate</code> to container elements as long, as the predicate returns <code>
|
||||
* true</code>. The iteration is interrupted otherwise.
|
||||
*/
|
||||
public <T extends DoublePredicate> T descendingForEach(T predicate);
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import java.util.RandomAccess;
|
||||
import java.util.stream.DoubleStream;
|
||||
|
||||
/**
|
||||
* An indexed container provides random access to elements based on an <code>index</code>. Indexes
|
||||
* are zero-based.
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeIndexedContainer.java")
|
||||
public interface DoubleIndexedContainer extends DoubleCollection, RandomAccess {
|
||||
/**
|
||||
* Removes the first element that equals <code>e1</code>, returning whether an element has been
|
||||
* removed.
|
||||
*/
|
||||
public boolean removeElement(double e1);
|
||||
|
||||
/**
|
||||
* Removes the first element that equals <code>e1</code>, returning its deleted position or <code>
|
||||
* -1</code> if the element was not found.
|
||||
*/
|
||||
public int removeFirst(double e1);
|
||||
|
||||
/**
|
||||
* Removes the last element that equals <code>e1</code>, returning its deleted position or <code>
|
||||
* -1</code> if the element was not found.
|
||||
*/
|
||||
public int removeLast(double e1);
|
||||
|
||||
/**
|
||||
* Returns the index of the first occurrence of the specified element in this list, or -1 if this
|
||||
* list does not contain the element.
|
||||
*/
|
||||
public int indexOf(double e1);
|
||||
|
||||
/**
|
||||
* Returns the index of the last occurrence of the specified element in this list, or -1 if this
|
||||
* list does not contain the element.
|
||||
*/
|
||||
public int lastIndexOf(double e1);
|
||||
|
||||
/** Adds an element to the end of this container (the last index is incremented by one). */
|
||||
public void add(double e1);
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the specified position in this list.
|
||||
*
|
||||
* @param index The index at which the element should be inserted, shifting any existing and
|
||||
* subsequent elements to the right.
|
||||
*/
|
||||
public void insert(int index, double e1);
|
||||
|
||||
/**
|
||||
* Replaces the element at the specified position in this list with the specified element.
|
||||
*
|
||||
* @return Returns the previous value in the list.
|
||||
*/
|
||||
public double set(int index, double e1);
|
||||
|
||||
/**
|
||||
* @return Returns the element at index <code>index</code> from the list.
|
||||
*/
|
||||
public double get(int index);
|
||||
|
||||
/**
|
||||
* Removes the element at the specified position in this container and returns it.
|
||||
*
|
||||
* @see #removeFirst
|
||||
* @see #removeLast
|
||||
* @see #removeAll
|
||||
*/
|
||||
public double removeAt(int index);
|
||||
|
||||
/** Removes and returns the last element of this container. This container must not be empty. */
|
||||
public double removeLast();
|
||||
|
||||
/**
|
||||
* Removes from this container all of the elements with indexes between <code>fromIndex</code>,
|
||||
* inclusive, and <code>toIndex</code>, exclusive.
|
||||
*/
|
||||
public void removeRange(int fromIndex, int toIndex);
|
||||
|
||||
/** Returns this container elements as a stream. */
|
||||
public DoubleStream stream();
|
||||
|
||||
/** Sorts the elements in this container and returns this container. */
|
||||
public DoubleIndexedContainer sort();
|
||||
|
||||
/** Reverses the elements in this container and returns this container. */
|
||||
public DoubleIndexedContainer reverse();
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
/**
|
||||
* Marker interface for containers that can check if they contain a given object in at least time
|
||||
* <code>O(log n)</code> and ideally in amortized constant time <code>O(1)</code>.
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeLookupContainer.java")
|
||||
public interface DoubleLookupContainer extends DoubleContainer {
|
||||
public boolean contains(double e);
|
||||
}
|
@ -1,600 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.DoubleCursor;
|
||||
import com.carrotsearch.hppc.procedures.DoubleProcedure;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Space-efficient index that enables fast rank/range search operations on a sorted sequence of
|
||||
* <code>double</code>.
|
||||
*
|
||||
* <p>Implementation of the PGM-Index described at <a
|
||||
* href="https://pgm.di.unipi.it/">https://pgm.di.unipi.it/</a>, based on the paper
|
||||
*
|
||||
* <pre>
|
||||
* Paolo Ferragina and Giorgio Vinciguerra.
|
||||
* The PGM-index: a fully-dynamic compressed learned index with provable worst-case bounds.
|
||||
* PVLDB, 13(8): 1162-1175, 2020.
|
||||
* </pre>
|
||||
*
|
||||
* It provides {@code rank} and {@code range} search operations. {@code indexOf()} is faster than
|
||||
* B+Tree, and the index is much more compact. {@code contains()} is between 4x to 7x slower than
|
||||
* {@code IntHashSet#contains()}, but between 2.5x to 3x faster than {@link Arrays#binarySearch}.
|
||||
*
|
||||
* <p>Its compactness (40KB for 200MB of keys) makes it efficient for very large collections, the
|
||||
* index fitting easily in the L2 cache. The {@code epsilon} parameter should be set according to
|
||||
* the desired space-time trade-off. A smaller value makes the estimation more precise and the range
|
||||
* smaller but at the cost of increased space usage. In practice, {@code epsilon} 64 is a good sweet
|
||||
* spot.
|
||||
*
|
||||
* <p>Internally the index uses an optimal piecewise linear mapping from keys to their position in
|
||||
* the sorted order. This mapping is represented as a sequence of linear models (segments) which are
|
||||
* themselves recursively indexed by other piecewise linear mappings.
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypePgmIndex.java")
|
||||
public class DoublePgmIndex implements Accountable {
|
||||
|
||||
/** Empty immutable DoublePgmIndex. */
|
||||
public static final DoublePgmIndex EMPTY = new DoubleEmptyPgmIndex();
|
||||
|
||||
/**
|
||||
* Epsilon approximation range when searching the list of keys. Controls the size of the returned
|
||||
* search range, strictly greater than 0. It should be set according to the desired space-time
|
||||
* trade-off. A smaller value makes the estimation more precise and the range smaller but at the
|
||||
* cost of increased space usage.
|
||||
*
|
||||
* <p>With EPSILON=64 the benchmark with 200MB of keys shows that this PGM index requires only 2%
|
||||
* additional memory on average (40KB). It depends on the distribution of the keys. This epsilon
|
||||
* value is good even for 2MB of keys. With EPSILON=32: +5% speed, but 4x space (160KB).
|
||||
*/
|
||||
public static final int EPSILON = 64;
|
||||
|
||||
/**
|
||||
* Epsilon approximation range for the segments layers. Controls the size of the search range in
|
||||
* the hierarchical segment lists, strictly greater than 0.
|
||||
*/
|
||||
public static final int EPSILON_RECURSIVE = 32;
|
||||
|
||||
/** Size of a key, measured in {@link Integer#BYTES} because the key is stored in an int[]. */
|
||||
public static final int KEY_SIZE =
|
||||
RamUsageEstimator.primitiveSizes.get(double.class) / Integer.BYTES;
|
||||
|
||||
/** 2x {@link #KEY_SIZE}. */
|
||||
public static final int DOUBLE_KEY_SIZE = KEY_SIZE * 2;
|
||||
|
||||
/**
|
||||
* Data size of a segment, measured in {@link Integer#BYTES}, because segments are stored in an
|
||||
* int[].
|
||||
*/
|
||||
public static final int SEGMENT_DATA_SIZE = KEY_SIZE * 3;
|
||||
|
||||
/** Initial value of the exponential jump when scanning out of the epsilon range. */
|
||||
public static final int BEYOND_EPSILON_JUMP = 16;
|
||||
|
||||
/**
|
||||
* The list of keys for which this index is built. It is sorted and may contain duplicate
|
||||
* elements.
|
||||
*/
|
||||
public final DoubleArrayList keys;
|
||||
|
||||
/** The size of the key set. That is, the number of distinct elements in {@link #keys}. */
|
||||
public final int size;
|
||||
|
||||
/** The lowest key in {@link #keys}. */
|
||||
public final double firstKey;
|
||||
|
||||
/** The highest key in {@link #keys}. */
|
||||
public final double lastKey;
|
||||
|
||||
/** The epsilon range used to build this index. */
|
||||
public final int epsilon;
|
||||
|
||||
/** The recursive epsilon range used to build this index. */
|
||||
public final int epsilonRecursive;
|
||||
|
||||
/** The offsets in {@link #segmentData} of the first segment of each segment level. */
|
||||
public final int[] levelOffsets;
|
||||
|
||||
/** The index data. It contains all the segments for all the levels. */
|
||||
public final int[] segmentData;
|
||||
|
||||
private DoublePgmIndex(
|
||||
DoubleArrayList keys,
|
||||
int size,
|
||||
int epsilon,
|
||||
int epsilonRecursive,
|
||||
int[] levelOffsets,
|
||||
int[] segmentData) {
|
||||
assert keys.size() > 0;
|
||||
assert size > 0 && size <= keys.size();
|
||||
assert epsilon > 0;
|
||||
assert epsilonRecursive > 0;
|
||||
this.keys = keys;
|
||||
this.size = size;
|
||||
firstKey = keys.get(0);
|
||||
lastKey = keys.get(keys.size() - 1);
|
||||
this.epsilon = epsilon;
|
||||
this.epsilonRecursive = epsilonRecursive;
|
||||
this.levelOffsets = levelOffsets;
|
||||
this.segmentData = segmentData;
|
||||
}
|
||||
|
||||
/** Empty set constructor. */
|
||||
private DoublePgmIndex() {
|
||||
keys = new DoubleArrayList(0);
|
||||
size = 0;
|
||||
firstKey = 0d;
|
||||
lastKey = 0d;
|
||||
epsilon = 0;
|
||||
epsilonRecursive = 0;
|
||||
levelOffsets = new int[0];
|
||||
segmentData = levelOffsets;
|
||||
}
|
||||
|
||||
/** Returns the size of the key set. That is, the number of distinct elements in {@link #keys}. */
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/** Returns whether this key set is empty. */
|
||||
public boolean isEmpty() {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
/** Returns whether this key set contains the given key. */
|
||||
public boolean contains(double key) {
|
||||
return indexOf(key) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the specified key, and returns its index in the element list. If multiple elements are
|
||||
* equal to the specified key, there is no guarantee which one will be found.
|
||||
*
|
||||
* @return The index of the searched key if it is present; otherwise, {@code (-(<i>insertion
|
||||
* point</i>) - 1)}. The <i>insertion point</i> is defined as the point at which the key would
|
||||
* be inserted into the list: the index of the first element greater than the key, or {@link
|
||||
* #keys}#{@code size()} if all the elements are less than the specified key. Note that this
|
||||
* guarantees that the return value will be >= 0 if and only if the key is found.
|
||||
*/
|
||||
public int indexOf(double key) {
|
||||
if (key < firstKey) {
|
||||
return -1;
|
||||
}
|
||||
if (key > lastKey) {
|
||||
return -keys.size() - 1;
|
||||
}
|
||||
final int[] segmentData = this.segmentData;
|
||||
int segmentDataIndex = findSegment(key);
|
||||
int nextIntercept = (int) getIntercept(segmentDataIndex + SEGMENT_DATA_SIZE, segmentData);
|
||||
int index =
|
||||
Math.min(
|
||||
approximateIndex(key, segmentDataIndex, segmentData),
|
||||
Math.min(nextIntercept, keys.size() - 1));
|
||||
assert index >= 0 && index < keys.size();
|
||||
double k = keys.get(index);
|
||||
if (key < k) {
|
||||
// Scan sequentially before the approximated index, within epsilon range.
|
||||
final int fromIndex = Math.max(index - epsilon - 1, 0);
|
||||
while (--index >= fromIndex) {
|
||||
k = keys.get(index);
|
||||
if (key > k) {
|
||||
return -index - 2;
|
||||
}
|
||||
if ((Double.doubleToLongBits(key) == Double.doubleToLongBits(k))) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
// Continue scanning out of the epsilon range.
|
||||
// This might happen in rare cases of precision error during the approximation
|
||||
// computation for longs (we don't have long double 128 bits in Java).
|
||||
// This might also happen in rare corner cases of large duplicate elements
|
||||
// sequence at the epsilon range boundary.
|
||||
index++;
|
||||
int jump = BEYOND_EPSILON_JUMP;
|
||||
do {
|
||||
int loIndex = Math.max(index - jump, 0);
|
||||
if (key >= keys.get(loIndex)) {
|
||||
return Arrays.binarySearch(keys.buffer, loIndex, index, key);
|
||||
}
|
||||
index = loIndex;
|
||||
jump <<= 1;
|
||||
} while (index > 0);
|
||||
return -1;
|
||||
} else if ((Double.doubleToLongBits(key) == Double.doubleToLongBits(k))) {
|
||||
return index;
|
||||
} else {
|
||||
// Scan sequentially after the approximated index, within epsilon range.
|
||||
final int toIndex = Math.min(index + epsilon + 3, keys.size());
|
||||
while (++index < toIndex) {
|
||||
k = keys.get(index);
|
||||
if (key < k) {
|
||||
return -index - 1;
|
||||
}
|
||||
if ((Double.doubleToLongBits(key) == Double.doubleToLongBits(k))) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
// Continue scanning out of the epsilon range.
|
||||
int jump = BEYOND_EPSILON_JUMP;
|
||||
do {
|
||||
int hiIndex = Math.min(index + jump, keys.size());
|
||||
if (key <= keys.get(hiIndex)) {
|
||||
return Arrays.binarySearch(keys.buffer, index, hiIndex, key);
|
||||
}
|
||||
index = hiIndex;
|
||||
jump <<= 1;
|
||||
} while (index < keys.size());
|
||||
return -keys.size() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns, for any value {@code x}, the number of keys in the sorted list which are smaller than
|
||||
* {@code x}. It is equal to {@link #indexOf} if {@code x} belongs to the list, or -{@link
|
||||
* #indexOf}-1 otherwise.
|
||||
*
|
||||
* <p>If multiple elements are equal to the specified key, there is no guarantee which one will be
|
||||
* found.
|
||||
*
|
||||
* @return The index of the searched key if it is present; otherwise, the {@code insertion point}.
|
||||
* The <i>insertion point</i> is defined as the point at which the key would be inserted into
|
||||
* the list: the index of the first element greater than the key, or {@link #keys}#{@code
|
||||
* size()} if all the elements are less than the specified key. Note that this method always
|
||||
* returns a value >= 0.
|
||||
*/
|
||||
public int rank(double x) {
|
||||
int index = indexOf(x);
|
||||
return index >= 0 ? index : -index - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of keys in the list that are greater than or equal to {@code minKey}
|
||||
* (inclusive), and less than or equal to {@code maxKey} (inclusive).
|
||||
*/
|
||||
public int rangeCardinality(double minKey, double maxKey) {
|
||||
int fromIndex = rank(minKey);
|
||||
int maxIndex = indexOf(maxKey);
|
||||
int toIndex = maxIndex >= 0 ? maxIndex + 1 : -maxIndex - 1;
|
||||
return Math.max(toIndex - fromIndex, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over the keys in the list that are greater than or equal to {@code minKey}
|
||||
* (inclusive), and less than or equal to {@code maxKey} (inclusive).
|
||||
*/
|
||||
public Iterator<DoubleCursor> rangeIterator(double minKey, double maxKey) {
|
||||
int fromIndex = rank(minKey);
|
||||
return new RangeIterator(keys, fromIndex, maxKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies {@code procedure} to the keys in the list that are greater than or equal to {@code
|
||||
* minKey} (inclusive), and less than or equal to {@code maxKey} (inclusive).
|
||||
*/
|
||||
public <T extends DoubleProcedure> T forEachInRange(T procedure, double minKey, double maxKey) {
|
||||
final double[] buffer = keys.buffer;
|
||||
double k;
|
||||
for (int i = rank(minKey), size = keys.size(); i < size && (k = buffer[i]) <= maxKey; i++) {
|
||||
procedure.apply(k);
|
||||
}
|
||||
return procedure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Estimates the allocated memory. It does not count the memory for the list of keys, only for the
|
||||
* index itself.
|
||||
*/
|
||||
@Override
|
||||
public long ramBytesAllocated() {
|
||||
// int: size, epsilon, epsilonRecursive
|
||||
// double: firstKey, lastKey
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ 3 * Integer.BYTES
|
||||
+ 2L * KEY_SIZE * Integer.BYTES
|
||||
// + keys.ramBytesAllocated()
|
||||
+ RamUsageEstimator.shallowSizeOfArray(levelOffsets)
|
||||
+ RamUsageEstimator.shallowSizeOfArray(segmentData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Estimates the bytes that are actually used. It does not count the memory for the list of keys,
|
||||
* only for the index itself.
|
||||
*/
|
||||
@Override
|
||||
public long ramBytesUsed() {
|
||||
// int: size, epsilon, epsilonRecursive
|
||||
// double: firstKey, lastKey
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ 3 * Integer.BYTES
|
||||
+ 2L * KEY_SIZE * Integer.BYTES
|
||||
// + keys.ramBytesUsed()
|
||||
+ RamUsageEstimator.shallowSizeOfArray(levelOffsets)
|
||||
+ RamUsageEstimator.shallowSizeOfArray(segmentData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the segment responsible for a given key, that is, the rightmost segment having its first
|
||||
* key <= the searched key.
|
||||
*
|
||||
* @return the segment data index; or -1 if none.
|
||||
*/
|
||||
private int findSegment(double key) {
|
||||
assert key >= firstKey && key <= lastKey;
|
||||
final int epsilonRecursive = this.epsilonRecursive;
|
||||
final int[] levelOffsets = this.levelOffsets;
|
||||
final int[] segmentData = this.segmentData;
|
||||
int level = levelOffsets.length - 1;
|
||||
int segmentDataIndex = levelOffsets[level] * SEGMENT_DATA_SIZE;
|
||||
while (--level >= 0) {
|
||||
int nextIntercept = (int) getIntercept(segmentDataIndex + SEGMENT_DATA_SIZE, segmentData);
|
||||
int index = Math.min(approximateIndex(key, segmentDataIndex, segmentData), nextIntercept);
|
||||
assert index >= 0 && index <= levelOffsets[level + 1] - levelOffsets[level] - 1;
|
||||
int sdIndex = (levelOffsets[level] + index) * SEGMENT_DATA_SIZE;
|
||||
if (getKey(sdIndex, segmentData) <= key) {
|
||||
// Scan sequentially segments after the approximated index, within the epsilon range.
|
||||
final int levelNumSegments = levelOffsets[level + 1] - levelOffsets[level] - 1;
|
||||
final int toIndex = Math.min(index + epsilonRecursive + 3, levelNumSegments);
|
||||
while (index++ < toIndex && getKey(sdIndex + SEGMENT_DATA_SIZE, segmentData) <= key) {
|
||||
sdIndex += SEGMENT_DATA_SIZE;
|
||||
}
|
||||
} else {
|
||||
// Scan sequentially segments before the approximated index, within the epsilon range.
|
||||
final int fromIndex = Math.max(index - epsilonRecursive - 1, 0);
|
||||
while (index-- > fromIndex) {
|
||||
sdIndex -= SEGMENT_DATA_SIZE;
|
||||
if (getKey(sdIndex, segmentData) <= key) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
segmentDataIndex = sdIndex;
|
||||
}
|
||||
assert segmentDataIndex >= 0;
|
||||
return segmentDataIndex;
|
||||
}
|
||||
|
||||
private int approximateIndex(double key, int segmentDataIndex, int[] segmentData) {
|
||||
long intercept = getIntercept(segmentDataIndex, segmentData);
|
||||
double sKey = getKey(segmentDataIndex, segmentData);
|
||||
double slope = getSlope(segmentDataIndex, segmentData);
|
||||
int index = (int) (slope * ((double) key - sKey) + intercept);
|
||||
return Math.max(index, 0);
|
||||
}
|
||||
|
||||
private static long getIntercept(int segmentDataIndex, int[] segmentData) {
|
||||
return PgmIndexUtil.getIntercept(segmentDataIndex, segmentData, KEY_SIZE);
|
||||
}
|
||||
|
||||
private double getKey(int segmentDataIndex, int[] segmentData) {
|
||||
return PgmIndexUtil.getKey(segmentDataIndex + KEY_SIZE, segmentData, 0d);
|
||||
}
|
||||
|
||||
private static double getSlope(int segmentDataIndex, int[] segmentData) {
|
||||
return PgmIndexUtil.getSlope(segmentDataIndex + DOUBLE_KEY_SIZE, segmentData, KEY_SIZE);
|
||||
}
|
||||
|
||||
/** Empty immutable PGM Index. */
|
||||
private static class DoubleEmptyPgmIndex extends DoublePgmIndex {
|
||||
|
||||
private final Iterator<DoubleCursor> emptyIterator = new DoubleEmptyIterator();
|
||||
|
||||
@Override
|
||||
public int indexOf(double key) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<DoubleCursor> rangeIterator(double minKey, double maxKey) {
|
||||
return emptyIterator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends DoubleProcedure> T forEachInRange(T procedure, double minKey, double maxKey) {
|
||||
return procedure;
|
||||
}
|
||||
|
||||
private static class DoubleEmptyIterator extends AbstractIterator<DoubleCursor> {
|
||||
@Override
|
||||
protected DoubleCursor fetch() {
|
||||
return done();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Iterator over a range of elements in a sorted array. */
|
||||
protected static class RangeIterator extends AbstractIterator<DoubleCursor> {
|
||||
private final double[] buffer;
|
||||
private final int size;
|
||||
private final DoubleCursor cursor;
|
||||
private final double maxKey;
|
||||
|
||||
/** Range iterator from {@code fromIndex} (inclusive) to {@code maxKey} (inclusive). */
|
||||
protected RangeIterator(DoubleArrayList keys, int fromIndex, double maxKey) {
|
||||
this.buffer = keys.buffer;
|
||||
this.size = keys.size();
|
||||
this.cursor = new DoubleCursor();
|
||||
this.cursor.index = fromIndex;
|
||||
this.maxKey = maxKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DoubleCursor fetch() {
|
||||
if (cursor.index >= size) {
|
||||
return done();
|
||||
}
|
||||
cursor.value = buffer[cursor.index++];
|
||||
if (cursor.value > maxKey) {
|
||||
cursor.index = size;
|
||||
return done();
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
/** Builds a {@link DoublePgmIndex} on a provided sorted list of keys. */
|
||||
public static class DoubleBuilder implements PlaModel.SegmentConsumer, Accountable {
|
||||
|
||||
protected DoubleArrayList keys;
|
||||
protected int epsilon = EPSILON;
|
||||
protected int epsilonRecursive = EPSILON_RECURSIVE;
|
||||
protected PlaModel plam;
|
||||
protected int size;
|
||||
protected IntArrayList segmentData;
|
||||
protected int numSegments;
|
||||
|
||||
/** Sets the sorted list of keys to build the index for; duplicate elements are allowed. */
|
||||
public DoubleBuilder setSortedKeys(DoubleArrayList keys) {
|
||||
this.keys = keys;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Sets the sorted array of keys to build the index for; duplicate elements are allowed. */
|
||||
public DoubleBuilder setSortedKeys(double[] keys, int length) {
|
||||
DoubleArrayList keyList = new DoubleArrayList(0);
|
||||
keyList.buffer = keys;
|
||||
keyList.elementsCount = length;
|
||||
return setSortedKeys(keyList);
|
||||
}
|
||||
|
||||
/** Sets the epsilon range to use when learning the segments for the list of keys. */
|
||||
public DoubleBuilder setEpsilon(int epsilon) {
|
||||
if (epsilon <= 0) {
|
||||
throw new IllegalArgumentException("epsilon must be > 0");
|
||||
}
|
||||
this.epsilon = epsilon;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the recursive epsilon range to use when learning the segments for the segment levels.
|
||||
*/
|
||||
public DoubleBuilder setEpsilonRecursive(int epsilonRecursive) {
|
||||
if (epsilonRecursive <= 0) {
|
||||
throw new IllegalArgumentException("epsilonRecursive must be > 0");
|
||||
}
|
||||
this.epsilonRecursive = epsilonRecursive;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Builds the {@link DoublePgmIndex}; or {@link #EMPTY} if there are no keys in the list. */
|
||||
public DoublePgmIndex build() {
|
||||
if (keys == null || keys.size() == 0) {
|
||||
return (DoublePgmIndex) EMPTY;
|
||||
}
|
||||
plam = new PlaModel(epsilon);
|
||||
|
||||
int segmentsInitialCapacity =
|
||||
Math.min(
|
||||
Math.max(keys.size() / (2 * epsilon * epsilon) * SEGMENT_DATA_SIZE, 16), 1 << 19);
|
||||
segmentData = new IntArrayList(segmentsInitialCapacity);
|
||||
IntArrayList levelOffsets = new IntArrayList(16);
|
||||
|
||||
int levelOffset = 0;
|
||||
levelOffsets.add(levelOffset);
|
||||
int levelNumSegments = buildFirstLevel();
|
||||
while (levelNumSegments > 1) {
|
||||
int nextLevelOffset = numSegments;
|
||||
levelOffsets.add(nextLevelOffset);
|
||||
levelNumSegments = buildUpperLevel(levelOffset, levelNumSegments);
|
||||
levelOffset = nextLevelOffset;
|
||||
}
|
||||
|
||||
int[] segmentDataFinal = segmentData.toArray();
|
||||
int[] levelOffsetsFinal = levelOffsets.toArray();
|
||||
return new DoublePgmIndex(
|
||||
keys, size, epsilon, epsilonRecursive, levelOffsetsFinal, segmentDataFinal);
|
||||
}
|
||||
|
||||
private int buildFirstLevel() {
|
||||
assert numSegments == 0;
|
||||
int numKeys = keys.size();
|
||||
int size = 0;
|
||||
double key = keys.get(0);
|
||||
size++;
|
||||
plam.addKey(key, 0, this);
|
||||
for (int i = 1; i < numKeys; i++) {
|
||||
double nextKey = keys.get(i);
|
||||
if (!(Double.doubleToLongBits(nextKey) == Double.doubleToLongBits(key))) {
|
||||
key = nextKey;
|
||||
plam.addKey(key, i, this);
|
||||
size++;
|
||||
}
|
||||
}
|
||||
plam.finish(this);
|
||||
addSentinelSegment(numKeys);
|
||||
this.size = size;
|
||||
return numSegments - 1;
|
||||
}
|
||||
|
||||
private int buildUpperLevel(int levelOffset, int levelNumSegments) {
|
||||
plam.setEpsilon(epsilonRecursive);
|
||||
assert numSegments > 0;
|
||||
int initialNumSegments = numSegments;
|
||||
int segmentDataIndex = levelOffset * SEGMENT_DATA_SIZE;
|
||||
double key = getKey(segmentDataIndex, segmentData.buffer);
|
||||
plam.addKey(key, 0, this);
|
||||
for (int i = 1; i < levelNumSegments; i++) {
|
||||
segmentDataIndex += SEGMENT_DATA_SIZE;
|
||||
double nextKey = getKey(segmentDataIndex, segmentData.buffer);
|
||||
if (!(Double.doubleToLongBits(nextKey) == Double.doubleToLongBits(key))) {
|
||||
key = nextKey;
|
||||
plam.addKey(key, i, this);
|
||||
}
|
||||
}
|
||||
plam.finish(this);
|
||||
addSentinelSegment(levelNumSegments);
|
||||
return numSegments - initialNumSegments - 1;
|
||||
}
|
||||
|
||||
private double getKey(int segmentDataIndex, int[] segmentData) {
|
||||
return PgmIndexUtil.getKey(segmentDataIndex + KEY_SIZE, segmentData, 0d);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a sentinel segment that is used to give a limit for the position approximation, but does
|
||||
* not count in the number of segments per level.
|
||||
*/
|
||||
private void addSentinelSegment(int endIndex) {
|
||||
// This sentinel segment is used in findSegment().
|
||||
accept(Double.MAX_VALUE, 0d, endIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(double firstKey, double slope, long intercept) {
|
||||
PgmIndexUtil.addIntercept(intercept, segmentData, KEY_SIZE);
|
||||
PgmIndexUtil.addKey((double) firstKey, segmentData);
|
||||
PgmIndexUtil.addSlope(slope, segmentData, KEY_SIZE);
|
||||
numSegments++;
|
||||
assert segmentData.size() == numSegments * SEGMENT_DATA_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Estimates the allocated memory. It does not count the memory for the list of keys, only for
|
||||
* the builder itself.
|
||||
*/
|
||||
@Override
|
||||
public long ramBytesAllocated() {
|
||||
// int: epsilon, epsilonRecursive, size, numSegments
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ 4 * Integer.BYTES
|
||||
// + keys.ramBytesAllocated()
|
||||
+ plam.ramBytesAllocated()
|
||||
+ segmentData.ramBytesAllocated();
|
||||
}
|
||||
|
||||
/**
|
||||
* Estimates the bytes that are actually used. It does not count the memory for the list of
|
||||
* keys, only for the builder itself.
|
||||
*/
|
||||
@Override
|
||||
public long ramBytesUsed() {
|
||||
// int: epsilon, epsilonRecursive, size, numSegments
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ 4 * Integer.BYTES
|
||||
// + keys.ramBytesUsed()
|
||||
+ plam.ramBytesUsed()
|
||||
+ segmentData.ramBytesUsed();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,137 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.DoubleCursor;
|
||||
|
||||
/**
|
||||
* A subclass of {@link DoubleArrayList} adding stack-related utility methods. The top of the stack
|
||||
* is at the <code>{@link #size()} - 1</code> element.
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeStack.java")
|
||||
public class DoubleStack extends DoubleArrayList {
|
||||
/** New instance with sane defaults. */
|
||||
public DoubleStack() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
*/
|
||||
public DoubleStack(int expectedElements) {
|
||||
super(expectedElements);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
* @param resizer Underlying buffer sizing strategy.
|
||||
*/
|
||||
public DoubleStack(int expectedElements, ArraySizingStrategy resizer) {
|
||||
super(expectedElements, resizer);
|
||||
}
|
||||
|
||||
/** Create a stack by pushing all elements of another container to it. */
|
||||
public DoubleStack(DoubleContainer container) {
|
||||
super(container);
|
||||
}
|
||||
|
||||
/** Adds one double to the stack. */
|
||||
public void push(double e1) {
|
||||
ensureBufferSpace(1);
|
||||
buffer[elementsCount++] = e1;
|
||||
}
|
||||
|
||||
/** Adds two doubles to the stack. */
|
||||
public void push(double e1, double e2) {
|
||||
ensureBufferSpace(2);
|
||||
buffer[elementsCount++] = e1;
|
||||
buffer[elementsCount++] = e2;
|
||||
}
|
||||
|
||||
/** Adds three doubles to the stack. */
|
||||
public void push(double e1, double e2, double e3) {
|
||||
ensureBufferSpace(3);
|
||||
buffer[elementsCount++] = e1;
|
||||
buffer[elementsCount++] = e2;
|
||||
buffer[elementsCount++] = e3;
|
||||
}
|
||||
|
||||
/** Adds four doubles to the stack. */
|
||||
public void push(double e1, double e2, double e3, double e4) {
|
||||
ensureBufferSpace(4);
|
||||
buffer[elementsCount++] = e1;
|
||||
buffer[elementsCount++] = e2;
|
||||
buffer[elementsCount++] = e3;
|
||||
buffer[elementsCount++] = e4;
|
||||
}
|
||||
|
||||
/** Add a range of array elements to the stack. */
|
||||
public void push(double[] elements, int start, int len) {
|
||||
assert start >= 0 && len >= 0;
|
||||
|
||||
ensureBufferSpace(len);
|
||||
System.arraycopy(elements, start, buffer, elementsCount, len);
|
||||
elementsCount += len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg-signature method for pushing elements at the top of the stack.
|
||||
*
|
||||
* <p><b>This method is handy, but costly if used in tight loops (anonymous array passing)</b>
|
||||
*/
|
||||
public final void push(double... elements) {
|
||||
push(elements, 0, elements.length);
|
||||
}
|
||||
|
||||
/** Pushes all elements from another container to the top of the stack. */
|
||||
public int pushAll(DoubleContainer container) {
|
||||
return addAll(container);
|
||||
}
|
||||
|
||||
/** Pushes all elements from another iterable to the top of the stack. */
|
||||
public int pushAll(Iterable<? extends DoubleCursor> iterable) {
|
||||
return addAll(iterable);
|
||||
}
|
||||
|
||||
/** Discard an arbitrary number of elements from the top of the stack. */
|
||||
public void discard(int count) {
|
||||
assert elementsCount >= count;
|
||||
|
||||
elementsCount -= count;
|
||||
}
|
||||
|
||||
/** Discard the top element from the stack. */
|
||||
public void discard() {
|
||||
assert elementsCount > 0;
|
||||
|
||||
elementsCount--;
|
||||
}
|
||||
|
||||
/** Remove the top element from the stack and return it. */
|
||||
public double pop() {
|
||||
return removeLast();
|
||||
}
|
||||
|
||||
/** Peek at the top element on the stack. */
|
||||
public double peek() {
|
||||
assert elementsCount > 0;
|
||||
return buffer[elementsCount - 1];
|
||||
}
|
||||
|
||||
/** Create a stack by pushing a variable number of arguments to it. */
|
||||
public static DoubleStack from(double... elements) {
|
||||
final DoubleStack stack = new DoubleStack(elements.length);
|
||||
stack.push(elements);
|
||||
return stack;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public DoubleStack clone() {
|
||||
return (DoubleStack) super.clone();
|
||||
}
|
||||
}
|
@ -1,776 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import static com.carrotsearch.hppc.Containers.*;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.FloatCursor;
|
||||
import com.carrotsearch.hppc.predicates.FloatPredicate;
|
||||
import com.carrotsearch.hppc.procedures.FloatProcedure;
|
||||
import java.util.*;
|
||||
|
||||
/** An array-backed {@link FloatDeque}. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeArrayDeque.java")
|
||||
public class FloatArrayDeque extends AbstractFloatCollection
|
||||
implements FloatDeque, Preallocable, Cloneable, Accountable {
|
||||
|
||||
/** Reuse the same strategy instance. */
|
||||
private static final BoundedProportionalArraySizingStrategy DEFAULT_SIZING_STRATEGY =
|
||||
BoundedProportionalArraySizingStrategy.DEFAULT_INSTANCE;
|
||||
|
||||
/** Internal array for storing elements of the deque. */
|
||||
public float[] buffer = FloatArrayList.EMPTY_ARRAY;
|
||||
|
||||
/**
|
||||
* The index of the element at the head of the deque or an arbitrary number equal to tail if the
|
||||
* deque is empty.
|
||||
*/
|
||||
public int head;
|
||||
|
||||
/** The index at which the next element would be added to the tail of the deque. */
|
||||
public int tail;
|
||||
|
||||
/** Buffer resizing strategy. */
|
||||
protected final ArraySizingStrategy resizer;
|
||||
|
||||
/** New instance with sane defaults. */
|
||||
public FloatArrayDeque() {
|
||||
this(DEFAULT_EXPECTED_ELEMENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
*/
|
||||
public FloatArrayDeque(int expectedElements) {
|
||||
this(expectedElements, DEFAULT_SIZING_STRATEGY);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
* @param resizer Underlying buffer sizing strategy.
|
||||
*/
|
||||
public FloatArrayDeque(int expectedElements, ArraySizingStrategy resizer) {
|
||||
assert resizer != null;
|
||||
this.resizer = resizer;
|
||||
ensureCapacity(expectedElements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deque from elements of another container, appending elements at the end of the
|
||||
* deque in the iteration order.
|
||||
*/
|
||||
public FloatArrayDeque(FloatContainer container) {
|
||||
this(container.size());
|
||||
addLast(container);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void addFirst(float e1) {
|
||||
int h = oneLeft(head, buffer.length);
|
||||
if (h == tail) {
|
||||
ensureBufferSpace(1);
|
||||
h = oneLeft(head, buffer.length);
|
||||
}
|
||||
buffer[head = h] = e1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg-signature method for adding elements at the front of this deque.
|
||||
*
|
||||
* <p><b>This method is handy, but costly if used in tight loops (anonymous array passing)</b>
|
||||
*
|
||||
* @param elements The elements to add.
|
||||
*/
|
||||
public final void addFirst(float... elements) {
|
||||
ensureBufferSpace(elements.length);
|
||||
for (float k : elements) {
|
||||
addFirst(k);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given container to the front of this deque.
|
||||
*
|
||||
* @param container The container to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addFirst(FloatContainer container) {
|
||||
int size = container.size();
|
||||
ensureBufferSpace(size);
|
||||
|
||||
for (FloatCursor cursor : container) {
|
||||
addFirst(cursor.value);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given iterable to the front of this deque.
|
||||
*
|
||||
* @param iterable The iterable to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addFirst(Iterable<? extends FloatCursor> iterable) {
|
||||
int size = 0;
|
||||
for (FloatCursor cursor : iterable) {
|
||||
addFirst(cursor.value);
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void addLast(float e1) {
|
||||
int t = oneRight(tail, buffer.length);
|
||||
if (head == t) {
|
||||
ensureBufferSpace(1);
|
||||
t = oneRight(tail, buffer.length);
|
||||
}
|
||||
buffer[tail] = e1;
|
||||
tail = t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg-signature method for adding elements at the end of this deque.
|
||||
*
|
||||
* <p><b>This method is handy, but costly if used in tight loops (anonymous array passing)</b>
|
||||
*
|
||||
* @param elements The elements to iterate over.
|
||||
*/
|
||||
public final void addLast(float... elements) {
|
||||
ensureBufferSpace(1);
|
||||
for (float k : elements) {
|
||||
addLast(k);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given container to the end of this deque.
|
||||
*
|
||||
* @param container The container to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addLast(FloatContainer container) {
|
||||
int size = container.size();
|
||||
ensureBufferSpace(size);
|
||||
|
||||
for (FloatCursor cursor : container) {
|
||||
addLast(cursor.value);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given iterable to the end of this deque.
|
||||
*
|
||||
* @param iterable The iterable to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addLast(Iterable<? extends FloatCursor> iterable) {
|
||||
int size = 0;
|
||||
for (FloatCursor cursor : iterable) {
|
||||
addLast(cursor.value);
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public float removeFirst() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
final float result = buffer[head];
|
||||
buffer[head] = 0f;
|
||||
head = oneRight(head, buffer.length);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public float removeLast() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
tail = oneLeft(tail, buffer.length);
|
||||
final float result = buffer[tail];
|
||||
buffer[tail] = 0f;
|
||||
return result;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public float getFirst() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
return buffer[head];
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public float getLast() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
return buffer[oneLeft(tail, buffer.length)];
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeFirst(float e1) {
|
||||
final int index = bufferIndexOf(e1);
|
||||
if (index >= 0) removeAtBufferIndex(index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index of the first (counting from head) element equal to <code>e1</code>. The index
|
||||
* points to the {@link #buffer} array.
|
||||
*
|
||||
* @param e1 The element to look for.
|
||||
* @return Returns the index of the first element equal to <code>e1</code> or <code>-1</code> if
|
||||
* not found.
|
||||
*/
|
||||
public int bufferIndexOf(float e1) {
|
||||
final int last = tail;
|
||||
final int bufLen = buffer.length;
|
||||
for (int i = head; i != last; i = oneRight(i, bufLen)) {
|
||||
if ((Float.floatToIntBits(e1) == Float.floatToIntBits(buffer[i]))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeLast(float e1) {
|
||||
final int index = lastBufferIndexOf(e1);
|
||||
if (index >= 0) {
|
||||
removeAtBufferIndex(index);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index of the last (counting from tail) element equal to <code>e1</code>. The index
|
||||
* points to the {@link #buffer} array.
|
||||
*
|
||||
* @param e1 The element to look for.
|
||||
* @return Returns the index of the first element equal to <code>e1</code> or <code>-1</code> if
|
||||
* not found.
|
||||
*/
|
||||
public int lastBufferIndexOf(float e1) {
|
||||
final int bufLen = buffer.length;
|
||||
final int last = oneLeft(head, bufLen);
|
||||
for (int i = oneLeft(tail, bufLen); i != last; i = oneLeft(i, bufLen)) {
|
||||
if ((Float.floatToIntBits(e1) == Float.floatToIntBits(buffer[i]))) return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(float e1) {
|
||||
int removed = 0;
|
||||
final int last = tail;
|
||||
final int bufLen = buffer.length;
|
||||
int from, to;
|
||||
for (from = to = head; from != last; from = oneRight(from, bufLen)) {
|
||||
if ((Float.floatToIntBits(e1) == Float.floatToIntBits(buffer[from]))) {
|
||||
buffer[from] = 0f;
|
||||
removed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = 0f;
|
||||
}
|
||||
|
||||
to = oneRight(to, bufLen);
|
||||
}
|
||||
|
||||
tail = to;
|
||||
return removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the element at <code>index</code> in the internal {#link {@link #buffer} array,
|
||||
* returning its value.
|
||||
*
|
||||
* @param index Index of the element to remove. The index must be located between {@link #head}
|
||||
* and {@link #tail} in modulo {@link #buffer} arithmetic.
|
||||
*/
|
||||
public void removeAtBufferIndex(int index) {
|
||||
assert (head <= tail ? index >= head && index < tail : index >= head || index < tail)
|
||||
: "Index out of range (head=" + head + ", tail=" + tail + ", index=" + index + ").";
|
||||
|
||||
// Cache fields in locals (hopefully moved to registers).
|
||||
final float[] buffer = this.buffer;
|
||||
final int bufLen = buffer.length;
|
||||
final int lastIndex = bufLen - 1;
|
||||
final int head = this.head;
|
||||
final int tail = this.tail;
|
||||
|
||||
final int leftChunk = Math.abs(index - head) % bufLen;
|
||||
final int rightChunk = Math.abs(tail - index) % bufLen;
|
||||
|
||||
if (leftChunk < rightChunk) {
|
||||
if (index >= head) {
|
||||
System.arraycopy(buffer, head, buffer, head + 1, leftChunk);
|
||||
} else {
|
||||
System.arraycopy(buffer, 0, buffer, 1, index);
|
||||
buffer[0] = buffer[lastIndex];
|
||||
System.arraycopy(buffer, head, buffer, head + 1, lastIndex - head);
|
||||
}
|
||||
buffer[head] = 0f;
|
||||
this.head = oneRight(head, bufLen);
|
||||
} else {
|
||||
if (index < tail) {
|
||||
System.arraycopy(buffer, index + 1, buffer, index, rightChunk);
|
||||
} else {
|
||||
System.arraycopy(buffer, index + 1, buffer, index, lastIndex - index);
|
||||
buffer[lastIndex] = buffer[0];
|
||||
System.arraycopy(buffer, 1, buffer, 0, tail);
|
||||
}
|
||||
buffer[tail] = 0f;
|
||||
this.tail = oneLeft(tail, bufLen);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int size() {
|
||||
if (head <= tail) return tail - head;
|
||||
else return (tail - head + buffer.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The internal array buffers are not released as a result of this call.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
if (head < tail) {
|
||||
Arrays.fill(buffer, head, tail, 0f);
|
||||
} else {
|
||||
Arrays.fill(buffer, 0, tail, 0f);
|
||||
Arrays.fill(buffer, head, buffer.length, 0f);
|
||||
}
|
||||
this.head = tail = 0;
|
||||
}
|
||||
|
||||
/** Release internal buffers of this deque and reallocate with the default buffer. */
|
||||
public void release() {
|
||||
this.head = tail = 0;
|
||||
buffer = FloatArrayList.EMPTY_ARRAY;
|
||||
ensureBufferSpace(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure this container can hold at least the given number of elements without resizing its
|
||||
* buffers.
|
||||
*
|
||||
* @param expectedElements The total number of elements, inclusive.
|
||||
*/
|
||||
@Override
|
||||
public void ensureCapacity(int expectedElements) {
|
||||
ensureBufferSpace(expectedElements - size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the internal buffer has enough free slots to store <code>expectedAdditions</code>.
|
||||
* Increases internal buffer size if needed.
|
||||
*/
|
||||
protected void ensureBufferSpace(int expectedAdditions) {
|
||||
final int bufferLen = buffer.length;
|
||||
final int elementsCount = size();
|
||||
|
||||
if (elementsCount + expectedAdditions >= bufferLen) {
|
||||
final int emptySlot = 1; // deque invariant: always an empty slot.
|
||||
final int newSize = resizer.grow(bufferLen, elementsCount + emptySlot, expectedAdditions);
|
||||
assert newSize >= (elementsCount + expectedAdditions + emptySlot)
|
||||
: "Resizer failed to"
|
||||
+ " return sensible new size: "
|
||||
+ newSize
|
||||
+ " <= "
|
||||
+ (elementsCount + expectedAdditions);
|
||||
|
||||
try {
|
||||
final float[] newBuffer = (new float[newSize]);
|
||||
if (bufferLen > 0) {
|
||||
toArray(newBuffer);
|
||||
tail = elementsCount;
|
||||
head = 0;
|
||||
}
|
||||
this.buffer = newBuffer;
|
||||
} catch (OutOfMemoryError e) {
|
||||
throw new BufferAllocationException(
|
||||
"Not enough memory to allocate new buffers: %,d -> %,d", e, bufferLen, newSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public float[] toArray() {
|
||||
|
||||
final int size = size();
|
||||
return toArray((new float[size]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies elements of this deque to an array. The content of the <code>target</code> array is
|
||||
* filled from index 0 (head of the queue) to index <code>size() - 1</code> (tail of the queue).
|
||||
*
|
||||
* @param target The target array must be large enough to hold all elements.
|
||||
* @return Returns the target argument for chaining.
|
||||
*/
|
||||
public float[] toArray(float[] target) {
|
||||
assert target.length >= size() : "Target array must be >= " + size();
|
||||
|
||||
if (head < tail) {
|
||||
// The contents is not wrapped around. Just copy.
|
||||
System.arraycopy(buffer, head, target, 0, size());
|
||||
} else if (head > tail) {
|
||||
// The contents is split. Merge elements from the following indexes:
|
||||
// [head...buffer.length - 1][0, tail - 1]
|
||||
final int rightCount = buffer.length - head;
|
||||
System.arraycopy(buffer, head, target, 0, rightCount);
|
||||
System.arraycopy(buffer, 0, target, rightCount, tail);
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone this object. The returned clone will reuse the same hash function and array resizing
|
||||
* strategy.
|
||||
*/
|
||||
@Override
|
||||
public FloatArrayDeque clone() {
|
||||
try {
|
||||
|
||||
FloatArrayDeque cloned = (FloatArrayDeque) super.clone();
|
||||
cloned.buffer = buffer.clone();
|
||||
return cloned;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Move one index to the left, wrapping around buffer. */
|
||||
protected static int oneLeft(int index, int modulus) {
|
||||
if (index >= 1) {
|
||||
return index - 1;
|
||||
}
|
||||
return modulus - 1;
|
||||
}
|
||||
|
||||
/** Move one index to the right, wrapping around buffer. */
|
||||
protected static int oneRight(int index, int modulus) {
|
||||
if (index + 1 == modulus) {
|
||||
return 0;
|
||||
}
|
||||
return index + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesAllocated() {
|
||||
// int: head, tail
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES * 2
|
||||
+ resizer.ramBytesAllocated()
|
||||
+ RamUsageEstimator.shallowSizeOfArray(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesUsed() {
|
||||
// int: head, tail
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES * 2
|
||||
+ resizer.ramBytesUsed()
|
||||
+ RamUsageEstimator.shallowUsedSizeOfArray(buffer, size());
|
||||
}
|
||||
|
||||
/** An iterator implementation for {@link ObjectArrayDeque#iterator}. */
|
||||
private final class ValueIterator extends AbstractIterator<FloatCursor> {
|
||||
private final FloatCursor cursor;
|
||||
private int remaining;
|
||||
|
||||
public ValueIterator() {
|
||||
cursor = new FloatCursor();
|
||||
cursor.index = oneLeft(head, buffer.length);
|
||||
this.remaining = size();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FloatCursor fetch() {
|
||||
if (remaining == 0) {
|
||||
return done();
|
||||
}
|
||||
|
||||
remaining--;
|
||||
cursor.value = buffer[cursor.index = oneRight(cursor.index, buffer.length)];
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
/** An iterator implementation for {@link ObjectArrayDeque#descendingIterator()}. */
|
||||
private final class DescendingValueIterator extends AbstractIterator<FloatCursor> {
|
||||
private final FloatCursor cursor;
|
||||
private int remaining;
|
||||
|
||||
public DescendingValueIterator() {
|
||||
cursor = new FloatCursor();
|
||||
cursor.index = tail;
|
||||
this.remaining = size();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FloatCursor fetch() {
|
||||
if (remaining == 0) return done();
|
||||
|
||||
remaining--;
|
||||
cursor.value = buffer[cursor.index = oneLeft(cursor.index, buffer.length)];
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a cursor over the values of this deque (in head to tail order). The iterator is
|
||||
* implemented as a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()} (to avoid boxing of primitive types). To read the current value (or index in
|
||||
* the deque's buffer) use the cursor's public fields. An example is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntValueCursor c : intDeque) {
|
||||
* System.out.println("buffer index=" + c.index + " value=" + c.value);
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public Iterator<FloatCursor> iterator() {
|
||||
return new ValueIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a cursor over the values of this deque (in tail to head order). The iterator is
|
||||
* implemented as a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()} (to avoid boxing of primitive types). To read the current value (or index in
|
||||
* the deque's buffer) use the cursor's public fields. An example is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (Iterator<IntCursor> i = intDeque.descendingIterator(); i.hasNext();) {
|
||||
* final IntCursor c = i.next();
|
||||
* System.out.println("buffer index=" + c.index + " value=" + c.value);
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public Iterator<FloatCursor> descendingIterator() {
|
||||
return new DescendingValueIterator();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends FloatProcedure> T forEach(T procedure) {
|
||||
forEach(procedure, head, tail);
|
||||
return procedure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>procedure</code> to a slice of the deque, <code>fromIndex</code>, inclusive, to
|
||||
* <code>toIndex</code>, exclusive.
|
||||
*/
|
||||
private void forEach(FloatProcedure procedure, int fromIndex, final int toIndex) {
|
||||
final float[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
procedure.apply(buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends FloatPredicate> T forEach(T predicate) {
|
||||
int fromIndex = head;
|
||||
int toIndex = tail;
|
||||
|
||||
final float[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
if (!predicate.apply(buffer[i])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return predicate;
|
||||
}
|
||||
|
||||
/** Applies <code>procedure</code> to all elements of this deque, tail to head. */
|
||||
@Override
|
||||
public <T extends FloatProcedure> T descendingForEach(T procedure) {
|
||||
descendingForEach(procedure, head, tail);
|
||||
return procedure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>procedure</code> to a slice of the deque, <code>toIndex</code>, exclusive, down
|
||||
* to <code>fromIndex</code>, inclusive.
|
||||
*/
|
||||
private void descendingForEach(FloatProcedure procedure, int fromIndex, final int toIndex) {
|
||||
if (fromIndex == toIndex) return;
|
||||
|
||||
final float[] buffer = this.buffer;
|
||||
int i = toIndex;
|
||||
do {
|
||||
i = oneLeft(i, buffer.length);
|
||||
procedure.apply(buffer[i]);
|
||||
} while (i != fromIndex);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends FloatPredicate> T descendingForEach(T predicate) {
|
||||
descendingForEach(predicate, head, tail);
|
||||
return predicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>predicate</code> to a slice of the deque, <code>toIndex</code>, exclusive, down
|
||||
* to <code>fromIndex</code>, inclusive or until the predicate returns <code>false</code>.
|
||||
*/
|
||||
private void descendingForEach(FloatPredicate predicate, int fromIndex, final int toIndex) {
|
||||
if (fromIndex == toIndex) return;
|
||||
|
||||
final float[] buffer = this.buffer;
|
||||
int i = toIndex;
|
||||
do {
|
||||
i = oneLeft(i, buffer.length);
|
||||
if (!predicate.apply(buffer[i])) {
|
||||
break;
|
||||
}
|
||||
} while (i != fromIndex);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(FloatPredicate predicate) {
|
||||
final float[] buffer = this.buffer;
|
||||
final int last = tail;
|
||||
final int bufLen = buffer.length;
|
||||
int removed = 0;
|
||||
int from, to;
|
||||
from = to = head;
|
||||
try {
|
||||
for (from = to = head; from != last; from = oneRight(from, bufLen)) {
|
||||
if (predicate.apply(buffer[from])) {
|
||||
buffer[from] = 0f;
|
||||
removed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = 0f;
|
||||
}
|
||||
|
||||
to = oneRight(to, bufLen);
|
||||
}
|
||||
} finally {
|
||||
// Keep the deque in consistent state even if the predicate throws an exception.
|
||||
for (; from != last; from = oneRight(from, bufLen)) {
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = 0f;
|
||||
}
|
||||
|
||||
to = oneRight(to, bufLen);
|
||||
}
|
||||
tail = to;
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean contains(float e) {
|
||||
int fromIndex = head;
|
||||
int toIndex = tail;
|
||||
|
||||
final float[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
if ((Float.floatToIntBits(e) == Float.floatToIntBits(buffer[i]))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = 1;
|
||||
int fromIndex = head;
|
||||
int toIndex = tail;
|
||||
|
||||
final float[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
h = 31 * h + BitMixer.mix(this.buffer[i]);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> only if the other object is an instance of the same class and with
|
||||
* the same elements.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return (this == obj)
|
||||
|| (obj != null && getClass() == obj.getClass() && equalElements(getClass().cast(obj)));
|
||||
}
|
||||
|
||||
/** Compare order-aligned elements against another {@link FloatDeque}. */
|
||||
protected boolean equalElements(FloatArrayDeque other) {
|
||||
int max = size();
|
||||
if (other.size() != max) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Iterator<FloatCursor> i1 = this.iterator();
|
||||
Iterator<? extends FloatCursor> i2 = other.iterator();
|
||||
|
||||
while (i1.hasNext() && i2.hasNext()) {
|
||||
if (!(Float.floatToIntBits(i1.next().value) == Float.floatToIntBits(i2.next().value))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return !i1.hasNext() && !i2.hasNext();
|
||||
}
|
||||
|
||||
/** Create a new deque by pushing a variable number of arguments to the end of it. */
|
||||
public static FloatArrayDeque from(float... elements) {
|
||||
final FloatArrayDeque coll = new FloatArrayDeque(elements.length);
|
||||
coll.addLast(elements);
|
||||
return coll;
|
||||
}
|
||||
}
|
@ -1,579 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import static com.carrotsearch.hppc.Containers.*;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.FloatPredicate;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.*;
|
||||
|
||||
/** An array-backed list of floats. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeArrayList.java")
|
||||
public class FloatArrayList extends AbstractFloatCollection
|
||||
implements FloatIndexedContainer, Preallocable, Cloneable, Accountable {
|
||||
/** An immutable empty buffer (array). */
|
||||
public static final float[] EMPTY_ARRAY = new float[0];
|
||||
|
||||
;
|
||||
|
||||
/** Reuse the same strategy instance. */
|
||||
private static final BoundedProportionalArraySizingStrategy DEFAULT_SIZING_STRATEGY =
|
||||
BoundedProportionalArraySizingStrategy.DEFAULT_INSTANCE;
|
||||
|
||||
/**
|
||||
* Internal array for storing the list. The array may be larger than the current size ({@link
|
||||
* #size()}).
|
||||
*/
|
||||
public float[] buffer = EMPTY_ARRAY;
|
||||
|
||||
/** Current number of elements stored in {@link #buffer}. */
|
||||
public int elementsCount;
|
||||
|
||||
/** Buffer resizing strategy. */
|
||||
protected final ArraySizingStrategy resizer;
|
||||
|
||||
/** New instance with sane defaults. */
|
||||
public FloatArrayList() {
|
||||
this(DEFAULT_EXPECTED_ELEMENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
*/
|
||||
public FloatArrayList(int expectedElements) {
|
||||
this(expectedElements, DEFAULT_SIZING_STRATEGY);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
* @param resizer Underlying buffer sizing strategy.
|
||||
*/
|
||||
public FloatArrayList(int expectedElements, ArraySizingStrategy resizer) {
|
||||
assert resizer != null;
|
||||
this.resizer = resizer;
|
||||
buffer = Arrays.copyOf(buffer, expectedElements);
|
||||
}
|
||||
|
||||
/** Creates a new list from the elements of another container in its iteration order. */
|
||||
public FloatArrayList(FloatContainer container) {
|
||||
this(container.size());
|
||||
addAll(container);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void add(float e1) {
|
||||
ensureBufferSpace(1);
|
||||
buffer[elementsCount++] = e1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends two elements at the end of the list. To add more than two elements, use <code>add
|
||||
* </code> (vararg-version) or access the buffer directly (tight loop).
|
||||
*/
|
||||
public void add(float e1, float e2) {
|
||||
ensureBufferSpace(2);
|
||||
buffer[elementsCount++] = e1;
|
||||
buffer[elementsCount++] = e2;
|
||||
}
|
||||
|
||||
/** Add all elements from a range of given array to the list. */
|
||||
public void add(float[] elements, int start, int length) {
|
||||
assert length >= 0 : "Length must be >= 0";
|
||||
|
||||
ensureBufferSpace(length);
|
||||
System.arraycopy(elements, start, buffer, elementsCount, length);
|
||||
elementsCount += length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg-signature method for adding elements at the end of the list.
|
||||
*
|
||||
* <p><b>This method is handy, but costly if used in tight loops (anonymous array passing)</b>
|
||||
*/
|
||||
public final void add(float... elements) {
|
||||
add(elements, 0, elements.length);
|
||||
}
|
||||
|
||||
/** Adds all elements from another container. */
|
||||
public int addAll(FloatContainer container) {
|
||||
final int size = container.size();
|
||||
ensureBufferSpace(size);
|
||||
|
||||
for (FloatCursor cursor : container) {
|
||||
add(cursor.value);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/** Adds all elements from another iterable. */
|
||||
public int addAll(Iterable<? extends FloatCursor> iterable) {
|
||||
int size = 0;
|
||||
for (FloatCursor cursor : iterable) {
|
||||
add(cursor.value);
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void insert(int index, float e1) {
|
||||
assert (index >= 0 && index <= size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
|
||||
ensureBufferSpace(1);
|
||||
System.arraycopy(buffer, index, buffer, index + 1, elementsCount - index);
|
||||
buffer[index] = e1;
|
||||
elementsCount++;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public float get(int index) {
|
||||
assert (index >= 0 && index < size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
return buffer[index];
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public float set(int index, float e1) {
|
||||
assert (index >= 0 && index < size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
final float v = buffer[index];
|
||||
buffer[index] = e1;
|
||||
return v;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public float removeAt(int index) {
|
||||
assert (index >= 0 && index < size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
final float v = buffer[index];
|
||||
System.arraycopy(buffer, index + 1, buffer, index, --elementsCount - index);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public float removeLast() {
|
||||
assert elementsCount > 0;
|
||||
|
||||
final float v = buffer[--elementsCount];
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void removeRange(int fromIndex, int toIndex) {
|
||||
assert (fromIndex >= 0 && fromIndex <= size())
|
||||
: "Index " + fromIndex + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
assert (toIndex >= 0 && toIndex <= size())
|
||||
: "Index " + toIndex + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
assert fromIndex <= toIndex : "fromIndex must be <= toIndex: " + fromIndex + ", " + toIndex;
|
||||
|
||||
System.arraycopy(buffer, toIndex, buffer, fromIndex, elementsCount - toIndex);
|
||||
final int count = toIndex - fromIndex;
|
||||
elementsCount -= count;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean removeElement(float e1) {
|
||||
return removeFirst(e1) != -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeFirst(float e1) {
|
||||
final int index = indexOf(e1);
|
||||
if (index >= 0) removeAt(index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeLast(float e1) {
|
||||
final int index = lastIndexOf(e1);
|
||||
if (index >= 0) removeAt(index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(float e1) {
|
||||
int to = 0;
|
||||
for (int from = 0; from < elementsCount; from++) {
|
||||
if ((Float.floatToIntBits(e1) == Float.floatToIntBits(buffer[from]))) {
|
||||
continue;
|
||||
}
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
}
|
||||
to++;
|
||||
}
|
||||
final int deleted = elementsCount - to;
|
||||
this.elementsCount = to;
|
||||
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean contains(float e1) {
|
||||
return indexOf(e1) >= 0;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int indexOf(float e1) {
|
||||
for (int i = 0; i < elementsCount; i++) {
|
||||
if ((Float.floatToIntBits(e1) == Float.floatToIntBits(buffer[i]))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int lastIndexOf(float e1) {
|
||||
for (int i = elementsCount - 1; i >= 0; i--) {
|
||||
if ((Float.floatToIntBits(e1) == Float.floatToIntBits(buffer[i]))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return elementsCount == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure this container can hold at least the given number of elements without resizing its
|
||||
* buffers.
|
||||
*
|
||||
* @param expectedElements The total number of elements, inclusive.
|
||||
*/
|
||||
@Override
|
||||
public void ensureCapacity(int expectedElements) {
|
||||
final int bufferLen = (buffer == null ? 0 : buffer.length);
|
||||
if (expectedElements > bufferLen) {
|
||||
ensureBufferSpace(expectedElements - size());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the internal buffer has enough free slots to store <code>expectedAdditions</code>.
|
||||
* Increases internal buffer size if needed.
|
||||
*/
|
||||
protected void ensureBufferSpace(int expectedAdditions) {
|
||||
final int bufferLen = (buffer == null ? 0 : buffer.length);
|
||||
if (elementsCount + expectedAdditions > bufferLen) {
|
||||
final int newSize = resizer.grow(bufferLen, elementsCount, expectedAdditions);
|
||||
assert newSize >= elementsCount + expectedAdditions
|
||||
: "Resizer failed to"
|
||||
+ " return sensible new size: "
|
||||
+ newSize
|
||||
+ " <= "
|
||||
+ (elementsCount + expectedAdditions);
|
||||
|
||||
this.buffer = Arrays.copyOf(buffer, newSize);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate or expand the list to the new size. If the list is truncated, the buffer will not be
|
||||
* reallocated (use {@link #trimToSize()} if you need a truncated buffer), but the truncated
|
||||
* values will be reset to the default value (zero). If the list is expanded, the elements beyond
|
||||
* the current size are initialized with JVM-defaults (zero or <code>null</code> values).
|
||||
*/
|
||||
public void resize(int newSize) {
|
||||
if (newSize <= buffer.length) {
|
||||
if (newSize < elementsCount) {
|
||||
Arrays.fill(buffer, newSize, elementsCount, 0f);
|
||||
} else {
|
||||
Arrays.fill(buffer, elementsCount, newSize, 0f);
|
||||
}
|
||||
} else {
|
||||
ensureCapacity(newSize);
|
||||
}
|
||||
this.elementsCount = newSize;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int size() {
|
||||
return elementsCount;
|
||||
}
|
||||
|
||||
/** Trim the internal buffer to the current size. */
|
||||
public void trimToSize() {
|
||||
if (size() != this.buffer.length) {
|
||||
this.buffer = toArray();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of stored elements to zero. Releases and initializes the internal storage array
|
||||
* to default values. To clear the list without cleaning the buffer, simply set the {@link
|
||||
* #elementsCount} field to zero.
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
Arrays.fill(buffer, 0, elementsCount, 0f);
|
||||
this.elementsCount = 0;
|
||||
}
|
||||
|
||||
/** Sets the number of stored elements to zero and releases the internal storage array. */
|
||||
@Override
|
||||
public void release() {
|
||||
this.buffer = EMPTY_ARRAY;
|
||||
this.elementsCount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The returned array is sized to match exactly the number of elements of the stack.
|
||||
*/
|
||||
@Override
|
||||
public float[] toArray() {
|
||||
|
||||
return Arrays.copyOf(buffer, elementsCount);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public FloatIndexedContainer sort() {
|
||||
Arrays.sort(buffer, 0, elementsCount);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public FloatIndexedContainer reverse() {
|
||||
for (int i = 0, mid = elementsCount >> 1, j = elementsCount - 1; i < mid; i++, j--) {
|
||||
float tmp = buffer[i];
|
||||
buffer[i] = buffer[j];
|
||||
buffer[j] = tmp;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone this object. The returned clone will reuse the same hash function and array resizing
|
||||
* strategy.
|
||||
*/
|
||||
@Override
|
||||
public FloatArrayList clone() {
|
||||
try {
|
||||
|
||||
final FloatArrayList cloned = (FloatArrayList) super.clone();
|
||||
cloned.buffer = buffer.clone();
|
||||
return cloned;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = 1, max = elementsCount;
|
||||
for (int i = 0; i < max; i++) {
|
||||
h = 31 * h + BitMixer.mix(this.buffer[i]);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> only if the other object is an instance of the same class and with
|
||||
* the same elements.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return (this == obj)
|
||||
|| (obj != null && getClass() == obj.getClass() && equalElements(getClass().cast(obj)));
|
||||
}
|
||||
|
||||
/** Compare index-aligned elements against another {@link FloatIndexedContainer}. */
|
||||
protected boolean equalElements(FloatArrayList other) {
|
||||
int max = size();
|
||||
if (other.size() != max) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < max; i++) {
|
||||
if (!(Float.floatToIntBits(get(i)) == Float.floatToIntBits(other.get(i)))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesAllocated() {
|
||||
// int: elementsCount
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES
|
||||
+ resizer.ramBytesAllocated()
|
||||
+ RamUsageEstimator.shallowSizeOfArray(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesUsed() {
|
||||
// int: elementsCount
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES
|
||||
+ resizer.ramBytesUsed()
|
||||
+ RamUsageEstimator.shallowUsedSizeOfArray(buffer, elementsCount);
|
||||
}
|
||||
|
||||
/** An iterator implementation for {@link FloatArrayList#iterator}. */
|
||||
static final class ValueIterator extends AbstractIterator<FloatCursor> {
|
||||
private final FloatCursor cursor;
|
||||
|
||||
private final float[] buffer;
|
||||
private final int size;
|
||||
|
||||
public ValueIterator(float[] buffer, int size) {
|
||||
this.cursor = new FloatCursor();
|
||||
this.cursor.index = -1;
|
||||
this.size = size;
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FloatCursor fetch() {
|
||||
if (cursor.index + 1 == size) return done();
|
||||
|
||||
cursor.value = buffer[++cursor.index];
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public Iterator<FloatCursor> iterator() {
|
||||
return new ValueIterator(buffer, size());
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends FloatProcedure> T forEach(T procedure) {
|
||||
return forEach(procedure, 0, size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>procedure</code> to a slice of the list, <code>fromIndex</code>, inclusive, to
|
||||
* <code>toIndex</code>, exclusive.
|
||||
*/
|
||||
public <T extends FloatProcedure> T forEach(T procedure, int fromIndex, final int toIndex) {
|
||||
assert (fromIndex >= 0 && fromIndex <= size())
|
||||
: "Index " + fromIndex + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
assert (toIndex >= 0 && toIndex <= size())
|
||||
: "Index " + toIndex + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
|
||||
assert fromIndex <= toIndex : "fromIndex must be <= toIndex: " + fromIndex + ", " + toIndex;
|
||||
|
||||
final float[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i < toIndex; i++) {
|
||||
procedure.apply(buffer[i]);
|
||||
}
|
||||
|
||||
return procedure;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(FloatPredicate predicate) {
|
||||
final float[] buffer = this.buffer;
|
||||
final int elementsCount = this.elementsCount;
|
||||
int to = 0;
|
||||
int from = 0;
|
||||
try {
|
||||
for (; from < elementsCount; from++) {
|
||||
if (predicate.apply(buffer[from])) {
|
||||
buffer[from] = 0f;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = 0f;
|
||||
}
|
||||
to++;
|
||||
}
|
||||
} finally {
|
||||
// Keep the list in a consistent state, even if the predicate throws an exception.
|
||||
for (; from < elementsCount; from++) {
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = 0f;
|
||||
}
|
||||
to++;
|
||||
}
|
||||
|
||||
this.elementsCount = to;
|
||||
}
|
||||
|
||||
return elementsCount - to;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends FloatPredicate> T forEach(T predicate) {
|
||||
return forEach(predicate, 0, size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>predicate</code> to a slice of the list, <code>fromIndex</code>, inclusive, to
|
||||
* <code>toIndex</code>, exclusive, or until predicate returns <code>false</code>.
|
||||
*/
|
||||
public <T extends FloatPredicate> T forEach(T predicate, int fromIndex, final int toIndex) {
|
||||
assert (fromIndex >= 0 && fromIndex <= size())
|
||||
: "Index " + fromIndex + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
assert (toIndex >= 0 && toIndex <= size())
|
||||
: "Index " + toIndex + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
assert fromIndex <= toIndex : "fromIndex must be <= toIndex: " + fromIndex + ", " + toIndex;
|
||||
|
||||
final float[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i < toIndex; i++) {
|
||||
if (!predicate.apply(buffer[i])) break;
|
||||
}
|
||||
|
||||
return predicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a list from a variable number of arguments or an array of <code>float</code>. The
|
||||
* elements are copied from the argument to the internal buffer.
|
||||
*/
|
||||
public static FloatArrayList from(float... elements) {
|
||||
final FloatArrayList list = new FloatArrayList(elements.length);
|
||||
list.add(elements);
|
||||
return list;
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
/**
|
||||
* Reused buffer visualization routines.
|
||||
*
|
||||
* @see FloatSet#visualizeKeyDistribution(int)
|
||||
* @see FloatVTypeMap#visualizeKeyDistribution(int)
|
||||
*/
|
||||
class FloatBufferVisualizer {
|
||||
static String visualizeKeyDistribution(float[] buffer, int max, int characters) {
|
||||
final StringBuilder b = new StringBuilder();
|
||||
final char[] chars = ".123456789X".toCharArray();
|
||||
for (int i = 1, start = -1; i <= characters; i++) {
|
||||
int end = (int) ((long) i * max / characters);
|
||||
|
||||
if (start + 1 <= end) {
|
||||
int taken = 0;
|
||||
int slots = 0;
|
||||
for (int slot = start + 1; slot <= end; slot++, slots++) {
|
||||
if (!(Float.floatToIntBits(buffer[slot]) == 0)) {
|
||||
taken++;
|
||||
}
|
||||
}
|
||||
b.append(chars[Math.min(chars.length - 1, taken * chars.length / slots)]);
|
||||
start = end;
|
||||
}
|
||||
}
|
||||
while (b.length() < characters) {
|
||||
b.append(' ');
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.predicates.FloatPredicate;
|
||||
|
||||
/**
|
||||
* A collection allows basic, efficient operations on sets of elements (difference and
|
||||
* intersection).
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeCollection.java")
|
||||
public interface FloatCollection extends FloatContainer {
|
||||
/**
|
||||
* Removes all occurrences of <code>e</code> from this collection.
|
||||
*
|
||||
* @param e Element to be removed from this collection, if present.
|
||||
* @return The number of removed elements as a result of this call.
|
||||
*/
|
||||
public int removeAll(float e);
|
||||
|
||||
/**
|
||||
* Removes all elements in this collection that are present in <code>c</code>.
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int removeAll(FloatLookupContainer c);
|
||||
|
||||
/**
|
||||
* Removes all elements in this collection for which the given predicate returns <code>true</code>
|
||||
* .
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int removeAll(FloatPredicate predicate);
|
||||
|
||||
/**
|
||||
* Keeps all elements in this collection that are present in <code>c</code>. Runs in time
|
||||
* proportional to the number of elements in this collection. Equivalent of sets intersection.
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int retainAll(FloatLookupContainer c);
|
||||
|
||||
/**
|
||||
* Keeps all elements in this collection for which the given predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int retainAll(FloatPredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all elements from this collection.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Removes all elements from the collection and additionally releases any internal buffers.
|
||||
* Typically, if the object is to be reused, a simple {@link #clear()} should be a better
|
||||
* alternative since it'll avoid reallocation.
|
||||
*
|
||||
* @see #clear()
|
||||
*/
|
||||
public void release();
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.FloatCursor;
|
||||
import com.carrotsearch.hppc.predicates.FloatPredicate;
|
||||
import com.carrotsearch.hppc.procedures.FloatProcedure;
|
||||
import java.util.Iterator;
|
||||
|
||||
/** A generic container holding <code>float</code>s. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeContainer.java")
|
||||
public interface FloatContainer extends Iterable<FloatCursor> {
|
||||
/**
|
||||
* Returns an iterator to a cursor traversing the collection. The order of traversal is not
|
||||
* defined. More than one cursor may be active at a time. The behavior of iterators is undefined
|
||||
* if structural changes are made to the underlying collection.
|
||||
*
|
||||
* <p>The iterator is implemented as a cursor and it returns <b>the same cursor instance</b> on
|
||||
* every call to {@link Iterator#next()} (to avoid boxing of primitive types). To read the current
|
||||
* list's value (or index in the list) use the cursor's public fields. An example is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (FloatCursor<float> c : container) {
|
||||
* System.out.println("index=" + c.index + " value=" + c.value);
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public Iterator<FloatCursor> iterator();
|
||||
|
||||
/**
|
||||
* Lookup a given element in the container. This operation has no speed guarantees (may be linear
|
||||
* with respect to the size of this container).
|
||||
*
|
||||
* @return Returns <code>true</code> if this container has an element equal to <code>e</code>.
|
||||
*/
|
||||
public boolean contains(float e);
|
||||
|
||||
/**
|
||||
* Return the current number of elements in this container. The time for calculating the
|
||||
* container's size may take <code>O(n)</code> time, although implementing classes should try to
|
||||
* maintain the current size and return in constant time.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/** Shortcut for <code>size() == 0</code>. */
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Copies all elements of this container to an array.
|
||||
*
|
||||
* <p>The returned array is always a copy, regardless of the storage used by the container.
|
||||
*/
|
||||
public float[] toArray();
|
||||
|
||||
/**
|
||||
* Applies a <code>procedure</code> to all container elements. Returns the argument (any subclass
|
||||
* of {@link FloatProcedure}. This lets the caller to call methods of the argument by chaining the
|
||||
* call (even if the argument is an anonymous type) to retrieve computed values, for example
|
||||
* (IntContainer):
|
||||
*
|
||||
* <pre>
|
||||
* int count = container.forEach(new IntProcedure() {
|
||||
* int count; // this is a field declaration in an anonymous class.
|
||||
*
|
||||
* public void apply(int value) {
|
||||
* count++;
|
||||
* }
|
||||
* }).count;
|
||||
* </pre>
|
||||
*/
|
||||
public <T extends FloatProcedure> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a <code>predicate</code> to container elements as long, as the predicate returns <code>
|
||||
* true</code>. The iteration is interrupted otherwise.
|
||||
*/
|
||||
public <T extends FloatPredicate> T forEach(T predicate);
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.FloatCursor;
|
||||
import com.carrotsearch.hppc.predicates.FloatPredicate;
|
||||
import com.carrotsearch.hppc.procedures.FloatProcedure;
|
||||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* A linear collection that supports element insertion and removal at both ends.
|
||||
*
|
||||
* @see Deque
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeDeque.java")
|
||||
public interface FloatDeque extends FloatCollection {
|
||||
/**
|
||||
* Removes the first element that equals <code>e</code>.
|
||||
*
|
||||
* @return The deleted element's index or <code>-1</code> if the element was not found.
|
||||
*/
|
||||
public int removeFirst(float e);
|
||||
|
||||
/**
|
||||
* Removes the last element that equals <code>e</code>.
|
||||
*
|
||||
* @return The deleted element's index or <code>-1</code> if the element was not found.
|
||||
*/
|
||||
public int removeLast(float e);
|
||||
|
||||
/** Inserts the specified element at the front of this deque. */
|
||||
public void addFirst(float e);
|
||||
|
||||
/** Inserts the specified element at the end of this deque. */
|
||||
public void addLast(float e);
|
||||
|
||||
/**
|
||||
* Retrieves and removes the first element of this deque.
|
||||
*
|
||||
* @return the head (first) element of this deque.
|
||||
*/
|
||||
public float removeFirst();
|
||||
|
||||
/**
|
||||
* Retrieves and removes the last element of this deque.
|
||||
*
|
||||
* @return the tail of this deque.
|
||||
*/
|
||||
public float removeLast();
|
||||
|
||||
/**
|
||||
* Retrieves the first element of this deque but does not remove it.
|
||||
*
|
||||
* @return the head of this deque.
|
||||
*/
|
||||
public float getFirst();
|
||||
|
||||
/**
|
||||
* Retrieves the last element of this deque but does not remove it.
|
||||
*
|
||||
* @return the head of this deque.
|
||||
*/
|
||||
public float getLast();
|
||||
|
||||
/**
|
||||
* @return An iterator over elements in this deque in tail-to-head order.
|
||||
*/
|
||||
public Iterator<FloatCursor> descendingIterator();
|
||||
|
||||
/** Applies a <code>procedure</code> to all elements in tail-to-head order. */
|
||||
public <T extends FloatProcedure> T descendingForEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a <code>predicate</code> to container elements as long, as the predicate returns <code>
|
||||
* true</code>. The iteration is interrupted otherwise.
|
||||
*/
|
||||
public <T extends FloatPredicate> T descendingForEach(T predicate);
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import java.util.RandomAccess;
|
||||
|
||||
/**
|
||||
* An indexed container provides random access to elements based on an <code>index</code>. Indexes
|
||||
* are zero-based.
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeIndexedContainer.java")
|
||||
public interface FloatIndexedContainer extends FloatCollection, RandomAccess {
|
||||
/**
|
||||
* Removes the first element that equals <code>e1</code>, returning whether an element has been
|
||||
* removed.
|
||||
*/
|
||||
public boolean removeElement(float e1);
|
||||
|
||||
/**
|
||||
* Removes the first element that equals <code>e1</code>, returning its deleted position or <code>
|
||||
* -1</code> if the element was not found.
|
||||
*/
|
||||
public int removeFirst(float e1);
|
||||
|
||||
/**
|
||||
* Removes the last element that equals <code>e1</code>, returning its deleted position or <code>
|
||||
* -1</code> if the element was not found.
|
||||
*/
|
||||
public int removeLast(float e1);
|
||||
|
||||
/**
|
||||
* Returns the index of the first occurrence of the specified element in this list, or -1 if this
|
||||
* list does not contain the element.
|
||||
*/
|
||||
public int indexOf(float e1);
|
||||
|
||||
/**
|
||||
* Returns the index of the last occurrence of the specified element in this list, or -1 if this
|
||||
* list does not contain the element.
|
||||
*/
|
||||
public int lastIndexOf(float e1);
|
||||
|
||||
/** Adds an element to the end of this container (the last index is incremented by one). */
|
||||
public void add(float e1);
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the specified position in this list.
|
||||
*
|
||||
* @param index The index at which the element should be inserted, shifting any existing and
|
||||
* subsequent elements to the right.
|
||||
*/
|
||||
public void insert(int index, float e1);
|
||||
|
||||
/**
|
||||
* Replaces the element at the specified position in this list with the specified element.
|
||||
*
|
||||
* @return Returns the previous value in the list.
|
||||
*/
|
||||
public float set(int index, float e1);
|
||||
|
||||
/**
|
||||
* @return Returns the element at index <code>index</code> from the list.
|
||||
*/
|
||||
public float get(int index);
|
||||
|
||||
/**
|
||||
* Removes the element at the specified position in this container and returns it.
|
||||
*
|
||||
* @see #removeFirst
|
||||
* @see #removeLast
|
||||
* @see #removeAll
|
||||
*/
|
||||
public float removeAt(int index);
|
||||
|
||||
/** Removes and returns the last element of this container. This container must not be empty. */
|
||||
public float removeLast();
|
||||
|
||||
/**
|
||||
* Removes from this container all of the elements with indexes between <code>fromIndex</code>,
|
||||
* inclusive, and <code>toIndex</code>, exclusive.
|
||||
*/
|
||||
public void removeRange(int fromIndex, int toIndex);
|
||||
|
||||
/** Returns this container elements as a stream. */
|
||||
|
||||
/** Sorts the elements in this container and returns this container. */
|
||||
public FloatIndexedContainer sort();
|
||||
|
||||
/** Reverses the elements in this container and returns this container. */
|
||||
public FloatIndexedContainer reverse();
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
/**
|
||||
* Marker interface for containers that can check if they contain a given object in at least time
|
||||
* <code>O(log n)</code> and ideally in amortized constant time <code>O(1)</code>.
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeLookupContainer.java")
|
||||
public interface FloatLookupContainer extends FloatContainer {
|
||||
public boolean contains(float e);
|
||||
}
|
@ -1,600 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.FloatCursor;
|
||||
import com.carrotsearch.hppc.procedures.FloatProcedure;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Space-efficient index that enables fast rank/range search operations on a sorted sequence of
|
||||
* <code>float</code>.
|
||||
*
|
||||
* <p>Implementation of the PGM-Index described at <a
|
||||
* href="https://pgm.di.unipi.it/">https://pgm.di.unipi.it/</a>, based on the paper
|
||||
*
|
||||
* <pre>
|
||||
* Paolo Ferragina and Giorgio Vinciguerra.
|
||||
* The PGM-index: a fully-dynamic compressed learned index with provable worst-case bounds.
|
||||
* PVLDB, 13(8): 1162-1175, 2020.
|
||||
* </pre>
|
||||
*
|
||||
* It provides {@code rank} and {@code range} search operations. {@code indexOf()} is faster than
|
||||
* B+Tree, and the index is much more compact. {@code contains()} is between 4x to 7x slower than
|
||||
* {@code IntHashSet#contains()}, but between 2.5x to 3x faster than {@link Arrays#binarySearch}.
|
||||
*
|
||||
* <p>Its compactness (40KB for 200MB of keys) makes it efficient for very large collections, the
|
||||
* index fitting easily in the L2 cache. The {@code epsilon} parameter should be set according to
|
||||
* the desired space-time trade-off. A smaller value makes the estimation more precise and the range
|
||||
* smaller but at the cost of increased space usage. In practice, {@code epsilon} 64 is a good sweet
|
||||
* spot.
|
||||
*
|
||||
* <p>Internally the index uses an optimal piecewise linear mapping from keys to their position in
|
||||
* the sorted order. This mapping is represented as a sequence of linear models (segments) which are
|
||||
* themselves recursively indexed by other piecewise linear mappings.
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypePgmIndex.java")
|
||||
public class FloatPgmIndex implements Accountable {
|
||||
|
||||
/** Empty immutable FloatPgmIndex. */
|
||||
public static final FloatPgmIndex EMPTY = new FloatEmptyPgmIndex();
|
||||
|
||||
/**
|
||||
* Epsilon approximation range when searching the list of keys. Controls the size of the returned
|
||||
* search range, strictly greater than 0. It should be set according to the desired space-time
|
||||
* trade-off. A smaller value makes the estimation more precise and the range smaller but at the
|
||||
* cost of increased space usage.
|
||||
*
|
||||
* <p>With EPSILON=64 the benchmark with 200MB of keys shows that this PGM index requires only 2%
|
||||
* additional memory on average (40KB). It depends on the distribution of the keys. This epsilon
|
||||
* value is good even for 2MB of keys. With EPSILON=32: +5% speed, but 4x space (160KB).
|
||||
*/
|
||||
public static final int EPSILON = 64;
|
||||
|
||||
/**
|
||||
* Epsilon approximation range for the segments layers. Controls the size of the search range in
|
||||
* the hierarchical segment lists, strictly greater than 0.
|
||||
*/
|
||||
public static final int EPSILON_RECURSIVE = 32;
|
||||
|
||||
/** Size of a key, measured in {@link Integer#BYTES} because the key is stored in an int[]. */
|
||||
public static final int KEY_SIZE =
|
||||
RamUsageEstimator.primitiveSizes.get(float.class) / Integer.BYTES;
|
||||
|
||||
/** 2x {@link #KEY_SIZE}. */
|
||||
public static final int DOUBLE_KEY_SIZE = KEY_SIZE * 2;
|
||||
|
||||
/**
|
||||
* Data size of a segment, measured in {@link Integer#BYTES}, because segments are stored in an
|
||||
* int[].
|
||||
*/
|
||||
public static final int SEGMENT_DATA_SIZE = KEY_SIZE * 3;
|
||||
|
||||
/** Initial value of the exponential jump when scanning out of the epsilon range. */
|
||||
public static final int BEYOND_EPSILON_JUMP = 16;
|
||||
|
||||
/**
|
||||
* The list of keys for which this index is built. It is sorted and may contain duplicate
|
||||
* elements.
|
||||
*/
|
||||
public final FloatArrayList keys;
|
||||
|
||||
/** The size of the key set. That is, the number of distinct elements in {@link #keys}. */
|
||||
public final int size;
|
||||
|
||||
/** The lowest key in {@link #keys}. */
|
||||
public final float firstKey;
|
||||
|
||||
/** The highest key in {@link #keys}. */
|
||||
public final float lastKey;
|
||||
|
||||
/** The epsilon range used to build this index. */
|
||||
public final int epsilon;
|
||||
|
||||
/** The recursive epsilon range used to build this index. */
|
||||
public final int epsilonRecursive;
|
||||
|
||||
/** The offsets in {@link #segmentData} of the first segment of each segment level. */
|
||||
public final int[] levelOffsets;
|
||||
|
||||
/** The index data. It contains all the segments for all the levels. */
|
||||
public final int[] segmentData;
|
||||
|
||||
private FloatPgmIndex(
|
||||
FloatArrayList keys,
|
||||
int size,
|
||||
int epsilon,
|
||||
int epsilonRecursive,
|
||||
int[] levelOffsets,
|
||||
int[] segmentData) {
|
||||
assert keys.size() > 0;
|
||||
assert size > 0 && size <= keys.size();
|
||||
assert epsilon > 0;
|
||||
assert epsilonRecursive > 0;
|
||||
this.keys = keys;
|
||||
this.size = size;
|
||||
firstKey = keys.get(0);
|
||||
lastKey = keys.get(keys.size() - 1);
|
||||
this.epsilon = epsilon;
|
||||
this.epsilonRecursive = epsilonRecursive;
|
||||
this.levelOffsets = levelOffsets;
|
||||
this.segmentData = segmentData;
|
||||
}
|
||||
|
||||
/** Empty set constructor. */
|
||||
private FloatPgmIndex() {
|
||||
keys = new FloatArrayList(0);
|
||||
size = 0;
|
||||
firstKey = 0f;
|
||||
lastKey = 0f;
|
||||
epsilon = 0;
|
||||
epsilonRecursive = 0;
|
||||
levelOffsets = new int[0];
|
||||
segmentData = levelOffsets;
|
||||
}
|
||||
|
||||
/** Returns the size of the key set. That is, the number of distinct elements in {@link #keys}. */
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/** Returns whether this key set is empty. */
|
||||
public boolean isEmpty() {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
/** Returns whether this key set contains the given key. */
|
||||
public boolean contains(float key) {
|
||||
return indexOf(key) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the specified key, and returns its index in the element list. If multiple elements are
|
||||
* equal to the specified key, there is no guarantee which one will be found.
|
||||
*
|
||||
* @return The index of the searched key if it is present; otherwise, {@code (-(<i>insertion
|
||||
* point</i>) - 1)}. The <i>insertion point</i> is defined as the point at which the key would
|
||||
* be inserted into the list: the index of the first element greater than the key, or {@link
|
||||
* #keys}#{@code size()} if all the elements are less than the specified key. Note that this
|
||||
* guarantees that the return value will be >= 0 if and only if the key is found.
|
||||
*/
|
||||
public int indexOf(float key) {
|
||||
if (key < firstKey) {
|
||||
return -1;
|
||||
}
|
||||
if (key > lastKey) {
|
||||
return -keys.size() - 1;
|
||||
}
|
||||
final int[] segmentData = this.segmentData;
|
||||
int segmentDataIndex = findSegment(key);
|
||||
int nextIntercept = (int) getIntercept(segmentDataIndex + SEGMENT_DATA_SIZE, segmentData);
|
||||
int index =
|
||||
Math.min(
|
||||
approximateIndex(key, segmentDataIndex, segmentData),
|
||||
Math.min(nextIntercept, keys.size() - 1));
|
||||
assert index >= 0 && index < keys.size();
|
||||
float k = keys.get(index);
|
||||
if (key < k) {
|
||||
// Scan sequentially before the approximated index, within epsilon range.
|
||||
final int fromIndex = Math.max(index - epsilon - 1, 0);
|
||||
while (--index >= fromIndex) {
|
||||
k = keys.get(index);
|
||||
if (key > k) {
|
||||
return -index - 2;
|
||||
}
|
||||
if ((Float.floatToIntBits(key) == Float.floatToIntBits(k))) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
// Continue scanning out of the epsilon range.
|
||||
// This might happen in rare cases of precision error during the approximation
|
||||
// computation for longs (we don't have long double 128 bits in Java).
|
||||
// This might also happen in rare corner cases of large duplicate elements
|
||||
// sequence at the epsilon range boundary.
|
||||
index++;
|
||||
int jump = BEYOND_EPSILON_JUMP;
|
||||
do {
|
||||
int loIndex = Math.max(index - jump, 0);
|
||||
if (key >= keys.get(loIndex)) {
|
||||
return Arrays.binarySearch(keys.buffer, loIndex, index, key);
|
||||
}
|
||||
index = loIndex;
|
||||
jump <<= 1;
|
||||
} while (index > 0);
|
||||
return -1;
|
||||
} else if ((Float.floatToIntBits(key) == Float.floatToIntBits(k))) {
|
||||
return index;
|
||||
} else {
|
||||
// Scan sequentially after the approximated index, within epsilon range.
|
||||
final int toIndex = Math.min(index + epsilon + 3, keys.size());
|
||||
while (++index < toIndex) {
|
||||
k = keys.get(index);
|
||||
if (key < k) {
|
||||
return -index - 1;
|
||||
}
|
||||
if ((Float.floatToIntBits(key) == Float.floatToIntBits(k))) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
// Continue scanning out of the epsilon range.
|
||||
int jump = BEYOND_EPSILON_JUMP;
|
||||
do {
|
||||
int hiIndex = Math.min(index + jump, keys.size());
|
||||
if (key <= keys.get(hiIndex)) {
|
||||
return Arrays.binarySearch(keys.buffer, index, hiIndex, key);
|
||||
}
|
||||
index = hiIndex;
|
||||
jump <<= 1;
|
||||
} while (index < keys.size());
|
||||
return -keys.size() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns, for any value {@code x}, the number of keys in the sorted list which are smaller than
|
||||
* {@code x}. It is equal to {@link #indexOf} if {@code x} belongs to the list, or -{@link
|
||||
* #indexOf}-1 otherwise.
|
||||
*
|
||||
* <p>If multiple elements are equal to the specified key, there is no guarantee which one will be
|
||||
* found.
|
||||
*
|
||||
* @return The index of the searched key if it is present; otherwise, the {@code insertion point}.
|
||||
* The <i>insertion point</i> is defined as the point at which the key would be inserted into
|
||||
* the list: the index of the first element greater than the key, or {@link #keys}#{@code
|
||||
* size()} if all the elements are less than the specified key. Note that this method always
|
||||
* returns a value >= 0.
|
||||
*/
|
||||
public int rank(float x) {
|
||||
int index = indexOf(x);
|
||||
return index >= 0 ? index : -index - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of keys in the list that are greater than or equal to {@code minKey}
|
||||
* (inclusive), and less than or equal to {@code maxKey} (inclusive).
|
||||
*/
|
||||
public int rangeCardinality(float minKey, float maxKey) {
|
||||
int fromIndex = rank(minKey);
|
||||
int maxIndex = indexOf(maxKey);
|
||||
int toIndex = maxIndex >= 0 ? maxIndex + 1 : -maxIndex - 1;
|
||||
return Math.max(toIndex - fromIndex, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over the keys in the list that are greater than or equal to {@code minKey}
|
||||
* (inclusive), and less than or equal to {@code maxKey} (inclusive).
|
||||
*/
|
||||
public Iterator<FloatCursor> rangeIterator(float minKey, float maxKey) {
|
||||
int fromIndex = rank(minKey);
|
||||
return new RangeIterator(keys, fromIndex, maxKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies {@code procedure} to the keys in the list that are greater than or equal to {@code
|
||||
* minKey} (inclusive), and less than or equal to {@code maxKey} (inclusive).
|
||||
*/
|
||||
public <T extends FloatProcedure> T forEachInRange(T procedure, float minKey, float maxKey) {
|
||||
final float[] buffer = keys.buffer;
|
||||
float k;
|
||||
for (int i = rank(minKey), size = keys.size(); i < size && (k = buffer[i]) <= maxKey; i++) {
|
||||
procedure.apply(k);
|
||||
}
|
||||
return procedure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Estimates the allocated memory. It does not count the memory for the list of keys, only for the
|
||||
* index itself.
|
||||
*/
|
||||
@Override
|
||||
public long ramBytesAllocated() {
|
||||
// int: size, epsilon, epsilonRecursive
|
||||
// float: firstKey, lastKey
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ 3 * Integer.BYTES
|
||||
+ 2L * KEY_SIZE * Integer.BYTES
|
||||
// + keys.ramBytesAllocated()
|
||||
+ RamUsageEstimator.shallowSizeOfArray(levelOffsets)
|
||||
+ RamUsageEstimator.shallowSizeOfArray(segmentData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Estimates the bytes that are actually used. It does not count the memory for the list of keys,
|
||||
* only for the index itself.
|
||||
*/
|
||||
@Override
|
||||
public long ramBytesUsed() {
|
||||
// int: size, epsilon, epsilonRecursive
|
||||
// float: firstKey, lastKey
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ 3 * Integer.BYTES
|
||||
+ 2L * KEY_SIZE * Integer.BYTES
|
||||
// + keys.ramBytesUsed()
|
||||
+ RamUsageEstimator.shallowSizeOfArray(levelOffsets)
|
||||
+ RamUsageEstimator.shallowSizeOfArray(segmentData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the segment responsible for a given key, that is, the rightmost segment having its first
|
||||
* key <= the searched key.
|
||||
*
|
||||
* @return the segment data index; or -1 if none.
|
||||
*/
|
||||
private int findSegment(float key) {
|
||||
assert key >= firstKey && key <= lastKey;
|
||||
final int epsilonRecursive = this.epsilonRecursive;
|
||||
final int[] levelOffsets = this.levelOffsets;
|
||||
final int[] segmentData = this.segmentData;
|
||||
int level = levelOffsets.length - 1;
|
||||
int segmentDataIndex = levelOffsets[level] * SEGMENT_DATA_SIZE;
|
||||
while (--level >= 0) {
|
||||
int nextIntercept = (int) getIntercept(segmentDataIndex + SEGMENT_DATA_SIZE, segmentData);
|
||||
int index = Math.min(approximateIndex(key, segmentDataIndex, segmentData), nextIntercept);
|
||||
assert index >= 0 && index <= levelOffsets[level + 1] - levelOffsets[level] - 1;
|
||||
int sdIndex = (levelOffsets[level] + index) * SEGMENT_DATA_SIZE;
|
||||
if (getKey(sdIndex, segmentData) <= key) {
|
||||
// Scan sequentially segments after the approximated index, within the epsilon range.
|
||||
final int levelNumSegments = levelOffsets[level + 1] - levelOffsets[level] - 1;
|
||||
final int toIndex = Math.min(index + epsilonRecursive + 3, levelNumSegments);
|
||||
while (index++ < toIndex && getKey(sdIndex + SEGMENT_DATA_SIZE, segmentData) <= key) {
|
||||
sdIndex += SEGMENT_DATA_SIZE;
|
||||
}
|
||||
} else {
|
||||
// Scan sequentially segments before the approximated index, within the epsilon range.
|
||||
final int fromIndex = Math.max(index - epsilonRecursive - 1, 0);
|
||||
while (index-- > fromIndex) {
|
||||
sdIndex -= SEGMENT_DATA_SIZE;
|
||||
if (getKey(sdIndex, segmentData) <= key) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
segmentDataIndex = sdIndex;
|
||||
}
|
||||
assert segmentDataIndex >= 0;
|
||||
return segmentDataIndex;
|
||||
}
|
||||
|
||||
private int approximateIndex(float key, int segmentDataIndex, int[] segmentData) {
|
||||
long intercept = getIntercept(segmentDataIndex, segmentData);
|
||||
float sKey = getKey(segmentDataIndex, segmentData);
|
||||
double slope = getSlope(segmentDataIndex, segmentData);
|
||||
int index = (int) (slope * ((double) key - sKey) + intercept);
|
||||
return Math.max(index, 0);
|
||||
}
|
||||
|
||||
private static long getIntercept(int segmentDataIndex, int[] segmentData) {
|
||||
return PgmIndexUtil.getIntercept(segmentDataIndex, segmentData, KEY_SIZE);
|
||||
}
|
||||
|
||||
private float getKey(int segmentDataIndex, int[] segmentData) {
|
||||
return PgmIndexUtil.getKey(segmentDataIndex + KEY_SIZE, segmentData, 0f);
|
||||
}
|
||||
|
||||
private static double getSlope(int segmentDataIndex, int[] segmentData) {
|
||||
return PgmIndexUtil.getSlope(segmentDataIndex + DOUBLE_KEY_SIZE, segmentData, KEY_SIZE);
|
||||
}
|
||||
|
||||
/** Empty immutable PGM Index. */
|
||||
private static class FloatEmptyPgmIndex extends FloatPgmIndex {
|
||||
|
||||
private final Iterator<FloatCursor> emptyIterator = new FloatEmptyIterator();
|
||||
|
||||
@Override
|
||||
public int indexOf(float key) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<FloatCursor> rangeIterator(float minKey, float maxKey) {
|
||||
return emptyIterator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends FloatProcedure> T forEachInRange(T procedure, float minKey, float maxKey) {
|
||||
return procedure;
|
||||
}
|
||||
|
||||
private static class FloatEmptyIterator extends AbstractIterator<FloatCursor> {
|
||||
@Override
|
||||
protected FloatCursor fetch() {
|
||||
return done();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Iterator over a range of elements in a sorted array. */
|
||||
protected static class RangeIterator extends AbstractIterator<FloatCursor> {
|
||||
private final float[] buffer;
|
||||
private final int size;
|
||||
private final FloatCursor cursor;
|
||||
private final float maxKey;
|
||||
|
||||
/** Range iterator from {@code fromIndex} (inclusive) to {@code maxKey} (inclusive). */
|
||||
protected RangeIterator(FloatArrayList keys, int fromIndex, float maxKey) {
|
||||
this.buffer = keys.buffer;
|
||||
this.size = keys.size();
|
||||
this.cursor = new FloatCursor();
|
||||
this.cursor.index = fromIndex;
|
||||
this.maxKey = maxKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FloatCursor fetch() {
|
||||
if (cursor.index >= size) {
|
||||
return done();
|
||||
}
|
||||
cursor.value = buffer[cursor.index++];
|
||||
if (cursor.value > maxKey) {
|
||||
cursor.index = size;
|
||||
return done();
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
/** Builds a {@link FloatPgmIndex} on a provided sorted list of keys. */
|
||||
public static class FloatBuilder implements PlaModel.SegmentConsumer, Accountable {
|
||||
|
||||
protected FloatArrayList keys;
|
||||
protected int epsilon = EPSILON;
|
||||
protected int epsilonRecursive = EPSILON_RECURSIVE;
|
||||
protected PlaModel plam;
|
||||
protected int size;
|
||||
protected IntArrayList segmentData;
|
||||
protected int numSegments;
|
||||
|
||||
/** Sets the sorted list of keys to build the index for; duplicate elements are allowed. */
|
||||
public FloatBuilder setSortedKeys(FloatArrayList keys) {
|
||||
this.keys = keys;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Sets the sorted array of keys to build the index for; duplicate elements are allowed. */
|
||||
public FloatBuilder setSortedKeys(float[] keys, int length) {
|
||||
FloatArrayList keyList = new FloatArrayList(0);
|
||||
keyList.buffer = keys;
|
||||
keyList.elementsCount = length;
|
||||
return setSortedKeys(keyList);
|
||||
}
|
||||
|
||||
/** Sets the epsilon range to use when learning the segments for the list of keys. */
|
||||
public FloatBuilder setEpsilon(int epsilon) {
|
||||
if (epsilon <= 0) {
|
||||
throw new IllegalArgumentException("epsilon must be > 0");
|
||||
}
|
||||
this.epsilon = epsilon;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the recursive epsilon range to use when learning the segments for the segment levels.
|
||||
*/
|
||||
public FloatBuilder setEpsilonRecursive(int epsilonRecursive) {
|
||||
if (epsilonRecursive <= 0) {
|
||||
throw new IllegalArgumentException("epsilonRecursive must be > 0");
|
||||
}
|
||||
this.epsilonRecursive = epsilonRecursive;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Builds the {@link FloatPgmIndex}; or {@link #EMPTY} if there are no keys in the list. */
|
||||
public FloatPgmIndex build() {
|
||||
if (keys == null || keys.size() == 0) {
|
||||
return (FloatPgmIndex) EMPTY;
|
||||
}
|
||||
plam = new PlaModel(epsilon);
|
||||
|
||||
int segmentsInitialCapacity =
|
||||
Math.min(
|
||||
Math.max(keys.size() / (2 * epsilon * epsilon) * SEGMENT_DATA_SIZE, 16), 1 << 19);
|
||||
segmentData = new IntArrayList(segmentsInitialCapacity);
|
||||
IntArrayList levelOffsets = new IntArrayList(16);
|
||||
|
||||
int levelOffset = 0;
|
||||
levelOffsets.add(levelOffset);
|
||||
int levelNumSegments = buildFirstLevel();
|
||||
while (levelNumSegments > 1) {
|
||||
int nextLevelOffset = numSegments;
|
||||
levelOffsets.add(nextLevelOffset);
|
||||
levelNumSegments = buildUpperLevel(levelOffset, levelNumSegments);
|
||||
levelOffset = nextLevelOffset;
|
||||
}
|
||||
|
||||
int[] segmentDataFinal = segmentData.toArray();
|
||||
int[] levelOffsetsFinal = levelOffsets.toArray();
|
||||
return new FloatPgmIndex(
|
||||
keys, size, epsilon, epsilonRecursive, levelOffsetsFinal, segmentDataFinal);
|
||||
}
|
||||
|
||||
private int buildFirstLevel() {
|
||||
assert numSegments == 0;
|
||||
int numKeys = keys.size();
|
||||
int size = 0;
|
||||
float key = keys.get(0);
|
||||
size++;
|
||||
plam.addKey(key, 0, this);
|
||||
for (int i = 1; i < numKeys; i++) {
|
||||
float nextKey = keys.get(i);
|
||||
if (!(Float.floatToIntBits(nextKey) == Float.floatToIntBits(key))) {
|
||||
key = nextKey;
|
||||
plam.addKey(key, i, this);
|
||||
size++;
|
||||
}
|
||||
}
|
||||
plam.finish(this);
|
||||
addSentinelSegment(numKeys);
|
||||
this.size = size;
|
||||
return numSegments - 1;
|
||||
}
|
||||
|
||||
private int buildUpperLevel(int levelOffset, int levelNumSegments) {
|
||||
plam.setEpsilon(epsilonRecursive);
|
||||
assert numSegments > 0;
|
||||
int initialNumSegments = numSegments;
|
||||
int segmentDataIndex = levelOffset * SEGMENT_DATA_SIZE;
|
||||
float key = getKey(segmentDataIndex, segmentData.buffer);
|
||||
plam.addKey(key, 0, this);
|
||||
for (int i = 1; i < levelNumSegments; i++) {
|
||||
segmentDataIndex += SEGMENT_DATA_SIZE;
|
||||
float nextKey = getKey(segmentDataIndex, segmentData.buffer);
|
||||
if (!(Float.floatToIntBits(nextKey) == Float.floatToIntBits(key))) {
|
||||
key = nextKey;
|
||||
plam.addKey(key, i, this);
|
||||
}
|
||||
}
|
||||
plam.finish(this);
|
||||
addSentinelSegment(levelNumSegments);
|
||||
return numSegments - initialNumSegments - 1;
|
||||
}
|
||||
|
||||
private float getKey(int segmentDataIndex, int[] segmentData) {
|
||||
return PgmIndexUtil.getKey(segmentDataIndex + KEY_SIZE, segmentData, 0f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a sentinel segment that is used to give a limit for the position approximation, but does
|
||||
* not count in the number of segments per level.
|
||||
*/
|
||||
private void addSentinelSegment(int endIndex) {
|
||||
// This sentinel segment is used in findSegment().
|
||||
accept(Double.MAX_VALUE, 0d, endIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(double firstKey, double slope, long intercept) {
|
||||
PgmIndexUtil.addIntercept(intercept, segmentData, KEY_SIZE);
|
||||
PgmIndexUtil.addKey((float) firstKey, segmentData);
|
||||
PgmIndexUtil.addSlope(slope, segmentData, KEY_SIZE);
|
||||
numSegments++;
|
||||
assert segmentData.size() == numSegments * SEGMENT_DATA_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Estimates the allocated memory. It does not count the memory for the list of keys, only for
|
||||
* the builder itself.
|
||||
*/
|
||||
@Override
|
||||
public long ramBytesAllocated() {
|
||||
// int: epsilon, epsilonRecursive, size, numSegments
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ 4 * Integer.BYTES
|
||||
// + keys.ramBytesAllocated()
|
||||
+ plam.ramBytesAllocated()
|
||||
+ segmentData.ramBytesAllocated();
|
||||
}
|
||||
|
||||
/**
|
||||
* Estimates the bytes that are actually used. It does not count the memory for the list of
|
||||
* keys, only for the builder itself.
|
||||
*/
|
||||
@Override
|
||||
public long ramBytesUsed() {
|
||||
// int: epsilon, epsilonRecursive, size, numSegments
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ 4 * Integer.BYTES
|
||||
// + keys.ramBytesUsed()
|
||||
+ plam.ramBytesUsed()
|
||||
+ segmentData.ramBytesUsed();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,137 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.FloatCursor;
|
||||
|
||||
/**
|
||||
* A subclass of {@link FloatArrayList} adding stack-related utility methods. The top of the stack
|
||||
* is at the <code>{@link #size()} - 1</code> element.
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeStack.java")
|
||||
public class FloatStack extends FloatArrayList {
|
||||
/** New instance with sane defaults. */
|
||||
public FloatStack() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
*/
|
||||
public FloatStack(int expectedElements) {
|
||||
super(expectedElements);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
* @param resizer Underlying buffer sizing strategy.
|
||||
*/
|
||||
public FloatStack(int expectedElements, ArraySizingStrategy resizer) {
|
||||
super(expectedElements, resizer);
|
||||
}
|
||||
|
||||
/** Create a stack by pushing all elements of another container to it. */
|
||||
public FloatStack(FloatContainer container) {
|
||||
super(container);
|
||||
}
|
||||
|
||||
/** Adds one float to the stack. */
|
||||
public void push(float e1) {
|
||||
ensureBufferSpace(1);
|
||||
buffer[elementsCount++] = e1;
|
||||
}
|
||||
|
||||
/** Adds two floats to the stack. */
|
||||
public void push(float e1, float e2) {
|
||||
ensureBufferSpace(2);
|
||||
buffer[elementsCount++] = e1;
|
||||
buffer[elementsCount++] = e2;
|
||||
}
|
||||
|
||||
/** Adds three floats to the stack. */
|
||||
public void push(float e1, float e2, float e3) {
|
||||
ensureBufferSpace(3);
|
||||
buffer[elementsCount++] = e1;
|
||||
buffer[elementsCount++] = e2;
|
||||
buffer[elementsCount++] = e3;
|
||||
}
|
||||
|
||||
/** Adds four floats to the stack. */
|
||||
public void push(float e1, float e2, float e3, float e4) {
|
||||
ensureBufferSpace(4);
|
||||
buffer[elementsCount++] = e1;
|
||||
buffer[elementsCount++] = e2;
|
||||
buffer[elementsCount++] = e3;
|
||||
buffer[elementsCount++] = e4;
|
||||
}
|
||||
|
||||
/** Add a range of array elements to the stack. */
|
||||
public void push(float[] elements, int start, int len) {
|
||||
assert start >= 0 && len >= 0;
|
||||
|
||||
ensureBufferSpace(len);
|
||||
System.arraycopy(elements, start, buffer, elementsCount, len);
|
||||
elementsCount += len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg-signature method for pushing elements at the top of the stack.
|
||||
*
|
||||
* <p><b>This method is handy, but costly if used in tight loops (anonymous array passing)</b>
|
||||
*/
|
||||
public final void push(float... elements) {
|
||||
push(elements, 0, elements.length);
|
||||
}
|
||||
|
||||
/** Pushes all elements from another container to the top of the stack. */
|
||||
public int pushAll(FloatContainer container) {
|
||||
return addAll(container);
|
||||
}
|
||||
|
||||
/** Pushes all elements from another iterable to the top of the stack. */
|
||||
public int pushAll(Iterable<? extends FloatCursor> iterable) {
|
||||
return addAll(iterable);
|
||||
}
|
||||
|
||||
/** Discard an arbitrary number of elements from the top of the stack. */
|
||||
public void discard(int count) {
|
||||
assert elementsCount >= count;
|
||||
|
||||
elementsCount -= count;
|
||||
}
|
||||
|
||||
/** Discard the top element from the stack. */
|
||||
public void discard() {
|
||||
assert elementsCount > 0;
|
||||
|
||||
elementsCount--;
|
||||
}
|
||||
|
||||
/** Remove the top element from the stack and return it. */
|
||||
public float pop() {
|
||||
return removeLast();
|
||||
}
|
||||
|
||||
/** Peek at the top element on the stack. */
|
||||
public float peek() {
|
||||
assert elementsCount > 0;
|
||||
return buffer[elementsCount - 1];
|
||||
}
|
||||
|
||||
/** Create a stack by pushing a variable number of arguments to it. */
|
||||
public static FloatStack from(float... elements) {
|
||||
final FloatStack stack = new FloatStack(elements.length);
|
||||
stack.push(elements);
|
||||
return stack;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public FloatStack clone() {
|
||||
return (FloatStack) super.clone();
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* HPPC
|
||||
*
|
||||
* Copyright (C) 2010-2024 Carrot Search s.c. and contributors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Refer to the full license file "LICENSE.txt":
|
||||
* https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
|
||||
*/
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.*;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Documented
|
||||
@Retention(SOURCE)
|
||||
@Target({PACKAGE, TYPE, ANNOTATION_TYPE, METHOD, CONSTRUCTOR, FIELD, LOCAL_VARIABLE, PARAMETER})
|
||||
public @interface Generated {
|
||||
/**
|
||||
* The value element MUST have the name of the code generator. The recommended convention is to
|
||||
* use the fully qualified name of the code generator. For example: com.acme.generator.CodeGen.
|
||||
*/
|
||||
String[] value();
|
||||
|
||||
/** Date when the source was generated. */
|
||||
String date() default "";
|
||||
|
||||
/**
|
||||
* A place holder for any comments that the code generator may want to include in the generated
|
||||
* code.
|
||||
*/
|
||||
String comments() default "";
|
||||
}
|
@ -1,112 +0,0 @@
|
||||
/*
|
||||
* HPPC
|
||||
*
|
||||
* Copyright (C) 2010-2024 Carrot Search s.c. and contributors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Refer to the full license file "LICENSE.txt":
|
||||
* https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
|
||||
*/
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public final class HashContainers {
|
||||
/**
|
||||
* Maximum array size for hash containers (power-of-two and still allocable in Java, not a
|
||||
* negative int).
|
||||
*/
|
||||
public static final int MAX_HASH_ARRAY_LENGTH = 0x80000000 >>> 1;
|
||||
|
||||
/** Minimum hash buffer size. */
|
||||
public static final int MIN_HASH_ARRAY_LENGTH = 4;
|
||||
|
||||
/** Default load factor. */
|
||||
public static final float DEFAULT_LOAD_FACTOR = 0.75f;
|
||||
|
||||
/** Minimal sane load factor (99 empty slots per 100). */
|
||||
public static final float MIN_LOAD_FACTOR = 1 / 100.0f;
|
||||
|
||||
/** Maximum sane load factor (1 empty slot per 100). */
|
||||
public static final float MAX_LOAD_FACTOR = 99 / 100.0f;
|
||||
|
||||
private static final AtomicInteger ITERATION_SEED = new AtomicInteger();
|
||||
|
||||
/**
|
||||
* Compute and return the maximum number of elements (inclusive) that can be stored in a hash
|
||||
* container for a given load factor.
|
||||
*/
|
||||
public static int maxElements(double loadFactor) {
|
||||
checkLoadFactor(loadFactor, 0, 1);
|
||||
return expandAtCount(MAX_HASH_ARRAY_LENGTH, loadFactor) - 1;
|
||||
}
|
||||
|
||||
/** */
|
||||
static int minBufferSize(int elements, double loadFactor) {
|
||||
if (elements < 0) {
|
||||
throw new IllegalArgumentException("Number of elements must be >= 0: " + elements);
|
||||
}
|
||||
|
||||
long length = (long) Math.ceil(elements / loadFactor);
|
||||
if (length == elements) {
|
||||
length++;
|
||||
}
|
||||
length = Math.max(MIN_HASH_ARRAY_LENGTH, BitUtil.nextHighestPowerOfTwo(length));
|
||||
|
||||
if (length > MAX_HASH_ARRAY_LENGTH) {
|
||||
throw new BufferAllocationException(
|
||||
"Maximum array size exceeded for this load factor (elements: %d, load factor: %f)",
|
||||
elements, loadFactor);
|
||||
}
|
||||
|
||||
return (int) length;
|
||||
}
|
||||
|
||||
/** */
|
||||
static int nextBufferSize(int arraySize, int elements, double loadFactor) {
|
||||
assert checkPowerOfTwo(arraySize);
|
||||
if (arraySize == MAX_HASH_ARRAY_LENGTH) {
|
||||
throw new BufferAllocationException(
|
||||
"Maximum array size exceeded for this load factor (elements: %d, load factor: %f)",
|
||||
elements, loadFactor);
|
||||
}
|
||||
|
||||
return (int) arraySize << 1;
|
||||
}
|
||||
|
||||
/** */
|
||||
static int expandAtCount(int arraySize, double loadFactor) {
|
||||
assert checkPowerOfTwo(arraySize);
|
||||
// Take care of hash container invariant (there has to be at least one empty slot to ensure
|
||||
// the lookup loop finds either the element or an empty slot).
|
||||
return Math.min(arraySize - 1, (int) Math.ceil(arraySize * loadFactor));
|
||||
}
|
||||
|
||||
/** */
|
||||
static void checkLoadFactor(
|
||||
double loadFactor, double minAllowedInclusive, double maxAllowedInclusive) {
|
||||
if (loadFactor < minAllowedInclusive || loadFactor > maxAllowedInclusive) {
|
||||
throw new BufferAllocationException(
|
||||
"The load factor should be in range [%.2f, %.2f]: %f",
|
||||
minAllowedInclusive, maxAllowedInclusive, loadFactor);
|
||||
}
|
||||
}
|
||||
|
||||
/** */
|
||||
static boolean checkPowerOfTwo(int arraySize) {
|
||||
// These are internals, we can just assert without retrying.
|
||||
assert arraySize > 1;
|
||||
assert BitUtil.nextHighestPowerOfTwo(arraySize) == arraySize;
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Provides the next hash iteration order seed. It is simply an incrementing atomic counter. */
|
||||
static int nextIterationSeed() {
|
||||
return ITERATION_SEED.incrementAndGet();
|
||||
}
|
||||
|
||||
/** Computes a hash iteration order increment based on the provided seed. */
|
||||
static int iterationIncrement(int seed) {
|
||||
return 29 + ((seed & 7) << 1); // Small odd integer.
|
||||
}
|
||||
}
|
@ -1,776 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import static com.carrotsearch.hppc.Containers.*;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.IntCursor;
|
||||
import com.carrotsearch.hppc.predicates.IntPredicate;
|
||||
import com.carrotsearch.hppc.procedures.IntProcedure;
|
||||
import java.util.*;
|
||||
|
||||
/** An array-backed {@link IntDeque}. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeArrayDeque.java")
|
||||
public class IntArrayDeque extends AbstractIntCollection
|
||||
implements IntDeque, Preallocable, Cloneable, Accountable {
|
||||
|
||||
/** Reuse the same strategy instance. */
|
||||
private static final BoundedProportionalArraySizingStrategy DEFAULT_SIZING_STRATEGY =
|
||||
BoundedProportionalArraySizingStrategy.DEFAULT_INSTANCE;
|
||||
|
||||
/** Internal array for storing elements of the deque. */
|
||||
public int[] buffer = IntArrayList.EMPTY_ARRAY;
|
||||
|
||||
/**
|
||||
* The index of the element at the head of the deque or an arbitrary number equal to tail if the
|
||||
* deque is empty.
|
||||
*/
|
||||
public int head;
|
||||
|
||||
/** The index at which the next element would be added to the tail of the deque. */
|
||||
public int tail;
|
||||
|
||||
/** Buffer resizing strategy. */
|
||||
protected final ArraySizingStrategy resizer;
|
||||
|
||||
/** New instance with sane defaults. */
|
||||
public IntArrayDeque() {
|
||||
this(DEFAULT_EXPECTED_ELEMENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
*/
|
||||
public IntArrayDeque(int expectedElements) {
|
||||
this(expectedElements, DEFAULT_SIZING_STRATEGY);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
* @param resizer Underlying buffer sizing strategy.
|
||||
*/
|
||||
public IntArrayDeque(int expectedElements, ArraySizingStrategy resizer) {
|
||||
assert resizer != null;
|
||||
this.resizer = resizer;
|
||||
ensureCapacity(expectedElements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deque from elements of another container, appending elements at the end of the
|
||||
* deque in the iteration order.
|
||||
*/
|
||||
public IntArrayDeque(IntContainer container) {
|
||||
this(container.size());
|
||||
addLast(container);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void addFirst(int e1) {
|
||||
int h = oneLeft(head, buffer.length);
|
||||
if (h == tail) {
|
||||
ensureBufferSpace(1);
|
||||
h = oneLeft(head, buffer.length);
|
||||
}
|
||||
buffer[head = h] = e1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg-signature method for adding elements at the front of this deque.
|
||||
*
|
||||
* <p><b>This method is handy, but costly if used in tight loops (anonymous array passing)</b>
|
||||
*
|
||||
* @param elements The elements to add.
|
||||
*/
|
||||
public final void addFirst(int... elements) {
|
||||
ensureBufferSpace(elements.length);
|
||||
for (int k : elements) {
|
||||
addFirst(k);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given container to the front of this deque.
|
||||
*
|
||||
* @param container The container to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addFirst(IntContainer container) {
|
||||
int size = container.size();
|
||||
ensureBufferSpace(size);
|
||||
|
||||
for (IntCursor cursor : container) {
|
||||
addFirst(cursor.value);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given iterable to the front of this deque.
|
||||
*
|
||||
* @param iterable The iterable to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addFirst(Iterable<? extends IntCursor> iterable) {
|
||||
int size = 0;
|
||||
for (IntCursor cursor : iterable) {
|
||||
addFirst(cursor.value);
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void addLast(int e1) {
|
||||
int t = oneRight(tail, buffer.length);
|
||||
if (head == t) {
|
||||
ensureBufferSpace(1);
|
||||
t = oneRight(tail, buffer.length);
|
||||
}
|
||||
buffer[tail] = e1;
|
||||
tail = t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg-signature method for adding elements at the end of this deque.
|
||||
*
|
||||
* <p><b>This method is handy, but costly if used in tight loops (anonymous array passing)</b>
|
||||
*
|
||||
* @param elements The elements to iterate over.
|
||||
*/
|
||||
public final void addLast(int... elements) {
|
||||
ensureBufferSpace(1);
|
||||
for (int k : elements) {
|
||||
addLast(k);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given container to the end of this deque.
|
||||
*
|
||||
* @param container The container to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addLast(IntContainer container) {
|
||||
int size = container.size();
|
||||
ensureBufferSpace(size);
|
||||
|
||||
for (IntCursor cursor : container) {
|
||||
addLast(cursor.value);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given iterable to the end of this deque.
|
||||
*
|
||||
* @param iterable The iterable to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addLast(Iterable<? extends IntCursor> iterable) {
|
||||
int size = 0;
|
||||
for (IntCursor cursor : iterable) {
|
||||
addLast(cursor.value);
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeFirst() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
final int result = buffer[head];
|
||||
buffer[head] = 0;
|
||||
head = oneRight(head, buffer.length);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeLast() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
tail = oneLeft(tail, buffer.length);
|
||||
final int result = buffer[tail];
|
||||
buffer[tail] = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int getFirst() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
return buffer[head];
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int getLast() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
return buffer[oneLeft(tail, buffer.length)];
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeFirst(int e1) {
|
||||
final int index = bufferIndexOf(e1);
|
||||
if (index >= 0) removeAtBufferIndex(index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index of the first (counting from head) element equal to <code>e1</code>. The index
|
||||
* points to the {@link #buffer} array.
|
||||
*
|
||||
* @param e1 The element to look for.
|
||||
* @return Returns the index of the first element equal to <code>e1</code> or <code>-1</code> if
|
||||
* not found.
|
||||
*/
|
||||
public int bufferIndexOf(int e1) {
|
||||
final int last = tail;
|
||||
final int bufLen = buffer.length;
|
||||
for (int i = head; i != last; i = oneRight(i, bufLen)) {
|
||||
if (((e1) == (buffer[i]))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeLast(int e1) {
|
||||
final int index = lastBufferIndexOf(e1);
|
||||
if (index >= 0) {
|
||||
removeAtBufferIndex(index);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index of the last (counting from tail) element equal to <code>e1</code>. The index
|
||||
* points to the {@link #buffer} array.
|
||||
*
|
||||
* @param e1 The element to look for.
|
||||
* @return Returns the index of the first element equal to <code>e1</code> or <code>-1</code> if
|
||||
* not found.
|
||||
*/
|
||||
public int lastBufferIndexOf(int e1) {
|
||||
final int bufLen = buffer.length;
|
||||
final int last = oneLeft(head, bufLen);
|
||||
for (int i = oneLeft(tail, bufLen); i != last; i = oneLeft(i, bufLen)) {
|
||||
if (((e1) == (buffer[i]))) return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(int e1) {
|
||||
int removed = 0;
|
||||
final int last = tail;
|
||||
final int bufLen = buffer.length;
|
||||
int from, to;
|
||||
for (from = to = head; from != last; from = oneRight(from, bufLen)) {
|
||||
if (((e1) == (buffer[from]))) {
|
||||
buffer[from] = 0;
|
||||
removed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = 0;
|
||||
}
|
||||
|
||||
to = oneRight(to, bufLen);
|
||||
}
|
||||
|
||||
tail = to;
|
||||
return removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the element at <code>index</code> in the internal {#link {@link #buffer} array,
|
||||
* returning its value.
|
||||
*
|
||||
* @param index Index of the element to remove. The index must be located between {@link #head}
|
||||
* and {@link #tail} in modulo {@link #buffer} arithmetic.
|
||||
*/
|
||||
public void removeAtBufferIndex(int index) {
|
||||
assert (head <= tail ? index >= head && index < tail : index >= head || index < tail)
|
||||
: "Index out of range (head=" + head + ", tail=" + tail + ", index=" + index + ").";
|
||||
|
||||
// Cache fields in locals (hopefully moved to registers).
|
||||
final int[] buffer = this.buffer;
|
||||
final int bufLen = buffer.length;
|
||||
final int lastIndex = bufLen - 1;
|
||||
final int head = this.head;
|
||||
final int tail = this.tail;
|
||||
|
||||
final int leftChunk = Math.abs(index - head) % bufLen;
|
||||
final int rightChunk = Math.abs(tail - index) % bufLen;
|
||||
|
||||
if (leftChunk < rightChunk) {
|
||||
if (index >= head) {
|
||||
System.arraycopy(buffer, head, buffer, head + 1, leftChunk);
|
||||
} else {
|
||||
System.arraycopy(buffer, 0, buffer, 1, index);
|
||||
buffer[0] = buffer[lastIndex];
|
||||
System.arraycopy(buffer, head, buffer, head + 1, lastIndex - head);
|
||||
}
|
||||
buffer[head] = 0;
|
||||
this.head = oneRight(head, bufLen);
|
||||
} else {
|
||||
if (index < tail) {
|
||||
System.arraycopy(buffer, index + 1, buffer, index, rightChunk);
|
||||
} else {
|
||||
System.arraycopy(buffer, index + 1, buffer, index, lastIndex - index);
|
||||
buffer[lastIndex] = buffer[0];
|
||||
System.arraycopy(buffer, 1, buffer, 0, tail);
|
||||
}
|
||||
buffer[tail] = 0;
|
||||
this.tail = oneLeft(tail, bufLen);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int size() {
|
||||
if (head <= tail) return tail - head;
|
||||
else return (tail - head + buffer.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The internal array buffers are not released as a result of this call.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
if (head < tail) {
|
||||
Arrays.fill(buffer, head, tail, 0);
|
||||
} else {
|
||||
Arrays.fill(buffer, 0, tail, 0);
|
||||
Arrays.fill(buffer, head, buffer.length, 0);
|
||||
}
|
||||
this.head = tail = 0;
|
||||
}
|
||||
|
||||
/** Release internal buffers of this deque and reallocate with the default buffer. */
|
||||
public void release() {
|
||||
this.head = tail = 0;
|
||||
buffer = IntArrayList.EMPTY_ARRAY;
|
||||
ensureBufferSpace(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure this container can hold at least the given number of elements without resizing its
|
||||
* buffers.
|
||||
*
|
||||
* @param expectedElements The total number of elements, inclusive.
|
||||
*/
|
||||
@Override
|
||||
public void ensureCapacity(int expectedElements) {
|
||||
ensureBufferSpace(expectedElements - size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the internal buffer has enough free slots to store <code>expectedAdditions</code>.
|
||||
* Increases internal buffer size if needed.
|
||||
*/
|
||||
protected void ensureBufferSpace(int expectedAdditions) {
|
||||
final int bufferLen = buffer.length;
|
||||
final int elementsCount = size();
|
||||
|
||||
if (elementsCount + expectedAdditions >= bufferLen) {
|
||||
final int emptySlot = 1; // deque invariant: always an empty slot.
|
||||
final int newSize = resizer.grow(bufferLen, elementsCount + emptySlot, expectedAdditions);
|
||||
assert newSize >= (elementsCount + expectedAdditions + emptySlot)
|
||||
: "Resizer failed to"
|
||||
+ " return sensible new size: "
|
||||
+ newSize
|
||||
+ " <= "
|
||||
+ (elementsCount + expectedAdditions);
|
||||
|
||||
try {
|
||||
final int[] newBuffer = (new int[newSize]);
|
||||
if (bufferLen > 0) {
|
||||
toArray(newBuffer);
|
||||
tail = elementsCount;
|
||||
head = 0;
|
||||
}
|
||||
this.buffer = newBuffer;
|
||||
} catch (OutOfMemoryError e) {
|
||||
throw new BufferAllocationException(
|
||||
"Not enough memory to allocate new buffers: %,d -> %,d", e, bufferLen, newSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int[] toArray() {
|
||||
|
||||
final int size = size();
|
||||
return toArray((new int[size]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies elements of this deque to an array. The content of the <code>target</code> array is
|
||||
* filled from index 0 (head of the queue) to index <code>size() - 1</code> (tail of the queue).
|
||||
*
|
||||
* @param target The target array must be large enough to hold all elements.
|
||||
* @return Returns the target argument for chaining.
|
||||
*/
|
||||
public int[] toArray(int[] target) {
|
||||
assert target.length >= size() : "Target array must be >= " + size();
|
||||
|
||||
if (head < tail) {
|
||||
// The contents is not wrapped around. Just copy.
|
||||
System.arraycopy(buffer, head, target, 0, size());
|
||||
} else if (head > tail) {
|
||||
// The contents is split. Merge elements from the following indexes:
|
||||
// [head...buffer.length - 1][0, tail - 1]
|
||||
final int rightCount = buffer.length - head;
|
||||
System.arraycopy(buffer, head, target, 0, rightCount);
|
||||
System.arraycopy(buffer, 0, target, rightCount, tail);
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone this object. The returned clone will reuse the same hash function and array resizing
|
||||
* strategy.
|
||||
*/
|
||||
@Override
|
||||
public IntArrayDeque clone() {
|
||||
try {
|
||||
|
||||
IntArrayDeque cloned = (IntArrayDeque) super.clone();
|
||||
cloned.buffer = buffer.clone();
|
||||
return cloned;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Move one index to the left, wrapping around buffer. */
|
||||
protected static int oneLeft(int index, int modulus) {
|
||||
if (index >= 1) {
|
||||
return index - 1;
|
||||
}
|
||||
return modulus - 1;
|
||||
}
|
||||
|
||||
/** Move one index to the right, wrapping around buffer. */
|
||||
protected static int oneRight(int index, int modulus) {
|
||||
if (index + 1 == modulus) {
|
||||
return 0;
|
||||
}
|
||||
return index + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesAllocated() {
|
||||
// int: head, tail
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES * 2
|
||||
+ resizer.ramBytesAllocated()
|
||||
+ RamUsageEstimator.shallowSizeOfArray(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesUsed() {
|
||||
// int: head, tail
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES * 2
|
||||
+ resizer.ramBytesUsed()
|
||||
+ RamUsageEstimator.shallowUsedSizeOfArray(buffer, size());
|
||||
}
|
||||
|
||||
/** An iterator implementation for {@link ObjectArrayDeque#iterator}. */
|
||||
private final class ValueIterator extends AbstractIterator<IntCursor> {
|
||||
private final IntCursor cursor;
|
||||
private int remaining;
|
||||
|
||||
public ValueIterator() {
|
||||
cursor = new IntCursor();
|
||||
cursor.index = oneLeft(head, buffer.length);
|
||||
this.remaining = size();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IntCursor fetch() {
|
||||
if (remaining == 0) {
|
||||
return done();
|
||||
}
|
||||
|
||||
remaining--;
|
||||
cursor.value = buffer[cursor.index = oneRight(cursor.index, buffer.length)];
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
/** An iterator implementation for {@link ObjectArrayDeque#descendingIterator()}. */
|
||||
private final class DescendingValueIterator extends AbstractIterator<IntCursor> {
|
||||
private final IntCursor cursor;
|
||||
private int remaining;
|
||||
|
||||
public DescendingValueIterator() {
|
||||
cursor = new IntCursor();
|
||||
cursor.index = tail;
|
||||
this.remaining = size();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IntCursor fetch() {
|
||||
if (remaining == 0) return done();
|
||||
|
||||
remaining--;
|
||||
cursor.value = buffer[cursor.index = oneLeft(cursor.index, buffer.length)];
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a cursor over the values of this deque (in head to tail order). The iterator is
|
||||
* implemented as a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()} (to avoid boxing of primitive types). To read the current value (or index in
|
||||
* the deque's buffer) use the cursor's public fields. An example is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntValueCursor c : intDeque) {
|
||||
* System.out.println("buffer index=" + c.index + " value=" + c.value);
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public Iterator<IntCursor> iterator() {
|
||||
return new ValueIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a cursor over the values of this deque (in tail to head order). The iterator is
|
||||
* implemented as a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()} (to avoid boxing of primitive types). To read the current value (or index in
|
||||
* the deque's buffer) use the cursor's public fields. An example is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (Iterator<IntCursor> i = intDeque.descendingIterator(); i.hasNext();) {
|
||||
* final IntCursor c = i.next();
|
||||
* System.out.println("buffer index=" + c.index + " value=" + c.value);
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public Iterator<IntCursor> descendingIterator() {
|
||||
return new DescendingValueIterator();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends IntProcedure> T forEach(T procedure) {
|
||||
forEach(procedure, head, tail);
|
||||
return procedure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>procedure</code> to a slice of the deque, <code>fromIndex</code>, inclusive, to
|
||||
* <code>toIndex</code>, exclusive.
|
||||
*/
|
||||
private void forEach(IntProcedure procedure, int fromIndex, final int toIndex) {
|
||||
final int[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
procedure.apply(buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends IntPredicate> T forEach(T predicate) {
|
||||
int fromIndex = head;
|
||||
int toIndex = tail;
|
||||
|
||||
final int[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
if (!predicate.apply(buffer[i])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return predicate;
|
||||
}
|
||||
|
||||
/** Applies <code>procedure</code> to all elements of this deque, tail to head. */
|
||||
@Override
|
||||
public <T extends IntProcedure> T descendingForEach(T procedure) {
|
||||
descendingForEach(procedure, head, tail);
|
||||
return procedure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>procedure</code> to a slice of the deque, <code>toIndex</code>, exclusive, down
|
||||
* to <code>fromIndex</code>, inclusive.
|
||||
*/
|
||||
private void descendingForEach(IntProcedure procedure, int fromIndex, final int toIndex) {
|
||||
if (fromIndex == toIndex) return;
|
||||
|
||||
final int[] buffer = this.buffer;
|
||||
int i = toIndex;
|
||||
do {
|
||||
i = oneLeft(i, buffer.length);
|
||||
procedure.apply(buffer[i]);
|
||||
} while (i != fromIndex);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends IntPredicate> T descendingForEach(T predicate) {
|
||||
descendingForEach(predicate, head, tail);
|
||||
return predicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>predicate</code> to a slice of the deque, <code>toIndex</code>, exclusive, down
|
||||
* to <code>fromIndex</code>, inclusive or until the predicate returns <code>false</code>.
|
||||
*/
|
||||
private void descendingForEach(IntPredicate predicate, int fromIndex, final int toIndex) {
|
||||
if (fromIndex == toIndex) return;
|
||||
|
||||
final int[] buffer = this.buffer;
|
||||
int i = toIndex;
|
||||
do {
|
||||
i = oneLeft(i, buffer.length);
|
||||
if (!predicate.apply(buffer[i])) {
|
||||
break;
|
||||
}
|
||||
} while (i != fromIndex);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(IntPredicate predicate) {
|
||||
final int[] buffer = this.buffer;
|
||||
final int last = tail;
|
||||
final int bufLen = buffer.length;
|
||||
int removed = 0;
|
||||
int from, to;
|
||||
from = to = head;
|
||||
try {
|
||||
for (from = to = head; from != last; from = oneRight(from, bufLen)) {
|
||||
if (predicate.apply(buffer[from])) {
|
||||
buffer[from] = 0;
|
||||
removed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = 0;
|
||||
}
|
||||
|
||||
to = oneRight(to, bufLen);
|
||||
}
|
||||
} finally {
|
||||
// Keep the deque in consistent state even if the predicate throws an exception.
|
||||
for (; from != last; from = oneRight(from, bufLen)) {
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = 0;
|
||||
}
|
||||
|
||||
to = oneRight(to, bufLen);
|
||||
}
|
||||
tail = to;
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean contains(int e) {
|
||||
int fromIndex = head;
|
||||
int toIndex = tail;
|
||||
|
||||
final int[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
if (((e) == (buffer[i]))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = 1;
|
||||
int fromIndex = head;
|
||||
int toIndex = tail;
|
||||
|
||||
final int[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
h = 31 * h + BitMixer.mix(this.buffer[i]);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> only if the other object is an instance of the same class and with
|
||||
* the same elements.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return (this == obj)
|
||||
|| (obj != null && getClass() == obj.getClass() && equalElements(getClass().cast(obj)));
|
||||
}
|
||||
|
||||
/** Compare order-aligned elements against another {@link IntDeque}. */
|
||||
protected boolean equalElements(IntArrayDeque other) {
|
||||
int max = size();
|
||||
if (other.size() != max) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Iterator<IntCursor> i1 = this.iterator();
|
||||
Iterator<? extends IntCursor> i2 = other.iterator();
|
||||
|
||||
while (i1.hasNext() && i2.hasNext()) {
|
||||
if (!((i1.next().value) == (i2.next().value))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return !i1.hasNext() && !i2.hasNext();
|
||||
}
|
||||
|
||||
/** Create a new deque by pushing a variable number of arguments to the end of it. */
|
||||
public static IntArrayDeque from(int... elements) {
|
||||
final IntArrayDeque coll = new IntArrayDeque(elements.length);
|
||||
coll.addLast(elements);
|
||||
return coll;
|
||||
}
|
||||
}
|
@ -1,586 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import static com.carrotsearch.hppc.Containers.*;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.IntPredicate;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.*;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
/** An array-backed list of ints. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeArrayList.java")
|
||||
public class IntArrayList extends AbstractIntCollection
|
||||
implements IntIndexedContainer, Preallocable, Cloneable, Accountable {
|
||||
/** An immutable empty buffer (array). */
|
||||
public static final int[] EMPTY_ARRAY = new int[0];
|
||||
|
||||
;
|
||||
|
||||
/** Reuse the same strategy instance. */
|
||||
private static final BoundedProportionalArraySizingStrategy DEFAULT_SIZING_STRATEGY =
|
||||
BoundedProportionalArraySizingStrategy.DEFAULT_INSTANCE;
|
||||
|
||||
/**
|
||||
* Internal array for storing the list. The array may be larger than the current size ({@link
|
||||
* #size()}).
|
||||
*/
|
||||
public int[] buffer = EMPTY_ARRAY;
|
||||
|
||||
/** Current number of elements stored in {@link #buffer}. */
|
||||
public int elementsCount;
|
||||
|
||||
/** Buffer resizing strategy. */
|
||||
protected final ArraySizingStrategy resizer;
|
||||
|
||||
/** New instance with sane defaults. */
|
||||
public IntArrayList() {
|
||||
this(DEFAULT_EXPECTED_ELEMENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
*/
|
||||
public IntArrayList(int expectedElements) {
|
||||
this(expectedElements, DEFAULT_SIZING_STRATEGY);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
* @param resizer Underlying buffer sizing strategy.
|
||||
*/
|
||||
public IntArrayList(int expectedElements, ArraySizingStrategy resizer) {
|
||||
assert resizer != null;
|
||||
this.resizer = resizer;
|
||||
buffer = Arrays.copyOf(buffer, expectedElements);
|
||||
}
|
||||
|
||||
/** Creates a new list from the elements of another container in its iteration order. */
|
||||
public IntArrayList(IntContainer container) {
|
||||
this(container.size());
|
||||
addAll(container);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void add(int e1) {
|
||||
ensureBufferSpace(1);
|
||||
buffer[elementsCount++] = e1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends two elements at the end of the list. To add more than two elements, use <code>add
|
||||
* </code> (vararg-version) or access the buffer directly (tight loop).
|
||||
*/
|
||||
public void add(int e1, int e2) {
|
||||
ensureBufferSpace(2);
|
||||
buffer[elementsCount++] = e1;
|
||||
buffer[elementsCount++] = e2;
|
||||
}
|
||||
|
||||
/** Add all elements from a range of given array to the list. */
|
||||
public void add(int[] elements, int start, int length) {
|
||||
assert length >= 0 : "Length must be >= 0";
|
||||
|
||||
ensureBufferSpace(length);
|
||||
System.arraycopy(elements, start, buffer, elementsCount, length);
|
||||
elementsCount += length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg-signature method for adding elements at the end of the list.
|
||||
*
|
||||
* <p><b>This method is handy, but costly if used in tight loops (anonymous array passing)</b>
|
||||
*/
|
||||
public final void add(int... elements) {
|
||||
add(elements, 0, elements.length);
|
||||
}
|
||||
|
||||
/** Adds all elements from another container. */
|
||||
public int addAll(IntContainer container) {
|
||||
final int size = container.size();
|
||||
ensureBufferSpace(size);
|
||||
|
||||
for (IntCursor cursor : container) {
|
||||
add(cursor.value);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/** Adds all elements from another iterable. */
|
||||
public int addAll(Iterable<? extends IntCursor> iterable) {
|
||||
int size = 0;
|
||||
for (IntCursor cursor : iterable) {
|
||||
add(cursor.value);
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void insert(int index, int e1) {
|
||||
assert (index >= 0 && index <= size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
|
||||
ensureBufferSpace(1);
|
||||
System.arraycopy(buffer, index, buffer, index + 1, elementsCount - index);
|
||||
buffer[index] = e1;
|
||||
elementsCount++;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int get(int index) {
|
||||
assert (index >= 0 && index < size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
return buffer[index];
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int set(int index, int e1) {
|
||||
assert (index >= 0 && index < size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
final int v = buffer[index];
|
||||
buffer[index] = e1;
|
||||
return v;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAt(int index) {
|
||||
assert (index >= 0 && index < size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
final int v = buffer[index];
|
||||
System.arraycopy(buffer, index + 1, buffer, index, --elementsCount - index);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeLast() {
|
||||
assert elementsCount > 0;
|
||||
|
||||
final int v = buffer[--elementsCount];
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void removeRange(int fromIndex, int toIndex) {
|
||||
assert (fromIndex >= 0 && fromIndex <= size())
|
||||
: "Index " + fromIndex + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
assert (toIndex >= 0 && toIndex <= size())
|
||||
: "Index " + toIndex + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
assert fromIndex <= toIndex : "fromIndex must be <= toIndex: " + fromIndex + ", " + toIndex;
|
||||
|
||||
System.arraycopy(buffer, toIndex, buffer, fromIndex, elementsCount - toIndex);
|
||||
final int count = toIndex - fromIndex;
|
||||
elementsCount -= count;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean removeElement(int e1) {
|
||||
return removeFirst(e1) != -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeFirst(int e1) {
|
||||
final int index = indexOf(e1);
|
||||
if (index >= 0) removeAt(index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeLast(int e1) {
|
||||
final int index = lastIndexOf(e1);
|
||||
if (index >= 0) removeAt(index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(int e1) {
|
||||
int to = 0;
|
||||
for (int from = 0; from < elementsCount; from++) {
|
||||
if (((e1) == (buffer[from]))) {
|
||||
continue;
|
||||
}
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
}
|
||||
to++;
|
||||
}
|
||||
final int deleted = elementsCount - to;
|
||||
this.elementsCount = to;
|
||||
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean contains(int e1) {
|
||||
return indexOf(e1) >= 0;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int indexOf(int e1) {
|
||||
for (int i = 0; i < elementsCount; i++) {
|
||||
if (((e1) == (buffer[i]))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int lastIndexOf(int e1) {
|
||||
for (int i = elementsCount - 1; i >= 0; i--) {
|
||||
if (((e1) == (buffer[i]))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return elementsCount == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure this container can hold at least the given number of elements without resizing its
|
||||
* buffers.
|
||||
*
|
||||
* @param expectedElements The total number of elements, inclusive.
|
||||
*/
|
||||
@Override
|
||||
public void ensureCapacity(int expectedElements) {
|
||||
final int bufferLen = (buffer == null ? 0 : buffer.length);
|
||||
if (expectedElements > bufferLen) {
|
||||
ensureBufferSpace(expectedElements - size());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the internal buffer has enough free slots to store <code>expectedAdditions</code>.
|
||||
* Increases internal buffer size if needed.
|
||||
*/
|
||||
protected void ensureBufferSpace(int expectedAdditions) {
|
||||
final int bufferLen = (buffer == null ? 0 : buffer.length);
|
||||
if (elementsCount + expectedAdditions > bufferLen) {
|
||||
final int newSize = resizer.grow(bufferLen, elementsCount, expectedAdditions);
|
||||
assert newSize >= elementsCount + expectedAdditions
|
||||
: "Resizer failed to"
|
||||
+ " return sensible new size: "
|
||||
+ newSize
|
||||
+ " <= "
|
||||
+ (elementsCount + expectedAdditions);
|
||||
|
||||
this.buffer = Arrays.copyOf(buffer, newSize);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate or expand the list to the new size. If the list is truncated, the buffer will not be
|
||||
* reallocated (use {@link #trimToSize()} if you need a truncated buffer), but the truncated
|
||||
* values will be reset to the default value (zero). If the list is expanded, the elements beyond
|
||||
* the current size are initialized with JVM-defaults (zero or <code>null</code> values).
|
||||
*/
|
||||
public void resize(int newSize) {
|
||||
if (newSize <= buffer.length) {
|
||||
if (newSize < elementsCount) {
|
||||
Arrays.fill(buffer, newSize, elementsCount, 0);
|
||||
} else {
|
||||
Arrays.fill(buffer, elementsCount, newSize, 0);
|
||||
}
|
||||
} else {
|
||||
ensureCapacity(newSize);
|
||||
}
|
||||
this.elementsCount = newSize;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int size() {
|
||||
return elementsCount;
|
||||
}
|
||||
|
||||
/** Trim the internal buffer to the current size. */
|
||||
public void trimToSize() {
|
||||
if (size() != this.buffer.length) {
|
||||
this.buffer = toArray();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of stored elements to zero. Releases and initializes the internal storage array
|
||||
* to default values. To clear the list without cleaning the buffer, simply set the {@link
|
||||
* #elementsCount} field to zero.
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
Arrays.fill(buffer, 0, elementsCount, 0);
|
||||
this.elementsCount = 0;
|
||||
}
|
||||
|
||||
/** Sets the number of stored elements to zero and releases the internal storage array. */
|
||||
@Override
|
||||
public void release() {
|
||||
this.buffer = EMPTY_ARRAY;
|
||||
this.elementsCount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The returned array is sized to match exactly the number of elements of the stack.
|
||||
*/
|
||||
@Override
|
||||
public int[] toArray() {
|
||||
|
||||
return Arrays.copyOf(buffer, elementsCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntStream stream() {
|
||||
|
||||
return Arrays.stream(buffer, 0, size());
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public IntIndexedContainer sort() {
|
||||
Arrays.sort(buffer, 0, elementsCount);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public IntIndexedContainer reverse() {
|
||||
for (int i = 0, mid = elementsCount >> 1, j = elementsCount - 1; i < mid; i++, j--) {
|
||||
int tmp = buffer[i];
|
||||
buffer[i] = buffer[j];
|
||||
buffer[j] = tmp;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone this object. The returned clone will reuse the same hash function and array resizing
|
||||
* strategy.
|
||||
*/
|
||||
@Override
|
||||
public IntArrayList clone() {
|
||||
try {
|
||||
|
||||
final IntArrayList cloned = (IntArrayList) super.clone();
|
||||
cloned.buffer = buffer.clone();
|
||||
return cloned;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = 1, max = elementsCount;
|
||||
for (int i = 0; i < max; i++) {
|
||||
h = 31 * h + BitMixer.mix(this.buffer[i]);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> only if the other object is an instance of the same class and with
|
||||
* the same elements.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return (this == obj)
|
||||
|| (obj != null && getClass() == obj.getClass() && equalElements(getClass().cast(obj)));
|
||||
}
|
||||
|
||||
/** Compare index-aligned elements against another {@link IntIndexedContainer}. */
|
||||
protected boolean equalElements(IntArrayList other) {
|
||||
int max = size();
|
||||
if (other.size() != max) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < max; i++) {
|
||||
if (!((get(i)) == (other.get(i)))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesAllocated() {
|
||||
// int: elementsCount
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES
|
||||
+ resizer.ramBytesAllocated()
|
||||
+ RamUsageEstimator.shallowSizeOfArray(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesUsed() {
|
||||
// int: elementsCount
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES
|
||||
+ resizer.ramBytesUsed()
|
||||
+ RamUsageEstimator.shallowUsedSizeOfArray(buffer, elementsCount);
|
||||
}
|
||||
|
||||
/** An iterator implementation for {@link IntArrayList#iterator}. */
|
||||
static final class ValueIterator extends AbstractIterator<IntCursor> {
|
||||
private final IntCursor cursor;
|
||||
|
||||
private final int[] buffer;
|
||||
private final int size;
|
||||
|
||||
public ValueIterator(int[] buffer, int size) {
|
||||
this.cursor = new IntCursor();
|
||||
this.cursor.index = -1;
|
||||
this.size = size;
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IntCursor fetch() {
|
||||
if (cursor.index + 1 == size) return done();
|
||||
|
||||
cursor.value = buffer[++cursor.index];
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public Iterator<IntCursor> iterator() {
|
||||
return new ValueIterator(buffer, size());
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends IntProcedure> T forEach(T procedure) {
|
||||
return forEach(procedure, 0, size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>procedure</code> to a slice of the list, <code>fromIndex</code>, inclusive, to
|
||||
* <code>toIndex</code>, exclusive.
|
||||
*/
|
||||
public <T extends IntProcedure> T forEach(T procedure, int fromIndex, final int toIndex) {
|
||||
assert (fromIndex >= 0 && fromIndex <= size())
|
||||
: "Index " + fromIndex + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
assert (toIndex >= 0 && toIndex <= size())
|
||||
: "Index " + toIndex + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
|
||||
assert fromIndex <= toIndex : "fromIndex must be <= toIndex: " + fromIndex + ", " + toIndex;
|
||||
|
||||
final int[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i < toIndex; i++) {
|
||||
procedure.apply(buffer[i]);
|
||||
}
|
||||
|
||||
return procedure;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(IntPredicate predicate) {
|
||||
final int[] buffer = this.buffer;
|
||||
final int elementsCount = this.elementsCount;
|
||||
int to = 0;
|
||||
int from = 0;
|
||||
try {
|
||||
for (; from < elementsCount; from++) {
|
||||
if (predicate.apply(buffer[from])) {
|
||||
buffer[from] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = 0;
|
||||
}
|
||||
to++;
|
||||
}
|
||||
} finally {
|
||||
// Keep the list in a consistent state, even if the predicate throws an exception.
|
||||
for (; from < elementsCount; from++) {
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = 0;
|
||||
}
|
||||
to++;
|
||||
}
|
||||
|
||||
this.elementsCount = to;
|
||||
}
|
||||
|
||||
return elementsCount - to;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends IntPredicate> T forEach(T predicate) {
|
||||
return forEach(predicate, 0, size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>predicate</code> to a slice of the list, <code>fromIndex</code>, inclusive, to
|
||||
* <code>toIndex</code>, exclusive, or until predicate returns <code>false</code>.
|
||||
*/
|
||||
public <T extends IntPredicate> T forEach(T predicate, int fromIndex, final int toIndex) {
|
||||
assert (fromIndex >= 0 && fromIndex <= size())
|
||||
: "Index " + fromIndex + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
assert (toIndex >= 0 && toIndex <= size())
|
||||
: "Index " + toIndex + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
assert fromIndex <= toIndex : "fromIndex must be <= toIndex: " + fromIndex + ", " + toIndex;
|
||||
|
||||
final int[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i < toIndex; i++) {
|
||||
if (!predicate.apply(buffer[i])) break;
|
||||
}
|
||||
|
||||
return predicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a list from a variable number of arguments or an array of <code>int</code>. The elements
|
||||
* are copied from the argument to the internal buffer.
|
||||
*/
|
||||
public static IntArrayList from(int... elements) {
|
||||
final IntArrayList list = new IntArrayList(elements.length);
|
||||
list.add(elements);
|
||||
return list;
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
/**
|
||||
* Reused buffer visualization routines.
|
||||
*
|
||||
* @see IntSet#visualizeKeyDistribution(int)
|
||||
* @see IntVTypeMap#visualizeKeyDistribution(int)
|
||||
*/
|
||||
class IntBufferVisualizer {
|
||||
static String visualizeKeyDistribution(int[] buffer, int max, int characters) {
|
||||
final StringBuilder b = new StringBuilder();
|
||||
final char[] chars = ".123456789X".toCharArray();
|
||||
for (int i = 1, start = -1; i <= characters; i++) {
|
||||
int end = (int) ((long) i * max / characters);
|
||||
|
||||
if (start + 1 <= end) {
|
||||
int taken = 0;
|
||||
int slots = 0;
|
||||
for (int slot = start + 1; slot <= end; slot++, slots++) {
|
||||
if (!((buffer[slot]) == 0)) {
|
||||
taken++;
|
||||
}
|
||||
}
|
||||
b.append(chars[Math.min(chars.length - 1, taken * chars.length / slots)]);
|
||||
start = end;
|
||||
}
|
||||
}
|
||||
while (b.length() < characters) {
|
||||
b.append(' ');
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.*;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* An associative container from keys to (one or possibly more) values.
|
||||
*
|
||||
* @see IntContainer
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeVTypeAssociativeContainer.java")
|
||||
public interface IntByteAssociativeContainer extends Iterable<IntByteCursor> {
|
||||
/**
|
||||
* Returns a cursor over the entries (key-value pairs) in this map. The iterator is implemented as
|
||||
* a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()}. To read the current key and value use the cursor's public fields. An example
|
||||
* is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntShortCursor c : intShortMap) {
|
||||
* System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
|
||||
* }</pre>
|
||||
*
|
||||
* <p>The <code>index</code> field inside the cursor gives the internal index inside the
|
||||
* container's implementation. The interpretation of this index depends on to the container.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<IntByteCursor> iterator();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this container has an association to a value for the given key.
|
||||
*/
|
||||
public boolean containsKey(int key);
|
||||
|
||||
/**
|
||||
* @return Returns the current size (number of assigned keys) in the container.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/**
|
||||
* @return Return <code>true</code> if this hash map contains no assigned keys.
|
||||
*/
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) present in a given container. An alias to:
|
||||
*
|
||||
* <pre>
|
||||
* keys().removeAll(container)
|
||||
* </pre>
|
||||
*
|
||||
* but with no additional overhead.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(IntContainer container);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(IntPredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(IntBytePredicate predicate);
|
||||
|
||||
/**
|
||||
* Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link IntByteProcedure}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*/
|
||||
public <T extends IntByteProcedure> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a given predicate to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link IntBytePredicate}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*
|
||||
* <p>The iteration is continued as long as the predicate returns <code>true</code>.
|
||||
*/
|
||||
public <T extends IntBytePredicate> T forEach(T predicate);
|
||||
|
||||
/**
|
||||
* Returns a collection of keys of this container. The returned collection is a view over the key
|
||||
* set and any modifications (if allowed) introduced to the collection will propagate to the
|
||||
* associative container immediately.
|
||||
*/
|
||||
public IntCollection keys();
|
||||
|
||||
/**
|
||||
* Returns a container view of all values present in this container. The returned collection is a
|
||||
* view over the key set and any modifications (if allowed) introduced to the collection will
|
||||
* propagate to the associative container immediately.
|
||||
*/
|
||||
public ByteContainer values();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,205 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.IntByteCursor;
|
||||
|
||||
/** An associative container with unique binding from keys to a single value. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeVTypeMap.java")
|
||||
public interface IntByteMap extends IntByteAssociativeContainer {
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the default value for the value
|
||||
* type, if the key is not associated with any value. For numeric value types, this default
|
||||
* value is 0, for object types it is {@code null}.
|
||||
*/
|
||||
public byte get(int key);
|
||||
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the provided default value if the
|
||||
* key is not associated with any value.
|
||||
*/
|
||||
public byte getOrDefault(int key, byte defaultValue);
|
||||
|
||||
/**
|
||||
* Place a given key and value in the container.
|
||||
*
|
||||
* @return The value previously stored under the given key in the map is returned.
|
||||
*/
|
||||
public byte put(int key, byte value);
|
||||
|
||||
/**
|
||||
* If the specified key is not already associated with a value, associates it with the given
|
||||
* value.
|
||||
*
|
||||
* @return {@code true} if {@code key} did not exist and {@code value} was placed in the map,
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
public default boolean putIfAbsent(int key, byte value) {
|
||||
int keyIndex = indexOf(key);
|
||||
if (indexExists(keyIndex)) {
|
||||
return false;
|
||||
} else {
|
||||
indexInsert(keyIndex, key, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts all keys from another container to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(IntByteAssociativeContainer container);
|
||||
|
||||
/**
|
||||
* Puts all keys from an iterable cursor to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(Iterable<? extends IntByteCursor> iterable);
|
||||
|
||||
/**
|
||||
* If <code>key</code> exists, <code>putValue</code> is inserted into the map, otherwise any
|
||||
* existing value is incremented by <code>additionValue</code>.
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param putValue The value to put if <code>key</code> does not exist.
|
||||
* @param incrementValue The value to add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public byte putOrAdd(int key, byte putValue, byte incrementValue);
|
||||
|
||||
/**
|
||||
* An equivalent of calling
|
||||
*
|
||||
* <pre>
|
||||
* putOrAdd(key, additionValue, additionValue);
|
||||
* </pre>
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param additionValue The value to put or add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public byte addTo(int key, byte additionValue);
|
||||
|
||||
/**
|
||||
* Remove all values at the given key. The default value for the key type is returned if the value
|
||||
* does not exist in the map.
|
||||
*/
|
||||
public byte remove(int key);
|
||||
|
||||
/**
|
||||
* Compares the specified object with this set for equality. Returns {@code true} if and only if
|
||||
* the specified object is also a {@link IntByteMap} and both objects contains exactly the same
|
||||
* key-value pairs.
|
||||
*/
|
||||
public boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* @return A hash code of elements stored in the map. The hash code is defined as a sum of hash
|
||||
* codes of keys and values stored within the set). Because sum is commutative, this ensures
|
||||
* that different order of elements in a set does not affect the hash code.
|
||||
*/
|
||||
public int hashCode();
|
||||
|
||||
/**
|
||||
* Returns a logical "index" of a given key that can be used to speed up follow-up value setters
|
||||
* or getters in certain scenarios (conditional logic).
|
||||
*
|
||||
* <p>The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
|
||||
* contiguous.
|
||||
*
|
||||
* <p>The index is valid only between map modifications (it will not be affected by read-only
|
||||
* operations like iteration or value retrievals).
|
||||
*
|
||||
* @see #indexExists
|
||||
* @see #indexGet
|
||||
* @see #indexInsert
|
||||
* @see #indexReplace
|
||||
* @param key The key to locate in the map.
|
||||
* @return A non-negative value of the logical "index" of the key in the map or a negative value
|
||||
* if the key did not exist.
|
||||
*/
|
||||
public int indexOf(int key);
|
||||
|
||||
/**
|
||||
* @see #indexOf
|
||||
* @param index The index of a given key, as returned from {@link #indexOf}.
|
||||
* @return Returns <code>true</code> if the index corresponds to an existing key or false
|
||||
* otherwise. This is equivalent to checking whether the index is a positive value (existing
|
||||
* keys) or a negative value (non-existing keys).
|
||||
*/
|
||||
public boolean indexExists(int index);
|
||||
|
||||
/**
|
||||
* Returns the value associated with an existing key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the value currently associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public byte indexGet(int index);
|
||||
|
||||
/**
|
||||
* Replaces the value associated with an existing key and returns any previous value stored for
|
||||
* that key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public byte indexReplace(int index, byte newValue);
|
||||
|
||||
/**
|
||||
* Inserts a key-value pair for a key that is not present in the map. This method may help in
|
||||
* avoiding double recalculation of the key's hash.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
|
||||
* @throws AssertionError If assertions are enabled and the index corresponds to an existing key.
|
||||
*/
|
||||
public void indexInsert(int index, int key, byte value);
|
||||
|
||||
/**
|
||||
* Removes a key-value pair at an index previously acquired from {@link #indexOf}.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of the key to remove, as returned from {@link #indexOf}.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public byte indexRemove(int index);
|
||||
|
||||
/**
|
||||
* Clear all keys and values in the container.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Removes all elements from the collection and additionally releases any internal buffers.
|
||||
* Typically, if the object is to be reused, a simple {@link #clear()} should be a better
|
||||
* alternative since it'll avoid reallocation.
|
||||
*
|
||||
* @see #clear()
|
||||
*/
|
||||
public void release();
|
||||
|
||||
/**
|
||||
* Visually depict the distribution of keys.
|
||||
*
|
||||
* @param characters The number of characters to "squeeze" the entire buffer into.
|
||||
* @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
|
||||
* buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
|
||||
* between 1 and 9 is between.
|
||||
*/
|
||||
public String visualizeKeyDistribution(int characters);
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.*;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* An associative container from keys to (one or possibly more) values.
|
||||
*
|
||||
* @see IntContainer
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeVTypeAssociativeContainer.java")
|
||||
public interface IntCharAssociativeContainer extends Iterable<IntCharCursor> {
|
||||
/**
|
||||
* Returns a cursor over the entries (key-value pairs) in this map. The iterator is implemented as
|
||||
* a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()}. To read the current key and value use the cursor's public fields. An example
|
||||
* is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntShortCursor c : intShortMap) {
|
||||
* System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
|
||||
* }</pre>
|
||||
*
|
||||
* <p>The <code>index</code> field inside the cursor gives the internal index inside the
|
||||
* container's implementation. The interpretation of this index depends on to the container.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<IntCharCursor> iterator();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this container has an association to a value for the given key.
|
||||
*/
|
||||
public boolean containsKey(int key);
|
||||
|
||||
/**
|
||||
* @return Returns the current size (number of assigned keys) in the container.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/**
|
||||
* @return Return <code>true</code> if this hash map contains no assigned keys.
|
||||
*/
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) present in a given container. An alias to:
|
||||
*
|
||||
* <pre>
|
||||
* keys().removeAll(container)
|
||||
* </pre>
|
||||
*
|
||||
* but with no additional overhead.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(IntContainer container);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(IntPredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(IntCharPredicate predicate);
|
||||
|
||||
/**
|
||||
* Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link IntCharProcedure}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*/
|
||||
public <T extends IntCharProcedure> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a given predicate to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link IntCharPredicate}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*
|
||||
* <p>The iteration is continued as long as the predicate returns <code>true</code>.
|
||||
*/
|
||||
public <T extends IntCharPredicate> T forEach(T predicate);
|
||||
|
||||
/**
|
||||
* Returns a collection of keys of this container. The returned collection is a view over the key
|
||||
* set and any modifications (if allowed) introduced to the collection will propagate to the
|
||||
* associative container immediately.
|
||||
*/
|
||||
public IntCollection keys();
|
||||
|
||||
/**
|
||||
* Returns a container view of all values present in this container. The returned collection is a
|
||||
* view over the key set and any modifications (if allowed) introduced to the collection will
|
||||
* propagate to the associative container immediately.
|
||||
*/
|
||||
public CharContainer values();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,205 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.IntCharCursor;
|
||||
|
||||
/** An associative container with unique binding from keys to a single value. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeVTypeMap.java")
|
||||
public interface IntCharMap extends IntCharAssociativeContainer {
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the default value for the value
|
||||
* type, if the key is not associated with any value. For numeric value types, this default
|
||||
* value is 0, for object types it is {@code null}.
|
||||
*/
|
||||
public char get(int key);
|
||||
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the provided default value if the
|
||||
* key is not associated with any value.
|
||||
*/
|
||||
public char getOrDefault(int key, char defaultValue);
|
||||
|
||||
/**
|
||||
* Place a given key and value in the container.
|
||||
*
|
||||
* @return The value previously stored under the given key in the map is returned.
|
||||
*/
|
||||
public char put(int key, char value);
|
||||
|
||||
/**
|
||||
* If the specified key is not already associated with a value, associates it with the given
|
||||
* value.
|
||||
*
|
||||
* @return {@code true} if {@code key} did not exist and {@code value} was placed in the map,
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
public default boolean putIfAbsent(int key, char value) {
|
||||
int keyIndex = indexOf(key);
|
||||
if (indexExists(keyIndex)) {
|
||||
return false;
|
||||
} else {
|
||||
indexInsert(keyIndex, key, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts all keys from another container to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(IntCharAssociativeContainer container);
|
||||
|
||||
/**
|
||||
* Puts all keys from an iterable cursor to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(Iterable<? extends IntCharCursor> iterable);
|
||||
|
||||
/**
|
||||
* If <code>key</code> exists, <code>putValue</code> is inserted into the map, otherwise any
|
||||
* existing value is incremented by <code>additionValue</code>.
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param putValue The value to put if <code>key</code> does not exist.
|
||||
* @param incrementValue The value to add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public char putOrAdd(int key, char putValue, char incrementValue);
|
||||
|
||||
/**
|
||||
* An equivalent of calling
|
||||
*
|
||||
* <pre>
|
||||
* putOrAdd(key, additionValue, additionValue);
|
||||
* </pre>
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param additionValue The value to put or add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public char addTo(int key, char additionValue);
|
||||
|
||||
/**
|
||||
* Remove all values at the given key. The default value for the key type is returned if the value
|
||||
* does not exist in the map.
|
||||
*/
|
||||
public char remove(int key);
|
||||
|
||||
/**
|
||||
* Compares the specified object with this set for equality. Returns {@code true} if and only if
|
||||
* the specified object is also a {@link IntCharMap} and both objects contains exactly the same
|
||||
* key-value pairs.
|
||||
*/
|
||||
public boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* @return A hash code of elements stored in the map. The hash code is defined as a sum of hash
|
||||
* codes of keys and values stored within the set). Because sum is commutative, this ensures
|
||||
* that different order of elements in a set does not affect the hash code.
|
||||
*/
|
||||
public int hashCode();
|
||||
|
||||
/**
|
||||
* Returns a logical "index" of a given key that can be used to speed up follow-up value setters
|
||||
* or getters in certain scenarios (conditional logic).
|
||||
*
|
||||
* <p>The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
|
||||
* contiguous.
|
||||
*
|
||||
* <p>The index is valid only between map modifications (it will not be affected by read-only
|
||||
* operations like iteration or value retrievals).
|
||||
*
|
||||
* @see #indexExists
|
||||
* @see #indexGet
|
||||
* @see #indexInsert
|
||||
* @see #indexReplace
|
||||
* @param key The key to locate in the map.
|
||||
* @return A non-negative value of the logical "index" of the key in the map or a negative value
|
||||
* if the key did not exist.
|
||||
*/
|
||||
public int indexOf(int key);
|
||||
|
||||
/**
|
||||
* @see #indexOf
|
||||
* @param index The index of a given key, as returned from {@link #indexOf}.
|
||||
* @return Returns <code>true</code> if the index corresponds to an existing key or false
|
||||
* otherwise. This is equivalent to checking whether the index is a positive value (existing
|
||||
* keys) or a negative value (non-existing keys).
|
||||
*/
|
||||
public boolean indexExists(int index);
|
||||
|
||||
/**
|
||||
* Returns the value associated with an existing key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the value currently associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public char indexGet(int index);
|
||||
|
||||
/**
|
||||
* Replaces the value associated with an existing key and returns any previous value stored for
|
||||
* that key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public char indexReplace(int index, char newValue);
|
||||
|
||||
/**
|
||||
* Inserts a key-value pair for a key that is not present in the map. This method may help in
|
||||
* avoiding double recalculation of the key's hash.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
|
||||
* @throws AssertionError If assertions are enabled and the index corresponds to an existing key.
|
||||
*/
|
||||
public void indexInsert(int index, int key, char value);
|
||||
|
||||
/**
|
||||
* Removes a key-value pair at an index previously acquired from {@link #indexOf}.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of the key to remove, as returned from {@link #indexOf}.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public char indexRemove(int index);
|
||||
|
||||
/**
|
||||
* Clear all keys and values in the container.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Removes all elements from the collection and additionally releases any internal buffers.
|
||||
* Typically, if the object is to be reused, a simple {@link #clear()} should be a better
|
||||
* alternative since it'll avoid reallocation.
|
||||
*
|
||||
* @see #clear()
|
||||
*/
|
||||
public void release();
|
||||
|
||||
/**
|
||||
* Visually depict the distribution of keys.
|
||||
*
|
||||
* @param characters The number of characters to "squeeze" the entire buffer into.
|
||||
* @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
|
||||
* buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
|
||||
* between 1 and 9 is between.
|
||||
*/
|
||||
public String visualizeKeyDistribution(int characters);
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.predicates.IntPredicate;
|
||||
|
||||
/**
|
||||
* A collection allows basic, efficient operations on sets of elements (difference and
|
||||
* intersection).
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeCollection.java")
|
||||
public interface IntCollection extends IntContainer {
|
||||
/**
|
||||
* Removes all occurrences of <code>e</code> from this collection.
|
||||
*
|
||||
* @param e Element to be removed from this collection, if present.
|
||||
* @return The number of removed elements as a result of this call.
|
||||
*/
|
||||
public int removeAll(int e);
|
||||
|
||||
/**
|
||||
* Removes all elements in this collection that are present in <code>c</code>.
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int removeAll(IntLookupContainer c);
|
||||
|
||||
/**
|
||||
* Removes all elements in this collection for which the given predicate returns <code>true</code>
|
||||
* .
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int removeAll(IntPredicate predicate);
|
||||
|
||||
/**
|
||||
* Keeps all elements in this collection that are present in <code>c</code>. Runs in time
|
||||
* proportional to the number of elements in this collection. Equivalent of sets intersection.
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int retainAll(IntLookupContainer c);
|
||||
|
||||
/**
|
||||
* Keeps all elements in this collection for which the given predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int retainAll(IntPredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all elements from this collection.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Removes all elements from the collection and additionally releases any internal buffers.
|
||||
* Typically, if the object is to be reused, a simple {@link #clear()} should be a better
|
||||
* alternative since it'll avoid reallocation.
|
||||
*
|
||||
* @see #clear()
|
||||
*/
|
||||
public void release();
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.IntCursor;
|
||||
import com.carrotsearch.hppc.predicates.IntPredicate;
|
||||
import com.carrotsearch.hppc.procedures.IntProcedure;
|
||||
import java.util.Iterator;
|
||||
|
||||
/** A generic container holding <code>int</code>s. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeContainer.java")
|
||||
public interface IntContainer extends Iterable<IntCursor> {
|
||||
/**
|
||||
* Returns an iterator to a cursor traversing the collection. The order of traversal is not
|
||||
* defined. More than one cursor may be active at a time. The behavior of iterators is undefined
|
||||
* if structural changes are made to the underlying collection.
|
||||
*
|
||||
* <p>The iterator is implemented as a cursor and it returns <b>the same cursor instance</b> on
|
||||
* every call to {@link Iterator#next()} (to avoid boxing of primitive types). To read the current
|
||||
* list's value (or index in the list) use the cursor's public fields. An example is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntCursor<int> c : container) {
|
||||
* System.out.println("index=" + c.index + " value=" + c.value);
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public Iterator<IntCursor> iterator();
|
||||
|
||||
/**
|
||||
* Lookup a given element in the container. This operation has no speed guarantees (may be linear
|
||||
* with respect to the size of this container).
|
||||
*
|
||||
* @return Returns <code>true</code> if this container has an element equal to <code>e</code>.
|
||||
*/
|
||||
public boolean contains(int e);
|
||||
|
||||
/**
|
||||
* Return the current number of elements in this container. The time for calculating the
|
||||
* container's size may take <code>O(n)</code> time, although implementing classes should try to
|
||||
* maintain the current size and return in constant time.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/** Shortcut for <code>size() == 0</code>. */
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Copies all elements of this container to an array.
|
||||
*
|
||||
* <p>The returned array is always a copy, regardless of the storage used by the container.
|
||||
*/
|
||||
public int[] toArray();
|
||||
|
||||
/**
|
||||
* Applies a <code>procedure</code> to all container elements. Returns the argument (any subclass
|
||||
* of {@link IntProcedure}. This lets the caller to call methods of the argument by chaining the
|
||||
* call (even if the argument is an anonymous type) to retrieve computed values, for example
|
||||
* (IntContainer):
|
||||
*
|
||||
* <pre>
|
||||
* int count = container.forEach(new IntProcedure() {
|
||||
* int count; // this is a field declaration in an anonymous class.
|
||||
*
|
||||
* public void apply(int value) {
|
||||
* count++;
|
||||
* }
|
||||
* }).count;
|
||||
* </pre>
|
||||
*/
|
||||
public <T extends IntProcedure> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a <code>predicate</code> to container elements as long, as the predicate returns <code>
|
||||
* true</code>. The iteration is interrupted otherwise.
|
||||
*/
|
||||
public <T extends IntPredicate> T forEach(T predicate);
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.IntCursor;
|
||||
import com.carrotsearch.hppc.predicates.IntPredicate;
|
||||
import com.carrotsearch.hppc.procedures.IntProcedure;
|
||||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* A linear collection that supports element insertion and removal at both ends.
|
||||
*
|
||||
* @see Deque
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeDeque.java")
|
||||
public interface IntDeque extends IntCollection {
|
||||
/**
|
||||
* Removes the first element that equals <code>e</code>.
|
||||
*
|
||||
* @return The deleted element's index or <code>-1</code> if the element was not found.
|
||||
*/
|
||||
public int removeFirst(int e);
|
||||
|
||||
/**
|
||||
* Removes the last element that equals <code>e</code>.
|
||||
*
|
||||
* @return The deleted element's index or <code>-1</code> if the element was not found.
|
||||
*/
|
||||
public int removeLast(int e);
|
||||
|
||||
/** Inserts the specified element at the front of this deque. */
|
||||
public void addFirst(int e);
|
||||
|
||||
/** Inserts the specified element at the end of this deque. */
|
||||
public void addLast(int e);
|
||||
|
||||
/**
|
||||
* Retrieves and removes the first element of this deque.
|
||||
*
|
||||
* @return the head (first) element of this deque.
|
||||
*/
|
||||
public int removeFirst();
|
||||
|
||||
/**
|
||||
* Retrieves and removes the last element of this deque.
|
||||
*
|
||||
* @return the tail of this deque.
|
||||
*/
|
||||
public int removeLast();
|
||||
|
||||
/**
|
||||
* Retrieves the first element of this deque but does not remove it.
|
||||
*
|
||||
* @return the head of this deque.
|
||||
*/
|
||||
public int getFirst();
|
||||
|
||||
/**
|
||||
* Retrieves the last element of this deque but does not remove it.
|
||||
*
|
||||
* @return the head of this deque.
|
||||
*/
|
||||
public int getLast();
|
||||
|
||||
/**
|
||||
* @return An iterator over elements in this deque in tail-to-head order.
|
||||
*/
|
||||
public Iterator<IntCursor> descendingIterator();
|
||||
|
||||
/** Applies a <code>procedure</code> to all elements in tail-to-head order. */
|
||||
public <T extends IntProcedure> T descendingForEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a <code>predicate</code> to container elements as long, as the predicate returns <code>
|
||||
* true</code>. The iteration is interrupted otherwise.
|
||||
*/
|
||||
public <T extends IntPredicate> T descendingForEach(T predicate);
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.*;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* An associative container from keys to (one or possibly more) values.
|
||||
*
|
||||
* @see IntContainer
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeVTypeAssociativeContainer.java")
|
||||
public interface IntDoubleAssociativeContainer extends Iterable<IntDoubleCursor> {
|
||||
/**
|
||||
* Returns a cursor over the entries (key-value pairs) in this map. The iterator is implemented as
|
||||
* a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()}. To read the current key and value use the cursor's public fields. An example
|
||||
* is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntShortCursor c : intShortMap) {
|
||||
* System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
|
||||
* }</pre>
|
||||
*
|
||||
* <p>The <code>index</code> field inside the cursor gives the internal index inside the
|
||||
* container's implementation. The interpretation of this index depends on to the container.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<IntDoubleCursor> iterator();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this container has an association to a value for the given key.
|
||||
*/
|
||||
public boolean containsKey(int key);
|
||||
|
||||
/**
|
||||
* @return Returns the current size (number of assigned keys) in the container.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/**
|
||||
* @return Return <code>true</code> if this hash map contains no assigned keys.
|
||||
*/
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) present in a given container. An alias to:
|
||||
*
|
||||
* <pre>
|
||||
* keys().removeAll(container)
|
||||
* </pre>
|
||||
*
|
||||
* but with no additional overhead.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(IntContainer container);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(IntPredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(IntDoublePredicate predicate);
|
||||
|
||||
/**
|
||||
* Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link IntDoubleProcedure}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*/
|
||||
public <T extends IntDoubleProcedure> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a given predicate to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link IntDoublePredicate}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*
|
||||
* <p>The iteration is continued as long as the predicate returns <code>true</code>.
|
||||
*/
|
||||
public <T extends IntDoublePredicate> T forEach(T predicate);
|
||||
|
||||
/**
|
||||
* Returns a collection of keys of this container. The returned collection is a view over the key
|
||||
* set and any modifications (if allowed) introduced to the collection will propagate to the
|
||||
* associative container immediately.
|
||||
*/
|
||||
public IntCollection keys();
|
||||
|
||||
/**
|
||||
* Returns a container view of all values present in this container. The returned collection is a
|
||||
* view over the key set and any modifications (if allowed) introduced to the collection will
|
||||
* propagate to the associative container immediately.
|
||||
*/
|
||||
public DoubleContainer values();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,205 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.IntDoubleCursor;
|
||||
|
||||
/** An associative container with unique binding from keys to a single value. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeVTypeMap.java")
|
||||
public interface IntDoubleMap extends IntDoubleAssociativeContainer {
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the default value for the value
|
||||
* type, if the key is not associated with any value. For numeric value types, this default
|
||||
* value is 0, for object types it is {@code null}.
|
||||
*/
|
||||
public double get(int key);
|
||||
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the provided default value if the
|
||||
* key is not associated with any value.
|
||||
*/
|
||||
public double getOrDefault(int key, double defaultValue);
|
||||
|
||||
/**
|
||||
* Place a given key and value in the container.
|
||||
*
|
||||
* @return The value previously stored under the given key in the map is returned.
|
||||
*/
|
||||
public double put(int key, double value);
|
||||
|
||||
/**
|
||||
* If the specified key is not already associated with a value, associates it with the given
|
||||
* value.
|
||||
*
|
||||
* @return {@code true} if {@code key} did not exist and {@code value} was placed in the map,
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
public default boolean putIfAbsent(int key, double value) {
|
||||
int keyIndex = indexOf(key);
|
||||
if (indexExists(keyIndex)) {
|
||||
return false;
|
||||
} else {
|
||||
indexInsert(keyIndex, key, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts all keys from another container to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(IntDoubleAssociativeContainer container);
|
||||
|
||||
/**
|
||||
* Puts all keys from an iterable cursor to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(Iterable<? extends IntDoubleCursor> iterable);
|
||||
|
||||
/**
|
||||
* If <code>key</code> exists, <code>putValue</code> is inserted into the map, otherwise any
|
||||
* existing value is incremented by <code>additionValue</code>.
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param putValue The value to put if <code>key</code> does not exist.
|
||||
* @param incrementValue The value to add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public double putOrAdd(int key, double putValue, double incrementValue);
|
||||
|
||||
/**
|
||||
* An equivalent of calling
|
||||
*
|
||||
* <pre>
|
||||
* putOrAdd(key, additionValue, additionValue);
|
||||
* </pre>
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param additionValue The value to put or add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public double addTo(int key, double additionValue);
|
||||
|
||||
/**
|
||||
* Remove all values at the given key. The default value for the key type is returned if the value
|
||||
* does not exist in the map.
|
||||
*/
|
||||
public double remove(int key);
|
||||
|
||||
/**
|
||||
* Compares the specified object with this set for equality. Returns {@code true} if and only if
|
||||
* the specified object is also a {@link IntDoubleMap} and both objects contains exactly the same
|
||||
* key-value pairs.
|
||||
*/
|
||||
public boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* @return A hash code of elements stored in the map. The hash code is defined as a sum of hash
|
||||
* codes of keys and values stored within the set). Because sum is commutative, this ensures
|
||||
* that different order of elements in a set does not affect the hash code.
|
||||
*/
|
||||
public int hashCode();
|
||||
|
||||
/**
|
||||
* Returns a logical "index" of a given key that can be used to speed up follow-up value setters
|
||||
* or getters in certain scenarios (conditional logic).
|
||||
*
|
||||
* <p>The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
|
||||
* contiguous.
|
||||
*
|
||||
* <p>The index is valid only between map modifications (it will not be affected by read-only
|
||||
* operations like iteration or value retrievals).
|
||||
*
|
||||
* @see #indexExists
|
||||
* @see #indexGet
|
||||
* @see #indexInsert
|
||||
* @see #indexReplace
|
||||
* @param key The key to locate in the map.
|
||||
* @return A non-negative value of the logical "index" of the key in the map or a negative value
|
||||
* if the key did not exist.
|
||||
*/
|
||||
public int indexOf(int key);
|
||||
|
||||
/**
|
||||
* @see #indexOf
|
||||
* @param index The index of a given key, as returned from {@link #indexOf}.
|
||||
* @return Returns <code>true</code> if the index corresponds to an existing key or false
|
||||
* otherwise. This is equivalent to checking whether the index is a positive value (existing
|
||||
* keys) or a negative value (non-existing keys).
|
||||
*/
|
||||
public boolean indexExists(int index);
|
||||
|
||||
/**
|
||||
* Returns the value associated with an existing key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the value currently associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public double indexGet(int index);
|
||||
|
||||
/**
|
||||
* Replaces the value associated with an existing key and returns any previous value stored for
|
||||
* that key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public double indexReplace(int index, double newValue);
|
||||
|
||||
/**
|
||||
* Inserts a key-value pair for a key that is not present in the map. This method may help in
|
||||
* avoiding double recalculation of the key's hash.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
|
||||
* @throws AssertionError If assertions are enabled and the index corresponds to an existing key.
|
||||
*/
|
||||
public void indexInsert(int index, int key, double value);
|
||||
|
||||
/**
|
||||
* Removes a key-value pair at an index previously acquired from {@link #indexOf}.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of the key to remove, as returned from {@link #indexOf}.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public double indexRemove(int index);
|
||||
|
||||
/**
|
||||
* Clear all keys and values in the container.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Removes all elements from the collection and additionally releases any internal buffers.
|
||||
* Typically, if the object is to be reused, a simple {@link #clear()} should be a better
|
||||
* alternative since it'll avoid reallocation.
|
||||
*
|
||||
* @see #clear()
|
||||
*/
|
||||
public void release();
|
||||
|
||||
/**
|
||||
* Visually depict the distribution of keys.
|
||||
*
|
||||
* @param characters The number of characters to "squeeze" the entire buffer into.
|
||||
* @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
|
||||
* buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
|
||||
* between 1 and 9 is between.
|
||||
*/
|
||||
public String visualizeKeyDistribution(int characters);
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.*;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* An associative container from keys to (one or possibly more) values.
|
||||
*
|
||||
* @see IntContainer
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeVTypeAssociativeContainer.java")
|
||||
public interface IntFloatAssociativeContainer extends Iterable<IntFloatCursor> {
|
||||
/**
|
||||
* Returns a cursor over the entries (key-value pairs) in this map. The iterator is implemented as
|
||||
* a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()}. To read the current key and value use the cursor's public fields. An example
|
||||
* is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntShortCursor c : intShortMap) {
|
||||
* System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
|
||||
* }</pre>
|
||||
*
|
||||
* <p>The <code>index</code> field inside the cursor gives the internal index inside the
|
||||
* container's implementation. The interpretation of this index depends on to the container.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<IntFloatCursor> iterator();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this container has an association to a value for the given key.
|
||||
*/
|
||||
public boolean containsKey(int key);
|
||||
|
||||
/**
|
||||
* @return Returns the current size (number of assigned keys) in the container.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/**
|
||||
* @return Return <code>true</code> if this hash map contains no assigned keys.
|
||||
*/
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) present in a given container. An alias to:
|
||||
*
|
||||
* <pre>
|
||||
* keys().removeAll(container)
|
||||
* </pre>
|
||||
*
|
||||
* but with no additional overhead.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(IntContainer container);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(IntPredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(IntFloatPredicate predicate);
|
||||
|
||||
/**
|
||||
* Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link IntFloatProcedure}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*/
|
||||
public <T extends IntFloatProcedure> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a given predicate to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link IntFloatPredicate}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*
|
||||
* <p>The iteration is continued as long as the predicate returns <code>true</code>.
|
||||
*/
|
||||
public <T extends IntFloatPredicate> T forEach(T predicate);
|
||||
|
||||
/**
|
||||
* Returns a collection of keys of this container. The returned collection is a view over the key
|
||||
* set and any modifications (if allowed) introduced to the collection will propagate to the
|
||||
* associative container immediately.
|
||||
*/
|
||||
public IntCollection keys();
|
||||
|
||||
/**
|
||||
* Returns a container view of all values present in this container. The returned collection is a
|
||||
* view over the key set and any modifications (if allowed) introduced to the collection will
|
||||
* propagate to the associative container immediately.
|
||||
*/
|
||||
public FloatContainer values();
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user