package at.yawk.numaec;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.ConcurrentModificationException;
import org.eclipse.collections.api.LazyIntIterable;
import org.eclipse.collections.api.IntIterable;
import org.eclipse.collections.api.block.function.primitive.ObjectIntIntToObjectFunction;
import org.eclipse.collections.api.block.function.primitive.ObjectIntToObjectFunction;
import org.eclipse.collections.api.block.function.primitive.IntToObjectFunction;
import org.eclipse.collections.api.block.predicate.primitive.IntPredicate;
import org.eclipse.collections.api.block.procedure.primitive.IntIntProcedure;
import org.eclipse.collections.api.block.procedure.primitive.IntProcedure;
import org.eclipse.collections.api.iterator.MutableIntIterator;
import org.eclipse.collections.api.iterator.IntIterator;
import org.eclipse.collections.api.list.ListIterable;
import org.eclipse.collections.api.list.MutableList;
import org.eclipse.collections.api.list.primitive.ImmutableIntList;
import org.eclipse.collections.api.list.primitive.MutableIntList;
import org.eclipse.collections.api.list.primitive.IntList;
import org.eclipse.collections.impl.lazy.primitive.ReverseIntIterable;
import org.eclipse.collections.impl.list.mutable.primitive.SynchronizedIntList;
import org.eclipse.collections.impl.list.mutable.primitive.UnmodifiableIntList;
import org.eclipse.collections.impl.primitive.AbstractIntIterable;
import java.util.Spliterator;
class IntBufferListImpl extends AbstractIntIterable implements IntBufferList {
private static final int INITIAL_CAPACITY = 16;
final LargeByteBufferAllocator allocator;
LargeByteBuffer buffer;
int size;
IntBufferListImpl(LargeByteBufferAllocator allocator) {
this.allocator = allocator;
buffer = LargeByteBuffer.EMPTY;
}
IntBufferListImpl(LargeByteBufferAllocator allocator, int initialCapacity) {
this.allocator = allocator;
buffer = allocator.allocate(scale(initialCapacity));
}
@Override
public void close() {
buffer.close();
buffer = null;
}
protected long scale(int index) {
return ((long) index) * Integer.BYTES;
}
@Override
public IntIterator intIterator() {
return new Itr();
}
@Override
public int[] toArray() {
int[] array = new int[size];
for (int i = 0; i < size; i++) {
array[i] = get(i);
}
return array;
}
@Override
public boolean contains(int value) {
for (int i = 0; i < size; i++) {
if (get(i) == value) {
return true;
}
}
return false;
}
@Override
public void forEach(IntProcedure procedure) {
for (int i = 0; i < size; i++) {
procedure.value(get(i));
}
}
@Override
public void each(IntProcedure procedure) {
forEach(procedure);
}
@Override
public int get(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException();
} else {
return buffer.getInt(scale(index));
}
}
@Override
public long
dotProduct(IntList list) {
long
sum = 0;
int i = 0;
IntIterator itr = list.intIterator();
while (i < size && itr.hasNext()) {
sum += get(i++) * itr.next();
}
if (itr.hasNext() || i < size) {
throw new IllegalArgumentException("Size mismatch");
}
return sum;
}
@Override
public int binarySearch(int value) {
int low = 0;
int high = size - 1;
while (low <= high) {
int mid = (low + high) / 2;
int pivot = get(mid);
if (pivot < value) {
low = mid + 1;
} else if (pivot > value) {
high = mid - 1;
} else {
return mid;
}
}
return ~low;
}
@Override
public int indexOf(int value) {
for (int i = 0; i < size; i++) {
if (get(i) == value) {
return i;
}
}
return -1;
}
@Override
public int lastIndexOf(int value) {
for (int i = size - 1; i >= 0; i--) {
if (get(i) == value) {
return i;
}
}
return -1;
}
@Override
public int getLast() {
return get(size - 1);
}
@Override
public LazyIntIterable asReversed() {
return ReverseIntIterable.adapt(this);
}
@Override
public int getFirst() {
return get(0);
}
@Override
public IntList select(IntPredicate predicate) {
throw new UnsupportedOperationException();
}
@Override
public IntList reject(IntPredicate predicate) {
throw new UnsupportedOperationException();
}
@Override
public <V> ListIterable<V> collect(IntToObjectFunction<? extends V> function) {
throw new UnsupportedOperationException();
}
@Override
public int detectIfNone(IntPredicate predicate, int ifNone) {
for (int i = 0; i < size; i++) {
int element = get(i);
if (predicate.accept(element)) {
return element;
}
}
return ifNone;
}
@Override
public int count(IntPredicate predicate) {
int count = 0;
for (int i = 0; i < size; i++) {
if (predicate.accept(get(i))) {
count++;
}
}
return count;
}
@Override
public boolean anySatisfy(IntPredicate predicate) {
for (int i = 0; i < size; i++) {
int element = get(i);
if (predicate.accept(element)) {
return true;
}
}
return false;
}
@Override
public boolean allSatisfy(IntPredicate predicate) {
for (int i = 0; i < size; i++) {
int element = get(i);
if (!predicate.accept(element)) {
return false;
}
}
return true;
}
@Override
public boolean noneSatisfy(IntPredicate predicate) {
return !anySatisfy(predicate);
}
@Override
public <T> T injectInto(T injectedValue, ObjectIntToObjectFunction<? super T, ? extends T> function) {
for (int i = 0; i < size; i++) {
injectedValue = function.valueOf(injectedValue, get(i));
}
return injectedValue;
}
@Override
public <T> T injectIntoWithIndex(T injectedValue, ObjectIntIntToObjectFunction<? super T, ? extends T> function) {
for (int i = 0; i < size; i++) {
injectedValue = function.valueOf(injectedValue, get(i), i);
}
return injectedValue;
}
@Override
public long
sum() {
long
sum = 0;
for (int i = 0; i < size; i++) {
sum += get(i);
}
return sum;
}
@Override
public int max() {
int max = get(0);
for (int i = 1; i < size; i++) {
int item = get(i);
if (item > max) {
return item;
}
}
return max;
}
@Override
public int min() {
int min = get(0);
for (int i = 1; i < size; i++) {
int item = get(i);
if (item < min) {
return item;
}
}
return min;
}
@Override
public ImmutableIntList toImmutable() {
throw new UnsupportedOperationException();
}
@Override
public IntList distinct() {
throw new UnsupportedOperationException();
}
@Override
public void forEachWithIndex(IntIntProcedure procedure) {
for (int i = 0; i < size; i++) {
procedure.value(get(i), i);
}
}
@Override
public IntList toReversed() {
throw new UnsupportedOperationException();
}
@Override
public IntList subList(int fromIndex, int toIndex) {
throw new UnsupportedOperationException();
}
@Override
public int size() {
return size;
}
@Override
public Spliterator.OfInt spliterator() {
throw new UnsupportedOperationException();
}
@Override
public void appendString(Appendable appendable, String start, String separator, String end) {
try {
appendable.append(start);
for (int i = 0; i < size; i++) {
if (i != 0) {
appendable.append(separator);
}
appendable.append(String.valueOf(get(i)));
}
appendable.append(end);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
@Override
public boolean equals(Object o) {
if (o instanceof IntList) {
IntList other = (IntList) o;
int expectedSize = other.size();
if (expectedSize == this.size()) {
IntIterator j = other.intIterator();
int i = 0;
while (i < expectedSize) {
if (!j.hasNext()) { throw new ConcurrentModificationException(); }
if (j.next() != get(i)) { return false; }
i++;
}
if (j.hasNext()) { throw new ConcurrentModificationException(); }
return true;
} else {
return false;
}
} else {
return false;
}
}
@Override
public int hashCode() {
int hashCode = 1;
for (int i = 0; i < size(); i++) {
hashCode *= 31;
hashCode += get(i);
}
return hashCode;
}
class Itr implements IntIterator {
int i;
@Override
public int next() {
return get(i++);
}
@Override
public boolean hasNext() {
return i < size;
}
}
public static class Mutable extends IntBufferListImpl implements MutableIntBufferList {
Mutable(LargeByteBufferAllocator allocator) {
super(allocator);
}
Mutable(LargeByteBufferAllocator allocator, int initialCapacity) {
super(allocator, initialCapacity);
}
private void ensureCapacity(int capacity) {
long requiredCapacity = scale(capacity);
long currentCapacity = buffer.size();
if (requiredCapacity > currentCapacity) {
long newCapacity = currentCapacity == 0 ? scale(INITIAL_CAPACITY) : currentCapacity;
while (requiredCapacity > newCapacity) {
newCapacity += newCapacity >> 1;
}
LargeByteBuffer reallocated = buffer.reallocate(newCapacity);
if (reallocated != null) {
this.buffer = reallocated;
} else {
@SuppressWarnings("resource")
LargeByteBuffer swap = allocator.allocate(newCapacity);
try {
swap.copyFrom(buffer, 0, 0, scale(size));
LargeByteBuffer tmp = swap;
swap = this.buffer;
this.buffer = tmp;
} finally {
swap.close();
}
}
}
}
@Override
public void addAtIndex(int index, int element) {
if (index == size) {
add(element);
} else if (index < 0 || index > size) {
throw new IndexOutOfBoundsException();
} else {
ensureCapacity(size + 1);
buffer.copyFrom(buffer, scale(index), scale(index + 1), scale(size - index));
buffer.setInt(scale(index), element);
size++;
}
}
@Override
public boolean addAllAtIndex(int index, int... source) {
if (index == size) {
return addAll(source);
} else if (index < 0 || index > size) {
throw new IndexOutOfBoundsException();
} else if (source.length == 0) {
return false;
} else {
ensureCapacity(size + source.length);
buffer.copyFrom(buffer, scale(index), scale(index + source.length), scale(size - index));
for (int i = 0; i < source.length; i++) {
buffer.setInt(scale(index + i), source[i]);
}
size += source.length;
return true;
}
}
@Override
public boolean addAllAtIndex(int index, IntIterable source) {
if (index == size) {
return addAll(source);
} else if (index < 0 || index > size) {
throw new IndexOutOfBoundsException();
} else if (source.isEmpty()) {
return false;
} else {
int expectedSize = source.size();
ensureCapacity(size + expectedSize);
buffer.copyFrom(buffer, scale(index), scale(index + expectedSize), scale(size - index));
IntIterator itr = source.intIterator();
for (int i = 0; i < expectedSize; i++) {
if (!itr.hasNext()) { throw new ConcurrentModificationException(); }
buffer.setInt(scale(index + i), itr.next());
}
if (itr.hasNext()) { throw new ConcurrentModificationException(); }
size += expectedSize;
return true;
}
}
@Override
public int removeAtIndex(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException();
} else {
int value = buffer.getInt(scale(index));
if (size > 1) {
buffer.copyFrom(buffer, scale(index + 1), scale(index), scale(size - index - 1));
}
size--;
return value;
}
}
@Override
public int set(int index, int element) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException();
} else {
int old = buffer.getInt(scale(index));
buffer.setInt(scale(index), element);
return old;
}
}
@Override
public boolean add(int element) {
ensureCapacity(size + 1);
buffer.setInt(scale(size), element);
size++;
return true;
}
@Override
public boolean addAll(int... source) {
ensureCapacity(size + source.length);
for (int i = 0; i < source.length; i++) {
buffer.setInt(scale(i + size), source[i]);
}
size += source.length;
return source.length > 0;
}
@Override
public boolean addAll(IntIterable source) {
int expectedSize = source.size();
ensureCapacity(size + expectedSize);
IntIterator itr = source.intIterator();
int i = 0;
while (itr.hasNext()) {
if (i > expectedSize) {
throw new ConcurrentModificationException();
}
buffer.setInt(scale(i + size), itr.next());
i++;
}
size += i;
return i > 0;
}
@Override
public boolean remove(int value) {
int ix = indexOf(value);
if (ix == -1) {
return false;
} else {
removeAtIndex(ix);
return true;
}
}
@Override
public boolean removeAll(IntIterable source) {
throw new UnsupportedOperationException();
}
@Override
public boolean removeAll(int... source) {
throw new UnsupportedOperationException();
}
@Override
public boolean retainAll(IntIterable elements) {
throw new UnsupportedOperationException();
}
@Override
public boolean retainAll(int... source) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
size = 0;
}
@Override
public MutableIntList with(int element) {
add(element);
return this;
}
@Override
public MutableIntList without(int element) {
remove(element);
return this;
}
@Override
public MutableIntList withAll(IntIterable elements) {
addAll(elements);
return this;
}
@Override
public MutableIntList withoutAll(IntIterable elements) {
removeAll(elements);
return this;
}
@Override
public MutableIntList reverseThis() {
throw new UnsupportedOperationException();
}
@Override
public MutableIntList sortThis() {
throw new UnsupportedOperationException();
}
@Override
public MutableIntList asUnmodifiable() {
return new UnmodifiableIntList(this);
}
@Override
public MutableIntList asSynchronized() {
return new SynchronizedIntList(this);
}
@Override
public MutableIntIterator intIterator() {
return new Itr();
}
@Override
public MutableIntList select(IntPredicate predicate) {
throw new UnsupportedOperationException();
}
@Override
public MutableIntList reject(IntPredicate predicate) {
throw new UnsupportedOperationException();
}
@Override
public <V> MutableList<V> collect(IntToObjectFunction<? extends V> function) {
throw new UnsupportedOperationException();
}
@Override
public MutableIntList toReversed() {
throw new UnsupportedOperationException();
}
@Override
public MutableIntList distinct() {
throw new UnsupportedOperationException();
}
@Override
public MutableIntList subList(int fromIndex, int toIndex) {
throw new UnsupportedOperationException();
}
class Itr extends IntBufferListImpl.Itr implements MutableIntIterator {
int removalIndex = -1;
@Override
public int next() {
removalIndex = i;
return super.next();
}
@Override
public void remove() {
if (removalIndex == -1) { throw new IllegalStateException(); }
removeAtIndex(removalIndex);
i--;
removalIndex = -1;
}
}
}
}