Skip to content

Commit

Permalink
Implement in-memory and database mixed decimal column comparisons (#1…
Browse files Browse the repository at this point in the history
  • Loading branch information
GregoryTravis authored Jul 25, 2024
1 parent 8c4a40c commit f31c084
Show file tree
Hide file tree
Showing 12 changed files with 224 additions and 31 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,16 @@
- [Compare two objects with `Ordering.compare` and define comparator with
`Comparable.new`][10468]
- [Added `dec` construction function for creating `Decimal`s.][10517]
- [Implemented in-memory and database mixed `Decimal` column
comparisons.][10614]

[10434]: https://github.com/enso-org/enso/pull/10434
[10445]: https://github.com/enso-org/enso/pull/10445
[10466]: https://github.com/enso-org/enso/pull/10466
[10467]: https://github.com/enso-org/enso/pull/10467
[10474]: https://github.com/enso-org/enso/pull/10474
[10517]: https://github.com/enso-org/enso/pull/10517
[10614]: https://github.com/enso-org/enso/pull/10614

# Enso 2024.2

Expand Down
2 changes: 1 addition & 1 deletion distribution/lib/Standard/Table/0.0.0-dev/src/Column.enso
Original file line number Diff line number Diff line change
Expand Up @@ -2684,7 +2684,7 @@ run_vectorized_binary_op_with_fallback_problem_handling column name operand fall
_ ->
s1 = column.java_column.getStorage
rs = Polyglot_Helpers.handle_polyglot_dataflow_errors <|
s1.vectorizedOrFallbackBinaryMap name problem_builder applied_fn operand skip_nulls storage_type
s1.vectorizedOrFallbackBinaryMap name problem_builder applied_fn (enso_to_java operand) skip_nulls storage_type
Column.Value (Java_Column.new new_name rs)

## PRIVATE
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.enso.table.data.column.operation.map.numeric.comparisons;

import java.math.BigDecimal;
import java.math.BigInteger;
import org.enso.table.data.column.operation.map.MapOperationProblemAggregator;
import org.enso.table.data.column.operation.map.numeric.helpers.DoubleArrayAdapter;
Expand Down Expand Up @@ -43,6 +44,11 @@ protected boolean doBigInteger(BigInteger a, BigInteger b) {
return a.equals(b);
}

@Override
protected boolean doBigDecimal(BigDecimal a, BigDecimal b) {
return a.compareTo(b) == 0;
}

@Override
protected boolean onOtherType(Object a, Object b) {
return false;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.enso.table.data.column.operation.map.numeric.comparisons;

import java.math.BigDecimal;
import java.math.BigInteger;
import org.enso.table.data.column.storage.Storage;

Expand All @@ -23,4 +24,9 @@ protected boolean doLong(long a, long b) {
protected boolean doBigInteger(BigInteger a, BigInteger b) {
return a.compareTo(b) > 0;
}

@Override
protected boolean doBigDecimal(BigDecimal a, BigDecimal b) {
return a.compareTo(b) > 0;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.enso.table.data.column.operation.map.numeric.comparisons;

import java.math.BigDecimal;
import java.math.BigInteger;
import org.enso.table.data.column.storage.Storage;

Expand All @@ -23,4 +24,9 @@ protected boolean doLong(long a, long b) {
protected boolean doBigInteger(BigInteger a, BigInteger b) {
return a.compareTo(b) >= 0;
}

@Override
protected boolean doBigDecimal(BigDecimal a, BigDecimal b) {
return a.compareTo(b) >= 0;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.enso.table.data.column.operation.map.numeric.comparisons;

import java.math.BigDecimal;
import java.math.BigInteger;
import org.enso.table.data.column.storage.Storage;

Expand All @@ -23,4 +24,9 @@ protected boolean doLong(long a, long b) {
protected boolean doBigInteger(BigInteger a, BigInteger b) {
return a.compareTo(b) < 0;
}

@Override
protected boolean doBigDecimal(BigDecimal a, BigDecimal b) {
return a.compareTo(b) < 0;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.enso.table.data.column.operation.map.numeric.comparisons;

import java.math.BigDecimal;
import java.math.BigInteger;
import org.enso.table.data.column.storage.Storage;

Expand All @@ -23,4 +24,9 @@ protected boolean doLong(long a, long b) {
protected boolean doBigInteger(BigInteger a, BigInteger b) {
return a.compareTo(b) <= 0;
}

@Override
protected boolean doBigDecimal(BigDecimal a, BigDecimal b) {
return a.compareTo(b) <= 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,20 @@

import static org.enso.table.data.column.operation.map.numeric.helpers.DoubleArrayAdapter.fromAnyStorage;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.BitSet;
import org.enso.base.CompareException;
import org.enso.base.polyglot.NumericConverter;
import org.enso.table.data.column.operation.map.BinaryMapOperation;
import org.enso.table.data.column.operation.map.MapOperationProblemAggregator;
import org.enso.table.data.column.operation.map.numeric.helpers.BigDecimalArrayAdapter;
import org.enso.table.data.column.operation.map.numeric.helpers.BigIntegerArrayAdapter;
import org.enso.table.data.column.operation.map.numeric.helpers.DoubleArrayAdapter;
import org.enso.table.data.column.storage.BoolStorage;
import org.enso.table.data.column.storage.Storage;
import org.enso.table.data.column.storage.numeric.AbstractLongStorage;
import org.enso.table.data.column.storage.numeric.BigDecimalStorage;
import org.enso.table.data.column.storage.numeric.BigIntegerStorage;
import org.enso.table.data.column.storage.numeric.DoubleStorage;
import org.enso.table.data.column.storage.type.AnyObjectType;
Expand All @@ -28,6 +31,8 @@ public abstract class NumericComparison<T extends Number, I extends Storage<? su

protected abstract boolean doBigInteger(BigInteger a, BigInteger b);

protected abstract boolean doBigDecimal(BigDecimal a, BigDecimal b);

protected boolean onOtherType(Object a, Object b) {
throw new CompareException(a, b);
}
Expand All @@ -47,24 +52,47 @@ public BoolStorage runBinaryMap(
BigIntegerArrayAdapter.fromStorage(s), bigInteger, problemAggregator);
case BigIntegerStorage s -> runBigIntegerMap(
BigIntegerArrayAdapter.fromStorage(s), bigInteger, problemAggregator);
case BigDecimalStorage s -> runBigDecimalMap(
BigDecimalArrayAdapter.fromStorage(s), new BigDecimal(bigInteger), problemAggregator);
case DoubleStorage s -> runDoubleMap(s, bigInteger.doubleValue(), problemAggregator);
default -> throw new IllegalStateException(
"Unsupported lhs storage: " + storage.getClass().getCanonicalName());
};
} else if (arg instanceof BigDecimal bigDecimal) {
return switch (storage) {
case AbstractLongStorage s -> runBigDecimalMap(
BigDecimalArrayAdapter.fromStorage(s), bigDecimal, problemAggregator);
case BigIntegerStorage s -> runBigDecimalMap(
BigDecimalArrayAdapter.fromStorage(s), bigDecimal, problemAggregator);
case BigDecimalStorage s -> runBigDecimalMap(
BigDecimalArrayAdapter.fromStorage(s), bigDecimal, problemAggregator);
case DoubleStorage s -> runBigDecimalMap(
BigDecimalArrayAdapter.fromStorage(s), bigDecimal, problemAggregator);
default -> throw new IllegalStateException(
"Unsupported lhs storage: " + storage.getClass().getCanonicalName());
};
} else if (NumericConverter.isCoercibleToLong(arg)) {
long rhs = NumericConverter.coerceToLong(arg);
return switch (storage) {
case AbstractLongStorage s -> runLongMap(s, rhs, problemAggregator);
case BigIntegerStorage s -> runBigIntegerMap(
BigIntegerArrayAdapter.fromStorage(s), BigInteger.valueOf(rhs), problemAggregator);
case BigDecimalStorage s -> runBigDecimalMap(
BigDecimalArrayAdapter.fromStorage(s), BigDecimal.valueOf(rhs), problemAggregator);
case DoubleStorage s -> runDoubleMap(s, (double) rhs, problemAggregator);
default -> throw new IllegalStateException(
"Unsupported lhs storage: " + storage.getClass().getCanonicalName());
};
} else if (NumericConverter.isCoercibleToDouble(arg)) {
DoubleArrayAdapter lhs = DoubleArrayAdapter.fromAnyStorage(storage);
double rhs = NumericConverter.coerceToDouble(arg);
return runDoubleMap(lhs, rhs, problemAggregator);
return switch (storage) {
case BigDecimalStorage s -> runBigDecimalMap(
BigDecimalArrayAdapter.fromStorage(s), BigDecimal.valueOf(rhs), problemAggregator);
default -> {
DoubleArrayAdapter lhs = DoubleArrayAdapter.fromAnyStorage(storage);
yield runDoubleMap(lhs, rhs, problemAggregator);
}
};
} else {
int n = storage.size();
BitSet isNothing = new BitSet();
Expand Down Expand Up @@ -155,16 +183,47 @@ protected BoolStorage runBigIntegerMap(
return new BoolStorage(comparisonResults, isNothing, n, false);
}

protected BoolStorage runBigDecimalMap(
BigDecimalArrayAdapter lhs, BigDecimal rhs, MapOperationProblemAggregator problemAggregator) {
int n = lhs.size();
BitSet comparisonResults = new BitSet();
BitSet isNothing = new BitSet();
Context context = Context.getCurrent();
for (int i = 0; i < n; ++i) {
BigDecimal item = lhs.getItem(i);
if (item == null) {
isNothing.set(i);
} else {
boolean r = doBigDecimal(item, rhs);
if (r) {
comparisonResults.set(i);
}
}

context.safepoint();
}

return new BoolStorage(comparisonResults, isNothing, n, false);
}

@Override
public BoolStorage runZip(
I storage, Storage<?> arg, MapOperationProblemAggregator problemAggregator) {
return switch (storage) {
case DoubleStorage lhs -> {
if (arg.getType() instanceof AnyObjectType) {
yield runMixedZip(lhs, arg, problemAggregator);
} else {
yield runDoubleZip(lhs, fromAnyStorage(arg), problemAggregator);
}
yield switch (arg) {
case BigDecimalStorage rhs -> runBigDecimalZip(
BigDecimalArrayAdapter.fromStorage(lhs),
BigDecimalArrayAdapter.fromStorage(rhs),
problemAggregator);
default -> {
if (arg.getType() instanceof AnyObjectType) {
yield runMixedZip(lhs, arg, problemAggregator);
} else {
yield runDoubleZip(lhs, fromAnyStorage(arg), problemAggregator);
}
}
};
}

case AbstractLongStorage lhs -> switch (arg) {
Expand All @@ -174,28 +233,50 @@ public BoolStorage runZip(
BigIntegerArrayAdapter right = BigIntegerArrayAdapter.fromStorage(rhs);
yield runBigIntegerZip(left, right, problemAggregator);
}
case BigDecimalStorage rhs -> runBigDecimalZip(
BigDecimalArrayAdapter.fromStorage(lhs),
BigDecimalArrayAdapter.fromStorage(rhs),
problemAggregator);
case DoubleStorage rhs -> runDoubleZip(
DoubleArrayAdapter.fromStorage(lhs), rhs, problemAggregator);
default -> runMixedZip(lhs, arg, problemAggregator);
};

case BigIntegerStorage lhs -> {
BigIntegerArrayAdapter left = BigIntegerArrayAdapter.fromStorage(lhs);
yield switch (arg) {
case AbstractLongStorage rhs -> {
BigIntegerArrayAdapter left = BigIntegerArrayAdapter.fromStorage(lhs);
BigIntegerArrayAdapter right = BigIntegerArrayAdapter.fromStorage(rhs);
yield runBigIntegerZip(left, right, problemAggregator);
}
case BigIntegerStorage rhs -> {
BigIntegerArrayAdapter left = BigIntegerArrayAdapter.fromStorage(lhs);
BigIntegerArrayAdapter right = BigIntegerArrayAdapter.fromStorage(rhs);
yield runBigIntegerZip(left, right, problemAggregator);
}
case BigDecimalStorage rhs -> runBigDecimalZip(
BigDecimalArrayAdapter.fromStorage(lhs),
BigDecimalArrayAdapter.fromStorage(rhs),
problemAggregator);
case DoubleStorage rhs -> runDoubleZip(
DoubleArrayAdapter.fromStorage(lhs), rhs, problemAggregator);
default -> runMixedZip(lhs, arg, problemAggregator);
};
}

case BigDecimalStorage lhs -> {
if (arg instanceof AbstractLongStorage
|| arg instanceof BigIntegerStorage
|| arg instanceof BigDecimalStorage
|| arg instanceof DoubleStorage) {
BigDecimalArrayAdapter left = BigDecimalArrayAdapter.fromAnyStorage(lhs);
BigDecimalArrayAdapter right = BigDecimalArrayAdapter.fromAnyStorage(arg);
yield runBigDecimalZip(left, right, problemAggregator);
} else {
yield runMixedZip(lhs, arg, problemAggregator);
}
}

default -> throw new IllegalStateException(
"Unsupported lhs storage: " + storage.getClass().getCanonicalName());
};
Expand Down Expand Up @@ -294,6 +375,37 @@ protected BoolStorage runBigIntegerZip(
return new BoolStorage(comparisonResults, isNothing, n, false);
}

protected BoolStorage runBigDecimalZip(
BigDecimalArrayAdapter lhs,
BigDecimalArrayAdapter rhs,
MapOperationProblemAggregator problemAggregator) {
int n = lhs.size();
int m = Math.min(lhs.size(), rhs.size());
BitSet comparisonResults = new BitSet();
BitSet isNothing = new BitSet();
Context context = Context.getCurrent();
for (int i = 0; i < m; ++i) {
BigDecimal x = lhs.getItem(i);
BigDecimal y = rhs.getItem(i);
if (x == null || y == null) {
isNothing.set(i);
} else {
boolean r = doBigDecimal(x, y);
if (r) {
comparisonResults.set(i);
}
}

context.safepoint();
}

if (m < n) {
isNothing.set(m, n);
}

return new BoolStorage(comparisonResults, isNothing, n, false);
}

protected BoolStorage runMixedZip(
Storage<?> lhs, Storage<?> rhs, MapOperationProblemAggregator problemAggregator) {
int n = lhs.size();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.enso.table.data.column.builder.Builder;
import org.enso.table.data.column.operation.map.MapOperationProblemAggregator;
import org.enso.table.data.column.storage.type.AnyObjectType;
import org.enso.table.data.column.storage.type.BigDecimalType;
import org.enso.table.data.column.storage.type.BigIntegerType;
import org.enso.table.data.column.storage.type.FloatType;
import org.enso.table.data.column.storage.type.IntegerType;
Expand Down Expand Up @@ -52,13 +53,16 @@ protected SpecializedStorage<Object> newInstance(Object[] data, int size) {
private boolean isNumeric(StorageType type) {
return type instanceof IntegerType
|| type instanceof FloatType
|| type instanceof BigIntegerType;
|| type instanceof BigIntegerType
|| type instanceof BigDecimalType;
}

private StorageType commonNumericType(StorageType a, StorageType b) {
assert isNumeric(a);
assert isNumeric(b);
if (a instanceof FloatType || b instanceof FloatType) {
if (a instanceof BigDecimalType || b instanceof BigDecimalType) {
return BigDecimalType.INSTANCE;
} else if (a instanceof FloatType || b instanceof FloatType) {
return FloatType.FLOAT_64;
} else if (a instanceof BigIntegerType || b instanceof BigIntegerType) {
return BigIntegerType.INSTANCE;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.enso.table.data.column.storage.type;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
Expand Down Expand Up @@ -42,6 +43,7 @@ static StorageType forBoxedItem(Object item) {

return switch (item) {
case String s -> TextType.VARIABLE_LENGTH;
case BigDecimal i -> BigDecimalType.INSTANCE;
case BigInteger i -> BigIntegerType.INSTANCE;
case Boolean b -> BooleanType.INSTANCE;
case LocalDate d -> DateType.INSTANCE;
Expand Down
Loading

0 comments on commit f31c084

Please sign in to comment.