package at.yawk.numaec;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.ConcurrentModificationException;
import org.eclipse.collections.api.LazyLongIterable;
import org.eclipse.collections.api.LongIterable;
import org.eclipse.collections.api.block.function.primitive.ObjectLongIntToObjectFunction;
import org.eclipse.collections.api.block.function.primitive.ObjectLongToObjectFunction;
import org.eclipse.collections.api.block.function.primitive.LongToObjectFunction;
import org.eclipse.collections.api.block.predicate.primitive.LongPredicate;
import org.eclipse.collections.api.block.procedure.primitive.LongIntProcedure;
import org.eclipse.collections.api.block.procedure.primitive.LongProcedure;
import org.eclipse.collections.api.iterator.MutableLongIterator;
import org.eclipse.collections.api.iterator.LongIterator;
import org.eclipse.collections.api.list.ListIterable;
import org.eclipse.collections.api.list.MutableList;
import org.eclipse.collections.api.list.primitive.ImmutableLongList;
import org.eclipse.collections.api.list.primitive.MutableLongList;
import org.eclipse.collections.api.list.primitive.LongList;
import org.eclipse.collections.impl.lazy.primitive.ReverseLongIterable;
import org.eclipse.collections.impl.list.mutable.primitive.SynchronizedLongList;
import org.eclipse.collections.impl.list.mutable.primitive.UnmodifiableLongList;
import org.eclipse.collections.impl.primitive.AbstractLongIterable;
import java.util.Spliterator;
class LongBufferListImpl extends AbstractLongIterable implements LongBufferList {
private static final int INITIAL_CAPACITY = 16;
final LargeByteBufferAllocator allocator;
LargeByteBuffer buffer;
int size;
LongBufferListImpl(LargeByteBufferAllocator allocator) {
this.allocator = allocator;
buffer = LargeByteBuffer.EMPTY;
}
LongBufferListImpl(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) * Long.BYTES;
}
@Override
public LongIterator longIterator() {
return new Itr();
}
@Override
public long[] toArray() {
long[] array = new long[size];
for (int i = 0; i < size; i++) {
array[i] = get(i);
}
return array;
}
@Override
public boolean contains(long value) {
for (int i = 0; i < size; i++) {
if (get(i) == value) {
return true;
}
}
return false;
}
@Override
public void forEach(LongProcedure procedure) {
for (int i = 0; i < size; i++) {
procedure.value(get(i));
}
}
@Override
public void each(LongProcedure procedure) {
forEach(procedure);
}
@Override
public long get(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException();
} else {
return buffer.getLong(scale(index));
}
}
@Override
public long
dotProduct(LongList list) {
long
sum = 0;
int i = 0;
LongIterator itr = list.longIterator();
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(long value) {
int low = 0;
int high = size - 1;
while (low <= high) {
int mid = (low + high) / 2;
long 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(long value) {
for (int i = 0; i < size; i++) {
if (get(i) == value) {
return i;
}
}
return -1;
}
@Override
public int lastIndexOf(long value) {
for (int i = size - 1; i >= 0; i--) {
if (get(i) == value) {
return i;
}
}
return -1;
}
@Override
public long getLast() {
return get(size - 1);
}
@Override
public LazyLongIterable asReversed() {
return ReverseLongIterable.adapt(this);
}
@Override
public long getFirst() {
return get(0);
}
@Override
public LongList select(LongPredicate predicate) {
throw new UnsupportedOperationException();
}
@Override
public LongList reject(LongPredicate predicate) {
throw new UnsupportedOperationException();
}
@Override
public <V> ListIterable<V> collect(LongToObjectFunction<? extends V> function) {
throw new UnsupportedOperationException();
}
@Override
public long detectIfNone(LongPredicate predicate, long ifNone) {
for (int i = 0; i < size; i++) {
long element = get(i);
if (predicate.accept(element)) {
return element;
}
}
return ifNone;
}
@Override
public int count(LongPredicate predicate) {
int count = 0;
for (int i = 0; i < size; i++) {
if (predicate.accept(get(i))) {
count++;
}
}
return count;
}
@Override
public boolean anySatisfy(LongPredicate predicate) {
for (int i = 0; i < size; i++) {
long element = get(i);
if (predicate.accept(element)) {
return true;
}
}
return false;
}
@Override
public boolean allSatisfy(LongPredicate predicate) {
for (int i = 0; i < size; i++) {
long element = get(i);
if (!predicate.accept(element)) {
return false;
}
}
return true;
}
@Override
public boolean noneSatisfy(LongPredicate predicate) {
return !anySatisfy(predicate);
}
@Override
public <T> T injectInto(T injectedValue, ObjectLongToObjectFunction<? 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, ObjectLongIntToObjectFunction<? 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 long max() {
long max = get(0);
for (int i = 1; i < size; i++) {
long item = get(i);
if (item > max) {
return item;
}
}
return max;
}
@Override
public long min() {
long min = get(0);
for (int i = 1; i < size; i++) {
long item = get(i);
if (item < min) {
return item;
}
}
return min;
}
@Override
public ImmutableLongList toImmutable() {
throw new UnsupportedOperationException();
}
@Override
public LongList distinct() {
throw new UnsupportedOperationException();
}
@Override
public void forEachWithIndex(LongIntProcedure procedure) {
for (int i = 0; i < size; i++) {
procedure.value(get(i), i);
}
}
@Override
public LongList toReversed() {
throw new UnsupportedOperationException();
}
@Override
public LongList subList(int fromIndex, int toIndex) {
throw new UnsupportedOperationException();
}
@Override
public int size() {
return size;
}
@Override
public Spliterator.OfLong 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 LongList) {
LongList other = (LongList) o;
int expectedSize = other.size();
if (expectedSize == this.size()) {
LongIterator j = other.longIterator();
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 LongIterator {
int i;
@Override
public long next() {
return get(i++);
}
@Override
public boolean hasNext() {
return i < size;
}
}
public static class Mutable extends LongBufferListImpl implements MutableLongBufferList {
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, long 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.setLong(scale(index), element);
size++;
}
}
@Override
public boolean addAllAtIndex(int index, long... 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.setLong(scale(index + i), source[i]);
}
size += source.length;
return true;
}
}
@Override
public boolean addAllAtIndex(int index, LongIterable 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));
LongIterator itr = source.longIterator();
for (int i = 0; i < expectedSize; i++) {
if (!itr.hasNext()) { throw new ConcurrentModificationException(); }
buffer.setLong(scale(index + i), itr.next());
}
if (itr.hasNext()) { throw new ConcurrentModificationException(); }
size += expectedSize;
return true;
}
}
@Override
public long removeAtIndex(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException();
} else {
long value = buffer.getLong(scale(index));
if (size > 1) {
buffer.copyFrom(buffer, scale(index + 1), scale(index), scale(size - index - 1));
}
size--;
return value;
}
}
@Override
public long set(int index, long element) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException();
} else {
long old = buffer.getLong(scale(index));
buffer.setLong(scale(index), element);
return old;
}
}
@Override
public boolean add(long element) {
ensureCapacity(size + 1);
buffer.setLong(scale(size), element);
size++;
return true;
}
@Override
public boolean addAll(long... source) {
ensureCapacity(size + source.length);
for (int i = 0; i < source.length; i++) {
buffer.setLong(scale(i + size), source[i]);
}
size += source.length;
return source.length > 0;
}
@Override
public boolean addAll(LongIterable source) {
int expectedSize = source.size();
ensureCapacity(size + expectedSize);
LongIterator itr = source.longIterator();
int i = 0;
while (itr.hasNext()) {
if (i > expectedSize) {
throw new ConcurrentModificationException();
}
buffer.setLong(scale(i + size), itr.next());
i++;
}
size += i;
return i > 0;
}
@Override
public boolean remove(long value) {
int ix = indexOf(value);
if (ix == -1) {
return false;
} else {
removeAtIndex(ix);
return true;
}
}
@Override
public boolean removeAll(LongIterable source) {
throw new UnsupportedOperationException();
}
@Override
public boolean removeAll(long... source) {
throw new UnsupportedOperationException();
}
@Override
public boolean retainAll(LongIterable elements) {
throw new UnsupportedOperationException();
}
@Override
public boolean retainAll(long... source) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
size = 0;
}
@Override
public MutableLongList with(long element) {
add(element);
return this;
}
@Override
public MutableLongList without(long element) {
remove(element);
return this;
}
@Override
public MutableLongList withAll(LongIterable elements) {
addAll(elements);
return this;
}
@Override
public MutableLongList withoutAll(LongIterable elements) {
removeAll(elements);
return this;
}
@Override
public MutableLongList reverseThis() {
throw new UnsupportedOperationException();
}
@Override
public MutableLongList sortThis() {
throw new UnsupportedOperationException();
}
@Override
public MutableLongList asUnmodifiable() {
return new UnmodifiableLongList(this);
}
@Override
public MutableLongList asSynchronized() {
return new SynchronizedLongList(this);
}
@Override
public MutableLongIterator longIterator() {
return new Itr();
}
@Override
public MutableLongList select(LongPredicate predicate) {
throw new UnsupportedOperationException();
}
@Override
public MutableLongList reject(LongPredicate predicate) {
throw new UnsupportedOperationException();
}
@Override
public <V> MutableList<V> collect(LongToObjectFunction<? extends V> function) {
throw new UnsupportedOperationException();
}
@Override
public MutableLongList toReversed() {
throw new UnsupportedOperationException();
}
@Override
public MutableLongList distinct() {
throw new UnsupportedOperationException();
}
@Override
public MutableLongList subList(int fromIndex, int toIndex) {
throw new UnsupportedOperationException();
}
class Itr extends LongBufferListImpl.Itr implements MutableLongIterator {
int removalIndex = -1;
@Override
public long next() {
removalIndex = i;
return super.next();
}
@Override
public void remove() {
if (removalIndex == -1) { throw new IllegalStateException(); }
removeAtIndex(removalIndex);
i--;
removalIndex = -1;
}
}
}
}