package at.yawk.numaec;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException;
import org.eclipse.collections.api.LazyShortIterable;
import org.eclipse.collections.api.RichIterable;
import org.eclipse.collections.api.bag.Bag;
import org.eclipse.collections.api.bag.primitive.DoubleBag;
import org.eclipse.collections.api.block.function.primitive.DoubleToObjectFunction;
import org.eclipse.collections.api.block.function.primitive.ObjectDoubleToObjectFunction;
import org.eclipse.collections.api.block.predicate.primitive.DoublePredicate;
import org.eclipse.collections.api.block.predicate.primitive.ShortDoublePredicate;
import org.eclipse.collections.api.block.procedure.Procedure;
import org.eclipse.collections.api.block.procedure.primitive.DoubleProcedure;
import org.eclipse.collections.api.block.procedure.primitive.ShortDoubleProcedure;
import org.eclipse.collections.api.block.procedure.primitive.ShortProcedure;
import org.eclipse.collections.api.collection.primitive.MutableDoubleCollection;
import org.eclipse.collections.api.iterator.DoubleIterator;
import org.eclipse.collections.api.iterator.MutableDoubleIterator;
import org.eclipse.collections.api.iterator.ShortIterator;
import org.eclipse.collections.api.map.primitive.DoubleShortMap;
import org.eclipse.collections.api.map.primitive.ImmutableShortDoubleMap;
import org.eclipse.collections.api.map.primitive.ShortDoubleMap;
import org.eclipse.collections.api.set.primitive.MutableShortSet;
import org.eclipse.collections.api.tuple.primitive.ShortDoublePair;
import org.eclipse.collections.impl.lazy.AbstractLazyIterable;
import org.eclipse.collections.impl.lazy.primitive.AbstractLazyShortIterable;
import org.eclipse.collections.impl.primitive.AbstractDoubleIterable;
import org.eclipse.collections.impl.tuple.primitive.PrimitiveTuples;
abstract class BaseShortDoubleMap extends AbstractDoubleIterable implements ShortDoubleMap {
static final long KEY_MASK = -1L >>> (64 - (Short.BYTES * 8));
static final long VALUE_MASK = -1L >>> (64 - (Double.BYTES * 8));
static long toKey(short key) {
return key & KEY_MASK;
}
static long toValue(double value) {
return Double.doubleToRawLongBits(value) & VALUE_MASK;
}
@SuppressWarnings("ConstantConditions")
static short fromKey(long key) {
if (KEY_MASK != -1) { if (key < 0 || key > KEY_MASK) { throw new IllegalArgumentException(); } }
return (short) key;
}
@SuppressWarnings("ConstantConditions")
static double fromValue(long value) {
if (VALUE_MASK != -1) { if (value < 0 || value > VALUE_MASK) { throw new IllegalArgumentException(); } }
return (double) Double.longBitsToDouble(value);
}
protected abstract MapStoreCursor iterationCursor();
protected abstract MapStoreCursor keyCursor(short key);
@DoNotMutate
void checkInvariants() {
int count = count(x -> true);
if (count != size()) { throw new AssertionError(); }
}
@Override
public double getIfAbsent(short key, double ifAbsent) {
try (MapStoreCursor cursor = keyCursor(key)) {
if (cursor.elementFound()) {
return fromValue(cursor.getValue());
} else {
return ifAbsent;
}
}
}
@Override
public double getOrThrow(short key) {
try (MapStoreCursor cursor = keyCursor(key)) {
if (cursor.elementFound()) {
return fromValue(cursor.getValue());
} else {
throw new IllegalStateException("Key " + key + " not present");
}
}
}
@Override
public boolean containsKey(short key) {
try (MapStoreCursor cursor = keyCursor(key)) {
return cursor.elementFound();
}
}
@Override
public void forEachKey(ShortProcedure procedure) {
try (MapStoreCursor cursor = iterationCursor()) {
while (cursor.next()) {
procedure.value(fromKey(cursor.getKey()));
}
}
}
@Override
public void forEachKeyValue(ShortDoubleProcedure procedure) {
try (MapStoreCursor cursor = iterationCursor()) {
while (cursor.next()) {
procedure.value(fromKey(cursor.getKey()),
fromValue(cursor.getValue()));
}
}
}
@Override
public LazyShortIterable keysView() {
return new AbstractLazyShortIterable() {
@Override
public ShortIterator shortIterator() {
return new KeyIterator(iterationCursor());
}
@Override
public void each(ShortProcedure procedure) {
forEachKey(procedure);
}
};
}
@Override
public RichIterable<ShortDoublePair> keyValuesView() {
return new AbstractLazyIterable<ShortDoublePair>() {
@Override
public Iterator<ShortDoublePair> iterator() {
return new KeyValueIterator(iterationCursor());
}
@Override
public void each(Procedure<? super ShortDoublePair> procedure) {
iterator().forEachRemaining(procedure);
}
};
}
@Override
public boolean containsValue(double value) {
long needle = toValue(value);
try (MapStoreCursor cursor = iterationCursor()) {
while (cursor.next()) {
if (cursor.getValue() == needle) {
return true;
}
}
}
return false;
}
@Override
public void forEachValue(DoubleProcedure procedure) {
try (MapStoreCursor cursor = iterationCursor()) {
while (cursor.next()) {
procedure.value(fromValue(cursor.getValue()));
}
}
}
@Override
public MutableDoubleIterator doubleIterator() {
return new ValueIterator(iterationCursor());
}
@Override
public double[] toArray() {
double[] data = new double[size()];
try (MapStoreCursor cursor = iterationCursor()) {
int i = 0;
while (cursor.next()) {
if (i >= data.length) { throw new ConcurrentModificationException(); }
data[i++] = fromValue(cursor.getValue());
}
if (i < data.length) { throw new ConcurrentModificationException(); }
return data;
}
}
@Override
public double detectIfNone(DoublePredicate predicate, double ifNone) {
try (MapStoreCursor cursor = iterationCursor()) {
while (cursor.next()) {
double value = fromValue(cursor.getValue());
if (predicate.accept(value)) {
return value;
}
}
}
return ifNone;
}
@Override
public int count(DoublePredicate predicate) {
int count = 0;
try (MapStoreCursor cursor = iterationCursor()) {
while (cursor.next()) {
double value = fromValue(cursor.getValue());
if (predicate.accept(value)) {
count++;
}
}
}
return count;
}
@Override
public boolean anySatisfy(DoublePredicate predicate) {
try (MapStoreCursor cursor = iterationCursor()) {
while (cursor.next()) {
double value = fromValue(cursor.getValue());
if (predicate.accept(value)) {
return true;
}
}
}
return false;
}
@Override
public boolean allSatisfy(DoublePredicate predicate) {
try (MapStoreCursor cursor = iterationCursor()) {
while (cursor.next()) {
double value = fromValue(cursor.getValue());
if (!predicate.accept(value)) {
return false;
}
}
}
return true;
}
@Override
public <T> T injectInto(T injectedValue, ObjectDoubleToObjectFunction<? super T, ? extends T> function) {
try (MapStoreCursor cursor = iterationCursor()) {
while (cursor.next()) {
injectedValue = function.valueOf(injectedValue, fromValue(cursor.getValue()));
}
}
return injectedValue;
}
@Override
public double
sum() {
double
sum = 0;
try (MapStoreCursor cursor = iterationCursor()) {
while (cursor.next()) {
sum += fromValue(cursor.getValue());
}
}
return sum;
}
@Override
public double max() {
try (MapStoreCursor cursor = iterationCursor()) {
if (!cursor.next()) { throw new NoSuchElementException(); }
double max = fromValue(cursor.getValue());
while (cursor.next()) {
max = (double) Math.max(max, fromValue(cursor.getValue()));
}
return max;
}
}
@Override
public double min() {
try (MapStoreCursor cursor = iterationCursor()) {
if (!cursor.next()) { throw new NoSuchElementException(); }
double min = fromValue(cursor.getValue());
while (cursor.next()) {
min = (double) Math.min(min, fromValue(cursor.getValue()));
}
return min;
}
}
@Override
public void appendString(Appendable appendable, String start, String separator, String end) {
try (MapStoreCursor cursor = iterationCursor()) {
appendable.append(start);
boolean first = true;
while (cursor.next()) {
if (first) {
first = false;
} else {
appendable.append(separator);
}
appendable.append(String.valueOf(fromValue(cursor.getValue())));
}
appendable.append(end);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder("{");
try (MapStoreCursor cursor = iterationCursor()) {
boolean first = true;
while (cursor.next()) {
if (first) {
first = false;
} else {
builder.append(", ");
}
builder.append(fromKey(cursor.getKey()))
.append('=')
.append(fromValue(cursor.getValue()));
}
return builder.append('}').toString();
}
}
@Override
public double get(short key) {
return getIfAbsent(key, (double) 0);
}
@Override
public DoubleShortMap flipUniqueValues() {
throw new UnsupportedOperationException("ShortDoubleBufferMap.flipUniqueValues not implemented yet");
}
@Override
public ShortDoubleMap select(ShortDoublePredicate predicate) {
throw new UnsupportedOperationException("ShortDoubleBufferMap.select not implemented yet");
}
@Override
public ShortDoubleMap reject(ShortDoublePredicate predicate) {
throw new UnsupportedOperationException("ShortDoubleBufferMap.reject not implemented yet");
}
@Override
public ImmutableShortDoubleMap toImmutable() {
throw new UnsupportedOperationException("ShortDoubleBufferMap.toImmutable not implemented yet");
}
@Override
public MutableShortSet keySet() {
throw new UnsupportedOperationException("ShortDoubleBufferMap.keySet not implemented yet");
}
@Override
public MutableDoubleCollection values() {
throw new UnsupportedOperationException("ShortDoubleBufferMap.values not implemented yet");
}
@Override
public DoubleBag select(DoublePredicate predicate) {
throw new UnsupportedOperationException("ShortDoubleBufferMap.select not implemented yet");
}
@Override
public DoubleBag reject(DoublePredicate predicate) {
throw new UnsupportedOperationException("ShortDoubleBufferMap.reject not implemented yet");
}
@Override
public <V> Bag<V> collect(DoubleToObjectFunction<? extends V> function) {
throw new UnsupportedOperationException("ShortDoubleBufferMap.collect not implemented yet");
}
@Override
public boolean contains(double value) {
return containsValue(value);
}
@Override
public void forEach(DoubleProcedure procedure) {
forEachValue(procedure);
}
@Override
public void each(DoubleProcedure procedure) {
forEachValue(procedure);
}
@Override
public boolean noneSatisfy(DoublePredicate predicate) {
return !anySatisfy(predicate);
}
private static abstract class BaseIterator {
protected final MapStoreCursor cursor;
private boolean peeked;
BaseIterator(MapStoreCursor cursor) {
this.cursor = cursor;
}
protected void next0() {
if (!hasNext()) { throw new NoSuchElementException(); }
peeked = false;
}
public boolean hasNext() {
if (peeked) {
return true;
} else {
return peeked = cursor.next();
}
}
}
private static class KeyIterator extends BaseIterator implements ShortIterator {
KeyIterator(MapStoreCursor cursor) {
super(cursor);
}
@Override
public short next() {
next0();
return fromKey(cursor.getKey());
}
}
private static class KeyValueIterator extends BaseIterator implements Iterator<ShortDoublePair> {
KeyValueIterator(MapStoreCursor cursor) {
super(cursor);
}
@Override
public ShortDoublePair next() {
next0();
return PrimitiveTuples.pair(fromKey(cursor.getKey()), fromValue(cursor.getValue()));
}
}
protected static class ValueIterator extends BaseIterator implements DoubleIterator, MutableDoubleIterator {
ValueIterator(MapStoreCursor cursor) {
super(cursor);
}
@Override
public double next() {
next0();
return fromValue(cursor.getValue());
}
@Override
public void remove() {
throw new UnsupportedOperationException("ValueIterator.remove not implemented yet");
}
}
}