
com.carrotsearch.hppcrt.lists.FloatArrayDeque Maven / Gradle / Ivy
package com.carrotsearch.hppcrt.lists;
import java.util.*;
import com.carrotsearch.hppcrt.*;
import com.carrotsearch.hppcrt.cursors.*;
import com.carrotsearch.hppcrt.hash.BitMixer;
import com.carrotsearch.hppcrt.lists.FloatLinkedList.ValueIterator;
import com.carrotsearch.hppcrt.predicates.*;
import com.carrotsearch.hppcrt.procedures.*;
import com.carrotsearch.hppcrt.sorting.*;
import com.carrotsearch.hppcrt.strategies.*;
/**
* An array-backed deque (double-ended queue) of floats. A single array is used to store and
* manipulate all elements. Reallocations are governed by a {@link ArraySizingStrategy}
* and may be expensive if they move around really large chunks of memory.
* This dequeue is also a FloatIndexedContainer, where index 0 is the head of the queue, and
* size() - 1 index is the last element.
* See {@link ObjectArrayDeque} class for API similarities and differences against Java
* Collections.
*/
@javax.annotation.Generated(
date = "2015-10-21T20:36:38+0200",
value = "KTypeArrayDeque.java")
public class FloatArrayDeque
extends AbstractFloatCollection implements FloatDeque, FloatIndexedContainer, Cloneable
{
/**
* Internal array for storing elements.
*
*
* Direct deque iteration from head to tail: iterate buffer[i % buffer.length] for i in [this.head; this.head + size()[
*
*/
public float []
buffer;
/**
* 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. (this is a valid index in buffer !)
*/
public int tail;
/**
* Buffer resizing strategy.
*/
protected final ArraySizingStrategy resizer;
/**
* internal pool of DescendingValueIterator (must be created in constructor)
*/
protected final IteratorPool descendingValueIteratorPool;
/**
* internal pool of ValueIterator (must be created in constructor)
*/
protected final IteratorPool valueIteratorPool;
/**
* Default constructor.
*/
public FloatArrayDeque() {
this(Containers.DEFAULT_EXPECTED_ELEMENTS);
}
/**
* Create with default sizing strategy and the given initial capacity.
*
* @see BoundedProportionalArraySizingStrategy
*/
public FloatArrayDeque(final int initialCapacity) {
this(initialCapacity, new BoundedProportionalArraySizingStrategy());
}
/**
* Create with a custom buffer resizing strategy.
*/
public FloatArrayDeque(final int initialCapacity, final ArraySizingStrategy resizer) {
assert resizer != null;
this.resizer = resizer;
//Allocate to capacity
ensureBufferSpace(Math.max(Containers.DEFAULT_EXPECTED_ELEMENTS, initialCapacity));
this.valueIteratorPool = new IteratorPool(new ObjectFactory() {
@Override
public ValueIterator create() {
return new ValueIterator();
}
@Override
public void initialize(final ValueIterator obj) {
obj.cursor.index = (((FloatArrayDeque.this.head) >= 1) ? (FloatArrayDeque.this.head) - 1 : (FloatArrayDeque.this.buffer.length) - 1);
obj.remaining = FloatArrayDeque.this.size();
}
@Override
public void reset(final ValueIterator obj) {
}
});
this.descendingValueIteratorPool = new IteratorPool(
new ObjectFactory() {
@Override
public DescendingValueIterator create() {
return new DescendingValueIterator();
}
@Override
public void initialize(final DescendingValueIterator obj) {
obj.cursor.index = FloatArrayDeque.this.tail;
obj.remaining = FloatArrayDeque.this.size();
}
@Override
public void reset(final DescendingValueIterator obj) {
}
});
}
/**
* Creates a new deque from elements of another container, appending them
* at the end of this deque.
*/
public FloatArrayDeque(final FloatContainer container) {
this(container.size());
addLast(container);
}
/**
* {@inheritDoc}
*/
@Override
public void addFirst(final float e1) {
int h = (((this.head) >= 1) ? (this.head) - 1 : (this.buffer.length) - 1);
if (h == this.tail) {
ensureBufferSpace(1);
h = (((this.head) >= 1) ? (this.head) - 1 : (this.buffer.length) - 1);
}
this.buffer[this.head = h] = e1;
}
/**
* Vararg-signature method for adding elements at the front of this deque.
*
* This method is handy, but costly if used in tight loops (anonymous
* array passing)
*/
public void addFirst(final float... elements) {
ensureBufferSpace(elements.length);
// For now, naive loop.
for (int i = 0; i < elements.length; i++) {
addFirst(elements[i]);
}
}
/**
* Inserts all elements from the given container to the front of this deque.
*
* @return Returns the number of elements actually added as a result of this
* call.
*/
public int addFirst(final FloatContainer container) {
return addFirst((Iterable extends FloatCursor>) container);
}
/**
* Inserts all elements from the given iterable to the front of this deque.
*
* @return Returns the number of elements actually added as a result of this call.
*/
public int addFirst(final Iterable extends FloatCursor> iterable) {
int size = 0;
for (final FloatCursor cursor : iterable) {
addFirst(cursor.value);
size++;
}
return size;
}
/**
* {@inheritDoc}
*/
@Override
public void addLast(final float e1) {
int t = (((this.tail) + 1 == (this.buffer.length)) ? 0 : (this.tail) + 1);
if (this.head == t) {
ensureBufferSpace(1);
t = (((this.tail) + 1 == (this.buffer.length)) ? 0 : (this.tail) + 1);
}
this.buffer[this.tail] = e1;
this.tail = t;
}
/**
* Vararg-signature method for adding elements at the end of this deque.
*
* This method is handy, but costly if used in tight loops (anonymous
* array passing)
*/
public void addLast(final float... elements) {
ensureBufferSpace(elements.length);
// For now, naive loop.
for (int i = 0; i < elements.length; i++) {
addLast(elements[i]);
}
}
/**
* Inserts all elements from the given container to the end of this deque.
*
* @return Returns the number of elements actually added as a result of this
* call.
*/
public int addLast(final FloatContainer container) {
return addLast((Iterable extends FloatCursor>) container);
}
/**
* Inserts all elements from the given iterable to the end of this deque.
*
* @return Returns the number of elements actually added as a result of this call.
*/
public int addLast(final Iterable extends FloatCursor> iterable) {
int size = 0;
for (final FloatCursor cursor : iterable) {
addLast(cursor.value);
size++;
}
return size;
}
/**
* {@inheritDoc}
*/
@Override
public float removeFirst() {
assert size() > 0 : "The deque is empty.";
final float result = ((this.buffer[this.head]));
this.head = (((this.head) + 1 == (this.buffer.length)) ? 0 : (this.head) + 1);
return result;
}
/**
* {@inheritDoc}
*/
@Override
public float removeLast() {
assert size() > 0 : "The deque is empty.";
this.tail = (((this.tail) >= 1) ? (this.tail) - 1 : (this.buffer.length) - 1);
final float result = ((this.buffer[this.tail]));
return result;
}
/**
* {@inheritDoc}
*/
@Override
public float getFirst() {
assert size() > 0 : "The deque is empty.";
return ((this.buffer[this.head]));
}
/**
* {@inheritDoc}
*/
@Override
public float getLast() {
assert size() > 0 : "The deque is empty.";
return ((this.buffer[(((this.tail) >= 1) ? (this.tail) - 1 : (this.buffer.length) - 1)]));
}
/**
* {@inheritDoc}
* The returned position is relative to the head,
* i.e w.r.t the {@link FloatIndexedContainer}, index 0 is the head of the queue, size() - 1 is the last element position.
*/
@Override
public int removeFirst(final float e1) {
int pos = -1;
final int index = bufferIndexOf(e1);
if (index >= 0) {
pos = bufferIndexToPosition(index);
removeBufferIndicesRange(index, (((index) + 1 == (this.buffer.length)) ? 0 : (index) + 1));
}
return pos;
}
/**
* Return the index of the first element equal to
* e1
. The index points to the {@link #buffer} array.
*
* @param e1 The element to look for.
* @return Returns the index in {@link #buffer} of the first element equal to e1
* or -1
if not found.
*/
public int bufferIndexOf(final float e1) {
final int last = this.tail;
final int bufLen = this.buffer.length;
final float[] buffer = ((this.buffer));
for (int i = this.head; i != last; i = (((i) + 1 == (bufLen)) ? 0 : (i) + 1)) {
if ((Float.floatToIntBits((e1)) == Float.floatToIntBits((buffer[i])))) {
return i;
}
}
return -1;
}
/**
* {@inheritDoc}
* The returned position is relative to the head,
* i.e w.r.t the {@link FloatIndexedContainer}, index 0 is the head of the queue, size() - 1 is the last element position.
*/
@Override
public int removeLast(final float e1) {
int pos = -1;
final int index = lastBufferIndexOf(e1);
if (index >= 0) {
pos = bufferIndexToPosition(index);
removeBufferIndicesRange(index, (((index) + 1 == (this.buffer.length)) ? 0 : (index) + 1));
}
return pos;
}
/**
* Return the index of the last element equal to
* e1
. The index points to the {@link #buffer} array.
*
* @param e1 The element to look for.
* @return Returns the index in {@link #buffer} of the first element equal to e1
* or -1
if not found.
*/
public int lastBufferIndexOf(final float e1) {
final int bufLen = this.buffer.length;
final int last = (((this.head) >= 1) ? (this.head) - 1 : (bufLen) - 1);
final float[] buffer = ((this.buffer));
for (int i = (((this.tail) >= 1) ? (this.tail) - 1 : (bufLen) - 1); i != last; i = (((i) >= 1) ? (i) - 1 : (bufLen) - 1)) {
if ((Float.floatToIntBits((e1)) == Float.floatToIntBits((buffer[i])))) {
return i;
}
}
return -1;
}
/**
* FloatIndexedContainer methods
*/
/**
* {@inheritDoc}
* The returned position is relative to the head,
* i.e w.r.t the {@link FloatIndexedContainer}, index 0 is the head of the queue, size() - 1 is the last element position.
*/
@Override
public int indexOf(final float e1) {
return bufferIndexToPosition(bufferIndexOf(e1));
}
/**
* {@inheritDoc}
* The returned position is relative to the head,
* i.e w.r.t the {@link FloatIndexedContainer}, index 0 is the head of the queue, size() - 1 is the last element position.
*/
@Override
public int lastIndexOf(final float e1) {
return bufferIndexToPosition(lastBufferIndexOf(e1));
}
/**
* {@inheritDoc}
*/
@Override
public int removeAll(final float e1) {
int removed = 0;
final int last = this.tail;
final int bufLen = this.buffer.length;
final float[] buffer = ((this.buffer));
int from, to;
for (from = to = this.head; from != last; from = (((from) + 1 == (bufLen)) ? 0 : (from) + 1)) {
if ((Float.floatToIntBits((e1)) == Float.floatToIntBits((buffer[from])))) {
removed++;
continue;
}
if (to != from) {
buffer[to] = buffer[from];
}
to = (((to) + 1 == (bufLen)) ? 0 : (to) + 1);
}
this.tail = to;
return removed;
}
/**
* {@inheritDoc}
*/
@Override
public int size() {
if (this.head <= this.tail) {
return this.tail - this.head;
}
return (this.tail - this.head + this.buffer.length);
}
/**
* {@inheritDoc}
*/
@Override
public int capacity() {
//because there is always an empty slot in the buffer
return this.buffer.length - 1;
}
/**
* {@inheritDoc}
* The internal array buffers are not released as a result of this call.
*/
@Override
public void clear() {
this.head = this.tail = 0;
}
/**
* Compact the internal buffer to prepare sorting
* Beware, this changes the relative order of elements, so is only useful to
* not-stable sorts while sorting the WHOLE buffer !
*/
private void compactBeforeSorting() {
if (this.head > this.tail) {
final int size = size();
//pack the separated chunk to the beginning of the buffer
System.arraycopy(this.buffer, this.head, this.buffer, this.tail, this.buffer.length - this.head);
//reset of the positions
this.head = 0;
this.tail = size;
//for GC sake, reset hole elements now at the end of buffer
}
}
/**
* Release internal buffers of this deque and reallocate the smallest buffer possible.
*/
public void release() {
this.head = this.tail = 0;
this.buffer = (new float[(Containers.DEFAULT_EXPECTED_ELEMENTS)]);
}
/**
* Ensures the internal buffer has enough free slots to store
* expectedAdditions
. Increases internal buffer size if needed.
*/
@SuppressWarnings("boxing")
protected void ensureBufferSpace(final int expectedAdditions) {
final int bufferLen = (this.buffer == null ? 0 : this.buffer.length);
final int elementsCount = (this.buffer == null ? 0 : size());
// +1 because there is always one empty slot in a deque.
if (elementsCount + 1 > bufferLen - expectedAdditions) {
int newSize = this.resizer.grow(bufferLen, elementsCount, expectedAdditions);
if (this.buffer == null) {
//first allocation, reserve an additional slot (tail is always a valid index in buffer)
newSize++;
}
try {
final float[] newBuffer = (new float[(newSize)]);
if (bufferLen > 0) {
toArray(newBuffer);
this.tail = elementsCount;
this.head = 0;
}
this.buffer = newBuffer;
} catch (final OutOfMemoryError e) {
throw new BufferAllocationException(
"Not enough memory to allocate buffers to grow from %d -> %d elements",
e,
bufferLen,
newSize);
}
}
}
/**
* Copies elements of this deque to an array. The content of the target
* array is filled from index 0 (head of the queue) to index size() - 1
* (tail of the queue).
*
* @param target The target array must be large enough to hold all elements.
* @return Returns the target argument for chaining.
*/
@Override
public float[] toArray(final float[] target) {
assert target.length >= size() : "Target array must be >= " + size();
if (this.head < this.tail) {
// The contents is not wrapped around. Just copy.
System.arraycopy(this.buffer, this.head, target, 0, size());
} else if (this.head > this.tail) {
// The contents is split. Merge elements from the following indexes:
// [head...buffer.length - 1][0, tail - 1]
final int rightCount = this.buffer.length - this.head;
System.arraycopy(this.buffer, this.head, target, 0, rightCount);
System.arraycopy(this.buffer, 0, target, rightCount, this.tail);
}
return target;
}
/**
* Clone this object. The returned clone will reuse the same array resizing strategy.
*/
@Override
public FloatArrayDeque clone() {
//placeholder container
final FloatArrayDeque cloned = new FloatArrayDeque(Containers.DEFAULT_EXPECTED_ELEMENTS, this.resizer);
//copy the full buffer
cloned.buffer = this.buffer.clone();
cloned.head = this.head;
cloned.tail = this.tail;
return cloned;
}
/**
* An iterator implementation for {@link ObjectArrayDeque#iterator}.
*/
public final class ValueIterator extends AbstractIterator
{
public final FloatCursor cursor;
private int remaining;
public ValueIterator() {
this.cursor = new FloatCursor();
this.cursor.index = (((FloatArrayDeque.this.head) >= 1) ? (FloatArrayDeque.this.head) - 1 : (FloatArrayDeque.this.buffer.length) - 1);
this.remaining = FloatArrayDeque.this.size();
}
@Override
protected FloatCursor fetch() {
if (this.remaining == 0) {
return done();
}
this.remaining--;
this.cursor.value = ((FloatArrayDeque.this.buffer[this.cursor.index = (((this.cursor.index) + 1 == (FloatArrayDeque.this.buffer.length)) ? 0 : (this.cursor.index) + 1)]));
return this.cursor;
}
}
/**
* An iterator implementation for {@link ObjectArrayDeque#descendingIterator()}.
*/
public final class DescendingValueIterator extends AbstractIterator
{
public final FloatCursor cursor;
private int remaining;
public DescendingValueIterator() {
this.cursor = new FloatCursor();
this.cursor.index = FloatArrayDeque.this.tail;
this.remaining = FloatArrayDeque.this.size();
}
@Override
protected FloatCursor fetch() {
if (this.remaining == 0) {
return done();
}
this.remaining--;
this.cursor.value = ((FloatArrayDeque.this.buffer[this.cursor.index = (((this.cursor.index) >= 1) ? (this.cursor.index) - 1 : (FloatArrayDeque.this.buffer.length) - 1)]));
return this.cursor;
}
}
/**
* Returns an iterator over the values of this deque (in head to tail order). The
* iterator is implemented as a cursor and it returns the same cursor instance
* on every call to {@link Iterator#next()} (to avoid boxing of primitive types). To
* read the current value, or index in the deque's {@link #buffer}, use the cursor's public
* fields. An example is shown below.
*
*
* for (IntValueCursor c : intDeque)
* {
* System.out.println("buffer index="
* + c.index + " value=" + c.value);
* }
*
*/
@Override
public ValueIterator iterator() {
//return new ValueIterator();
return this.valueIteratorPool.borrow();
}
/**
* Returns an iterator over the values of this deque (in tail to head order). The
* iterator is implemented as a cursor and it returns the same cursor instance
* on every call to {@link Iterator#next()} (to avoid boxing of primitive types). To
* read the current value, or index in the deque's {@link #buffer}, use the cursor's public
* fields. An example is shown below.
*
*
* for (Iterator i = intDeque.descendingIterator(); i.hasNext(); )
* {
* final IntCursor c = i.next();
* System.out.println("buffer index="
* + c.index + " value=" + c.value);
* }
*
*
*/
@Override
public DescendingValueIterator descendingIterator() {
//return new DescendingValueIterator();
return this.descendingValueIteratorPool.borrow();
}
/**
* {@inheritDoc}
*/
@Override
public T forEach(final T procedure) {
internalForEach(procedure, this.head, this.tail);
return procedure;
}
/**
* {@inheritDoc}
*/
@Override
public T forEach(final T procedure, final int fromIndex, final int toIndex) {
checkRangeBounds(fromIndex, toIndex);
if (fromIndex == toIndex) {
return procedure; //nothing to do
}
final int bufferPositionStart = indexToBufferPosition(fromIndex);
final int endBufferPosInclusive = indexToBufferPosition(toIndex - 1); //must be a valid index
internalForEach(procedure, bufferPositionStart, (((endBufferPosInclusive) + 1 == (this.buffer.length)) ? 0 : (endBufferPosInclusive) + 1));
return procedure;
}
/**
* Applies procedure
to a slice of the deque,
* fromIndexBuffer
, inclusive, to toIndexBuffer
,
* exclusive, indices are in {@link #buffer} array.
*/
private void internalForEach(final FloatProcedure procedure, final int fromIndexBuffer, final int toIndexBuffer) {
final float[] buffer = ((this.buffer));
for (int i = fromIndexBuffer; i != toIndexBuffer; i = (((i) + 1 == (buffer.length)) ? 0 : (i) + 1)) {
procedure.apply(buffer[i]);
}
}
/**
* {@inheritDoc}
*/
@Override
public T forEach(final T predicate) {
internalForEach(predicate, this.head, this.tail);
return predicate;
}
/**
* {@inheritDoc}
*/
@Override
public T forEach(final T predicate, final int fromIndex, final int toIndex) {
checkRangeBounds(fromIndex, toIndex);
if (fromIndex == toIndex) {
return predicate; //nothing to do
}
final int bufferPositionStart = indexToBufferPosition(fromIndex);
final int endBufferPosInclusive = indexToBufferPosition(toIndex - 1); //must be a valid index
internalForEach(predicate, bufferPositionStart, (((endBufferPosInclusive) + 1 == (this.buffer.length)) ? 0 : (endBufferPosInclusive) + 1));
return predicate;
}
/**
* Applies predicate
to a slice of the deque,
* fromIndexBuffer
, inclusive, to toIndexBuffer
,
* exclusive, indices are in {@link #buffer} array.
*/
private void internalForEach(final FloatPredicate predicate, final int fromIndexBuffer, final int toIndexBuffer) {
final float[] buffer = ((this.buffer));
for (int i = fromIndexBuffer; i != toIndexBuffer; i = (((i) + 1 == (buffer.length)) ? 0 : (i) + 1)) {
if (!predicate.apply(buffer[i])) {
break;
}
}
}
/**
* Applies procedure
to all elements of this deque, tail to head.
*/
@Override
public T descendingForEach(final T procedure) {
descendingForEach(procedure, this.head, this.tail);
return procedure;
}
/**
* Applies procedure
to a slice of the deque,
* toIndex
, exclusive, down to fromIndex
, inclusive.
*/
private void descendingForEach(final FloatProcedure procedure, final int fromIndex, final int toIndex) {
if (fromIndex == toIndex) {
return;
}
final float[] buffer = ((this.buffer));
int i = toIndex;
do {
i = (((i) >= 1) ? (i) - 1 : (buffer.length) - 1);
procedure.apply(buffer[i]);
} while (i != fromIndex);
}
/**
* {@inheritDoc}
*/
@Override
public T descendingForEach(final T predicate) {
descendingForEach(predicate, this.head, this.tail);
return predicate;
}
/**
* Applies predicate
to a slice of the deque,
* toIndex
, exclusive, down to fromIndex
, inclusive
* or until the predicate returns false
.
* Indices are in {@link #buffer} array.
*/
private void descendingForEach(final FloatPredicate predicate, final int fromIndex, final int toIndex) {
if (fromIndex == toIndex) {
return;
}
final float[] buffer = ((this.buffer));
int i = toIndex;
do {
i = (((i) >= 1) ? (i) - 1 : (buffer.length) - 1);
if (!predicate.apply(buffer[i])) {
break;
}
} while (i != fromIndex);
}
/**
* {@inheritDoc}
*/
@Override
public int removeAll(final FloatPredicate predicate) {
int removed = 0;
final int last = this.tail;
final int bufLen = this.buffer.length;
final float[] buffer = ((this.buffer));
int from, to;
from = to = this.head;
try {
for (from = to = this.head; from != last; from = (((from) + 1 == (bufLen)) ? 0 : (from) + 1)) {
if (predicate.apply(buffer[from])) {
removed++;
continue;
}
if (to != from) {
buffer[to] = buffer[from];
}
to = (((to) + 1 == (bufLen)) ? 0 : (to) + 1);
}
} finally {
// Keep the deque in consistent state even if the predicate throws an exception.
for (; from != last; from = (((from) + 1 == (bufLen)) ? 0 : (from) + 1)) {
if (to != from) {
buffer[to] = buffer[from];
}
to = (((to) + 1 == (bufLen)) ? 0 : (to) + 1);
}
this.tail = to;
}
return removed;
}
/**
* {@inheritDoc}
*/
@Override
public boolean contains(final float e) {
final int fromIndex = this.head;
final int toIndex = this.tail;
final float[] buffer = ((this.buffer));
for (int i = fromIndex; i != toIndex; i = (((i) + 1 == (buffer.length)) ? 0 : (i) + 1)) {
if ((Float.floatToIntBits((e)) == Float.floatToIntBits((buffer[i])))) {
return true;
}
}
return false;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
int h = 1;
final int fromIndex = this.head;
final int toIndex = this.tail;
final float[] buffer = ((this.buffer));
for (int i = fromIndex; i != toIndex; i = (((i) + 1 == (buffer.length)) ? 0 : (i) + 1)) {
h = 31 * h + BitMixer.mix(buffer[i]);
}
return h;
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(final Object obj) {
if (obj != null) {
if (obj == this) {
return true;
}
if (obj instanceof FloatLinkedList) { //Access by index is slow, iterate by iterator when the other is a linked list
final FloatLinkedList other = (FloatLinkedList) obj;
if (other.size() != this.size()) {
return false;
}
final ValueIterator it = this.iterator();
final FloatLinkedList.ValueIterator itOther = (FloatLinkedList.ValueIterator) other.iterator();
while (it.hasNext()) {
final float myVal = it.next().value;
final float otherVal = itOther.next().value;
if (!(Float.floatToIntBits((myVal)) == Float.floatToIntBits((otherVal)))) {
//recycle
it.release();
itOther.release();
return false;
}
} //end while
itOther.release();
return true;
}
else if (obj instanceof FloatIndexedContainer) {
//we can compare with any FloatIndexedContainer :
final FloatIndexedContainer other = (FloatIndexedContainer) obj;
return other.size() == this.size() && allIndexesEqual(this, (FloatIndexedContainer) other, this.size());
}
}
return false;
}
/**
* Compare index-aligned FloatIndexedContainer objects
*/
private boolean allIndexesEqual(final FloatIndexedContainer b1, final FloatIndexedContainer b2,
final int length) {
for (int i = 0; i < length; i++) {
final float o1 = b1.get(i);
final float o2 = b2.get(i);
if (!(Float.floatToIntBits((o1)) == Float.floatToIntBits((o2)))) {
return false;
}
}
return true;
}
/**
* Returns a new object of this class with no need to declare generic type (shortcut
* instead of using a constructor).
*/
public static/* */
FloatArrayDeque newInstance() {
return new FloatArrayDeque();
}
/**
* Returns a new object of this class with no need to declare generic type (shortcut
* instead of using a constructor).
*/
public static/* */
FloatArrayDeque newInstance(final int initialCapacity) {
return new FloatArrayDeque(initialCapacity);
}
/**
* Create a new deque by pushing a variable number of arguments to the end of it.
*/
public static/* */
FloatArrayDeque from(final float... elements) {
final FloatArrayDeque coll = new FloatArrayDeque(elements.length);
coll.addLast(elements);
return coll;
}
/**
* Create a new deque by pushing a variable number of arguments to the end of it.
*/
public static/* */
FloatArrayDeque from(final FloatContainer container) {
return new FloatArrayDeque(container);
}
////////////////////////////
/**
* In-place sort the dequeue from [beginIndex, endIndex[
* by natural ordering (smaller first)
* @param beginIndex the start index to be sorted
* @param endIndex the end index to be sorted (excluded)
*/
public void sort(final int beginIndex, final int endIndex) {
checkRangeBounds(beginIndex, endIndex);
if (beginIndex == endIndex) {
return; //nothing to do
}
//Fast path : if the actual indices matching [beginIndex; endIndex[
//in the underlying buffer are in increasing order (means there is no folding of buffer in the interval),
// use quicksort array version directly.
final int bufferPosStart = indexToBufferPosition(beginIndex);
final int bufferPosEndInclusive = indexToBufferPosition(endIndex - 1); //must be a valid index
if (bufferPosEndInclusive > bufferPosStart) {
FloatSort.quicksort(this.buffer, bufferPosStart, bufferPosEndInclusive + 1);
} else {
//Use the slower FloatIndexedContainer sort
FloatSort.quicksort(this, beginIndex, endIndex);
}
}
/**
* In-place sort the dequeue from [beginIndex, endIndex[
* using a FloatComparator
* @param beginIndex the start index to be sorted
* @param endIndex the end index to be sorted (excluded)
*/
public void sort(final int beginIndex, final int endIndex,
FloatComparator
comp) {
checkRangeBounds(beginIndex, endIndex);
if (beginIndex == endIndex) {
return; //nothing to do
}
//Fast path : if the actual indices matching [beginIndex; endIndex[
//in the underlying buffer are in increasing order (means there is no folding of buffer in the interval),
// use quicksort array version directly.
final int bufferPosStart = indexToBufferPosition(beginIndex);
final int bufferPosEndInclusive = indexToBufferPosition(endIndex - 1); //must be valid indices
if (bufferPosEndInclusive > bufferPosStart) {
FloatSort.quicksort(((this.buffer)), bufferPosStart, bufferPosEndInclusive + 1, comp);
} else {
//Use the slower FloatIndexedContainer sort
FloatSort.quicksort(this, beginIndex, endIndex, comp);
}
}
/**
* In-place sort the whole dequeue by natural ordering (smaller first)
*/
public void sort() {
if (size() > 1) {
compactBeforeSorting();
FloatSort.quicksort(this.buffer, this.head, this.tail);
}
}
////////////////////////////
/**
* In-place sort the whole dequeue
* using a FloatComparator
*/
public void sort(
FloatComparator
comp) {
if (size() > 1) {
compactBeforeSorting();
FloatSort.quicksort(((this.buffer)), this.head, this.tail, comp);
}
}
/**
* FloatIndexedContainer methods
*/
/**
* {@inheritDoc}
*/
@Override
public void add(final float e1) {
addLast(e1);
}
/**
* This operation is not supported on array deques, throwing UnsupportedOperationException.
* @throws UnsupportedOperationException
*/
@Override
public void insert(final int index, final float e1) {
throw new UnsupportedOperationException(
"insert(final int index, final KType e1) operation is not supported on KTypeArrayDeque");
}
/**
* {@inheritDoc}
* The position is relative to the head,
* i.e w.r.t the {@link FloatIndexedContainer}, index 0 is the head of the queue, size() - 1 is the last element position.
*/
@Override
public float set(final int index, final float e1) {
final int indexInBuffer = indexToBufferPosition(index);
final float previous = ((this.buffer[indexInBuffer]));
this.buffer[indexInBuffer] = e1;
return previous;
}
/**
* {@inheritDoc}
* The position is relative to the head,
* i.e w.r.t the {@link FloatIndexedContainer}, index 0 is the head of the queue, size() - 1 is the last element position.
*/
@Override
public float get(final int index) {
return ((this.buffer[indexToBufferPosition(index)]));
}
/**
* {@inheritDoc}
* The position is relative to the head,
* i.e w.r.t the {@link FloatIndexedContainer}, index 0 is the head of the queue, size() - 1 is the last element position.
*/
@Override
public float remove(final int index) {
final int indexInBuffer = indexToBufferPosition(index);
final float previous = ((this.buffer[indexInBuffer]));
removeBufferIndicesRange(indexInBuffer, (((indexInBuffer) + 1 == (this.buffer.length)) ? 0 : (indexInBuffer) + 1));
return previous;
}
/**
* Remove all elements in [fromBufferIndex; toBufferIndex[ indices in {@link #buffer}.
* @param fromBufferIndex
* @param toBufferIndex
*/
private void removeBufferIndicesRange(final int fromBufferIndex, final int toBufferIndex) {
final int bufLen = this.buffer.length;
final float[] buffer = ((this.buffer));
if (fromBufferIndex == toBufferIndex) {
//nothing to do
return;
}
long nbToBeRemoved = (long) toBufferIndex - fromBufferIndex;
//fold the value
if (nbToBeRemoved < 0) {
nbToBeRemoved += bufLen;
}
final int last = this.tail;
long removed = 0;
int from, to;
for (from = to = fromBufferIndex; from != last; from = (((from) + 1 == (bufLen)) ? 0 : (from) + 1)) {
if (removed < nbToBeRemoved) {
removed++;
continue;
}
buffer[to] = buffer[from];
to = (((to) + 1 == (bufLen)) ? 0 : (to) + 1);
} //end for
this.tail = to;
}
/**
* {@inheritDoc}
* The position is relative to the head,
* i.e w.r.t the {@link FloatIndexedContainer}, index 0 is the head of the queue, size() - 1 is the last element position.
*/
@Override
public void removeRange(final int fromIndex, final int toIndex) {
checkRangeBounds(fromIndex, toIndex);
if (fromIndex == toIndex) {
return; //nothing to do
}
final int bufferPositionStart = indexToBufferPosition(fromIndex);
final int bufferPositionEndInclusive = indexToBufferPosition(toIndex - 1); //must be a valid index
removeBufferIndicesRange(bufferPositionStart, (((bufferPositionEndInclusive) + 1 == (this.buffer.length)) ? 0 : (bufferPositionEndInclusive) + 1));
}
/**
* Convert the internal {@link #buffer} index to equivalent {@link #FloatIndexedContainer}
* position.
* @param bufferIndex
* @return
*/
private int bufferIndexToPosition(final int bufferIndex) {
int pos = -1;
if (bufferIndex >= 0) {
pos = bufferIndex - this.head;
if (pos < 0) {
//fold it
pos += this.buffer.length;
}
}
return pos;
}
/**
* Convert the {@link #FloatIndexedContainer}
* index to the internal position in buffer{@link #buffer}.
* @param index a valid index towards {@link #FloatIndexedContainer}.
* @return
*/
private int indexToBufferPosition(final int index) {
//since the buffer is circular, we could have out-of-bounds access without JRE throwing an ArrayOutOfBoundsException,
//so it is safer to do it this way.
if (index < 0 || index >= size()) {
throw new IndexOutOfBoundsException("Index " + index + " out of bounds [" + 0 + ", size=" + size() + "[.");
}
//Convert to long to prevent overflow
long bufferPos = (long) index + this.head;
if (bufferPos >= this.buffer.length) {
//fold it
bufferPos -= this.buffer.length;
}
return (int) bufferPos;
}
private void checkRangeBounds(final int beginIndex, final int endIndex) {
if (beginIndex > endIndex) {
throw new IllegalArgumentException("Index beginIndex " + beginIndex + " is > endIndex " + endIndex);
}
if (beginIndex < 0) {
throw new IndexOutOfBoundsException("Index beginIndex < 0");
}
if (endIndex > size()) {
throw new IndexOutOfBoundsException("Index endIndex " + endIndex + " out of bounds [" + 0 + ", " + size() + "].");
}
}
}