mirror of
https://github.com/enso-org/enso.git
synced 2025-01-03 16:23:25 +03:00
BigDecimalBuilder
and arithmetic operations. (#9950)
* hack * make a column * add * no scale=0 on BD type * a test * wip * 3 arithmetic ops * / * wip * BigDecimalPowerOp * wip * mod test * NumericBinaryOpReturningBigDecimal * with scalar * misc arithmetic tests * fix integralBigDecimalToInteger * mixed columns * bigdecimal pow via double * cleanup * j2e on get * arithmetic exception * mod 0 * cleanup * fmt * changelog * check type first * merge * mc error message * add BD case to Builder.java * fmt * changelog * add BD case to StorageConverter.java * fmt * fix test
This commit is contained in:
parent
106007cb89
commit
5fad3558a6
@ -5,9 +5,12 @@
|
|||||||
- [Added Statistic.Product][10122]
|
- [Added Statistic.Product][10122]
|
||||||
- [Added Encoding.Default that tries to detect UTF-8 or UTF-16 encoding based on
|
- [Added Encoding.Default that tries to detect UTF-8 or UTF-16 encoding based on
|
||||||
BOM][10130]
|
BOM][10130]
|
||||||
|
- [Added `Decimal` column to the in-memory database, with some arithmetic
|
||||||
|
operations.][9950]
|
||||||
|
|
||||||
[debug-shortcuts]:
|
[debug-shortcuts]:
|
||||||
|
|
||||||
|
[9950]: https://github.com/enso-org/enso/pull/9950
|
||||||
[10122]: https://github.com/enso-org/enso/pull/10122
|
[10122]: https://github.com/enso-org/enso/pull/10122
|
||||||
[10130]: https://github.com/enso-org/enso/pull/10130
|
[10130]: https://github.com/enso-org/enso/pull/10130
|
||||||
|
|
||||||
|
@ -499,7 +499,8 @@ type Decimal
|
|||||||
# => Decimal.new 45.7
|
# => Decimal.new 45.7
|
||||||
divide : Decimal -> Math_Context | Nothing -> Decimal ! Arithmetic_Error
|
divide : Decimal -> Math_Context | Nothing -> Decimal ! Arithmetic_Error
|
||||||
divide self (that : Decimal) (math_context : Math_Context | Nothing = Nothing) -> Decimal ! Arithmetic_Error =
|
divide self (that : Decimal) (math_context : Math_Context | Nothing = Nothing) -> Decimal ! Arithmetic_Error =
|
||||||
handle_java_exception <|
|
extra_message = " Please use `.divide` with an explicit `Math_Context` to limit the numeric precision."
|
||||||
|
handle_java_exception extra_message=extra_message <|
|
||||||
case math_context of
|
case math_context of
|
||||||
Nothing -> Decimal.Value (self.big_decimal.divide that.big_decimal)
|
Nothing -> Decimal.Value (self.big_decimal.divide that.big_decimal)
|
||||||
_ -> Decimal.Value (self.big_decimal.divide that.big_decimal math_context.math_context)
|
_ -> Decimal.Value (self.big_decimal.divide that.big_decimal math_context.math_context)
|
||||||
@ -1042,9 +1043,9 @@ attach_loss_of_numeric_precision x value =
|
|||||||
Warning.attach (Loss_Of_Numeric_Precision.Warning x value) value
|
Warning.attach (Loss_Of_Numeric_Precision.Warning x value) value
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
handle_java_exception ~action =
|
handle_java_exception ~action (extra_message : Text = "") =
|
||||||
Panic.catch ArithmeticException action caught_panic->
|
Panic.catch ArithmeticException action caught_panic->
|
||||||
Error.throw (Arithmetic_Error.Error caught_panic.payload.getMessage)
|
Error.throw (Arithmetic_Error.Error caught_panic.payload.getMessage+extra_message)
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
handle_unsupported_argument_types ~action =
|
handle_unsupported_argument_types ~action =
|
||||||
|
@ -31,6 +31,7 @@ import project.Value_Type.Value_Type
|
|||||||
from project.Errors import Conversion_Failure, Floating_Point_Equality, Inexact_Type_Coercion, Invalid_Column_Names, Invalid_Value_Type, No_Index_Set_Error
|
from project.Errors import Conversion_Failure, Floating_Point_Equality, Inexact_Type_Coercion, Invalid_Column_Names, Invalid_Value_Type, No_Index_Set_Error
|
||||||
from project.Internal.Column_Format import all
|
from project.Internal.Column_Format import all
|
||||||
from project.Internal.Java_Exports import make_date_builder_adapter, make_string_builder
|
from project.Internal.Java_Exports import make_date_builder_adapter, make_string_builder
|
||||||
|
from project.Internal.Storage import enso_to_java, java_to_enso
|
||||||
|
|
||||||
polyglot java import org.enso.base.Time_Utils
|
polyglot java import org.enso.base.Time_Utils
|
||||||
polyglot java import org.enso.table.data.column.operation.cast.CastProblemAggregator
|
polyglot java import org.enso.table.data.column.operation.cast.CastProblemAggregator
|
||||||
@ -89,6 +90,12 @@ type Column
|
|||||||
Value_Type.Boolean -> False
|
Value_Type.Boolean -> False
|
||||||
Value_Type.Byte -> False
|
Value_Type.Byte -> False
|
||||||
_ -> True
|
_ -> True
|
||||||
|
needs_enso_to_java_conversion = case value_type of
|
||||||
|
Value_Type.Decimal _ _ -> True
|
||||||
|
Auto -> True
|
||||||
|
_ -> False
|
||||||
|
enso_to_java_maybe items = if needs_enso_to_java_conversion.not then items else
|
||||||
|
items.map enso_to_java
|
||||||
expected_storage_type = case value_type of
|
expected_storage_type = case value_type of
|
||||||
Auto -> Nothing
|
Auto -> Nothing
|
||||||
_ -> Storage.from_value_type value_type on_problems=Problem_Behavior.Report_Warning
|
_ -> Storage.from_value_type value_type on_problems=Problem_Behavior.Report_Warning
|
||||||
@ -102,7 +109,7 @@ type Column
|
|||||||
Invalid_Column_Names.handle_java_exception <| Polyglot_Helpers.handle_polyglot_dataflow_errors <| handle_invalid_value_type <|
|
Invalid_Column_Names.handle_java_exception <| Polyglot_Helpers.handle_polyglot_dataflow_errors <| handle_invalid_value_type <|
|
||||||
java_column = Java_Problems.with_problem_aggregator Problem_Behavior.Report_Warning java_problem_aggregator->
|
java_column = Java_Problems.with_problem_aggregator Problem_Behavior.Report_Warning java_problem_aggregator->
|
||||||
case needs_polyglot_conversion of
|
case needs_polyglot_conversion of
|
||||||
True -> Java_Column.fromItems name items expected_storage_type java_problem_aggregator
|
True -> Java_Column.fromItems name (enso_to_java_maybe items) expected_storage_type java_problem_aggregator
|
||||||
False -> Java_Column.fromItemsNoDateConversion name items expected_storage_type java_problem_aggregator
|
False -> Java_Column.fromItemsNoDateConversion name items expected_storage_type java_problem_aggregator
|
||||||
result = Column.Value java_column . throw_on_warning Conversion_Failure
|
result = Column.Value java_column . throw_on_warning Conversion_Failure
|
||||||
result.catch Conversion_Failure error->
|
result.catch Conversion_Failure error->
|
||||||
@ -684,8 +691,9 @@ type Column
|
|||||||
example_div = Examples.decimal_column ^ Examples.integer_column
|
example_div = Examples.decimal_column ^ Examples.integer_column
|
||||||
^ : Column | Any -> Column
|
^ : Column | Any -> Column
|
||||||
^ self other =
|
^ self other =
|
||||||
Value_Type_Helpers.check_binary_numeric_op self other <|
|
Illegal_Argument.handle_java_exception <|
|
||||||
run_vectorized_binary_op self Java_Storage.Maps.POWER other
|
Value_Type_Helpers.check_binary_numeric_op self other <|
|
||||||
|
run_vectorized_binary_op self Java_Storage.Maps.POWER other
|
||||||
|
|
||||||
## ALIAS and
|
## ALIAS and
|
||||||
GROUP Standard.Base.Operators
|
GROUP Standard.Base.Operators
|
||||||
@ -2187,7 +2195,7 @@ type Column
|
|||||||
if valid_index.not then default else
|
if valid_index.not then default else
|
||||||
storage = self.java_column.getStorage
|
storage = self.java_column.getStorage
|
||||||
if storage.isNothing index then Nothing else
|
if storage.isNothing index then Nothing else
|
||||||
storage.getItem index
|
java_to_enso <| storage.getItem index
|
||||||
|
|
||||||
## ICON data_input
|
## ICON data_input
|
||||||
Returns a column containing rows of this column.
|
Returns a column containing rows of this column.
|
||||||
@ -2211,7 +2219,7 @@ type Column
|
|||||||
|
|
||||||
example_to_vector = Examples.integer_column.to_vector
|
example_to_vector = Examples.integer_column.to_vector
|
||||||
to_vector : Vector
|
to_vector : Vector
|
||||||
to_vector self = Vector.from_polyglot_array self.java_column.getStorage.toList
|
to_vector self = Vector.from_polyglot_array self.java_column.getStorage.toList . map java_to_enso
|
||||||
|
|
||||||
## GROUP Standard.Base.Metadata
|
## GROUP Standard.Base.Metadata
|
||||||
ICON metadata
|
ICON metadata
|
||||||
@ -2533,7 +2541,7 @@ run_vectorized_binary_op column name operand new_name=Nothing fallback_fn=Nothin
|
|||||||
_ ->
|
_ ->
|
||||||
s1 = column.java_column.getStorage
|
s1 = column.java_column.getStorage
|
||||||
rs = Polyglot_Helpers.handle_polyglot_dataflow_errors <|
|
rs = Polyglot_Helpers.handle_polyglot_dataflow_errors <|
|
||||||
s1.vectorizedOrFallbackBinaryMap name problem_builder fallback_fn operand skip_nulls storage_type
|
s1.vectorizedOrFallbackBinaryMap name problem_builder fallback_fn (enso_to_java operand) skip_nulls storage_type
|
||||||
Column.Value (Java_Column.new effective_new_name rs)
|
Column.Value (Java_Column.new effective_new_name rs)
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
|
@ -8,8 +8,11 @@ import project.Value_Type.Bits
|
|||||||
import project.Value_Type.Value_Type
|
import project.Value_Type.Value_Type
|
||||||
from project.Errors import Inexact_Type_Coercion
|
from project.Errors import Inexact_Type_Coercion
|
||||||
|
|
||||||
|
polyglot java import java.math.BigDecimal
|
||||||
|
|
||||||
polyglot java import org.enso.table.data.column.builder.Builder as Java_Builder
|
polyglot java import org.enso.table.data.column.builder.Builder as Java_Builder
|
||||||
polyglot java import org.enso.table.data.column.storage.type.AnyObjectType
|
polyglot java import org.enso.table.data.column.storage.type.AnyObjectType
|
||||||
|
polyglot java import org.enso.table.data.column.storage.type.BigDecimalType
|
||||||
polyglot java import org.enso.table.data.column.storage.type.BigIntegerType
|
polyglot java import org.enso.table.data.column.storage.type.BigIntegerType
|
||||||
polyglot java import org.enso.table.data.column.storage.type.Bits as Java_Bits
|
polyglot java import org.enso.table.data.column.storage.type.Bits as Java_Bits
|
||||||
polyglot java import org.enso.table.data.column.storage.type.BooleanType
|
polyglot java import org.enso.table.data.column.storage.type.BooleanType
|
||||||
@ -40,6 +43,7 @@ to_value_type storage_type = case storage_type of
|
|||||||
_ : DateType -> Value_Type.Date
|
_ : DateType -> Value_Type.Date
|
||||||
_ : DateTimeType -> Value_Type.Date_Time with_timezone=True
|
_ : DateTimeType -> Value_Type.Date_Time with_timezone=True
|
||||||
_ : TimeOfDayType -> Value_Type.Time
|
_ : TimeOfDayType -> Value_Type.Time
|
||||||
|
_ : BigDecimalType -> Value_Type.Decimal
|
||||||
_ : BigIntegerType -> Value_Type.Decimal scale=0
|
_ : BigIntegerType -> Value_Type.Decimal scale=0
|
||||||
_ : AnyObjectType -> Value_Type.Mixed
|
_ : AnyObjectType -> Value_Type.Mixed
|
||||||
|
|
||||||
@ -64,11 +68,29 @@ closest_storage_type value_type = case value_type of
|
|||||||
Value_Type.Mixed -> AnyObjectType.INSTANCE
|
Value_Type.Mixed -> AnyObjectType.INSTANCE
|
||||||
Value_Type.Decimal _ scale ->
|
Value_Type.Decimal _ scale ->
|
||||||
is_integer = scale.is_nothing || scale <= 0
|
is_integer = scale.is_nothing || scale <= 0
|
||||||
if is_integer then BigIntegerType.INSTANCE else
|
if is_integer then BigIntegerType.INSTANCE else BigDecimalType.INSTANCE
|
||||||
Error.throw (Illegal_Argument.Error "Columns of type "+value_type.to_display_text+" are currently not supported in the in-memory backend - only Decimal of integer type (scale <= 0) is supported. You may cast the column to Float first (lossy conversion).")
|
|
||||||
_ ->
|
_ ->
|
||||||
Error.throw (Illegal_Argument.Error "Columns of type "+value_type.to_display_text+" are currently not supported in the in-memory backend.")
|
Error.throw (Illegal_Argument.Error "Columns of type "+value_type.to_display_text+" are currently not supported in the in-memory backend.")
|
||||||
|
|
||||||
|
## PRIVATE
|
||||||
|
|
||||||
|
Convert an Enso value to a Java value before storing it in a Java `Column`.
|
||||||
|
This step is unnecessary for primitive and builtin values, but necessary for
|
||||||
|
values such as `Decimal`/`BigDecimal`.
|
||||||
|
enso_to_java x = case x of
|
||||||
|
Decimal.Value big_decimal -> big_decimal
|
||||||
|
_ -> x
|
||||||
|
|
||||||
|
## PRIVATE
|
||||||
|
|
||||||
|
Convert a Java value to an Enso value before returning it to Enso from a Java
|
||||||
|
`Column`. This step is unnecessary for primitive and builtin values, but
|
||||||
|
necessary for values such as `Decimal`/`BigDecimal`.
|
||||||
|
java_to_enso x = case x of
|
||||||
|
_ : Nothing -> Nothing
|
||||||
|
_ : BigDecimal -> Decimal.Value x
|
||||||
|
_ -> x
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
Converts a value type to an in-memory storage type, possibly approximating it
|
Converts a value type to an in-memory storage type, possibly approximating it
|
||||||
to the closest supported type.
|
to the closest supported type.
|
||||||
|
@ -27,6 +27,7 @@ most_specific_value_type : Any -> Boolean -> Value_Type
|
|||||||
most_specific_value_type value use_smallest=False =
|
most_specific_value_type value use_smallest=False =
|
||||||
case value of
|
case value of
|
||||||
_ : Float -> Value_Type.Float Bits.Bits_64
|
_ : Float -> Value_Type.Float Bits.Bits_64
|
||||||
|
_ : Decimal -> Value_Type.Decimal
|
||||||
_ : Boolean -> Value_Type.Boolean
|
_ : Boolean -> Value_Type.Boolean
|
||||||
_ : Date -> Value_Type.Date
|
_ : Date -> Value_Type.Date
|
||||||
_ : Time_Of_Day -> Value_Type.Time
|
_ : Time_Of_Day -> Value_Type.Time
|
||||||
|
@ -59,6 +59,25 @@ public class NumericConverter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Coerces a number to a BigDecimal.
|
||||||
|
*
|
||||||
|
* <p>Will throw an exception if the object is not a number.
|
||||||
|
*/
|
||||||
|
public static BigDecimal coerceToBigDecimal(Object o) {
|
||||||
|
return switch (o) {
|
||||||
|
case Double x -> BigDecimal.valueOf(x);
|
||||||
|
case BigDecimal x -> x;
|
||||||
|
case Float x -> BigDecimal.valueOf(x);
|
||||||
|
case BigInteger x -> new BigDecimal(x);
|
||||||
|
case Long x -> BigDecimal.valueOf(x);
|
||||||
|
case Integer x -> BigDecimal.valueOf(x);
|
||||||
|
case Short x -> BigDecimal.valueOf(x);
|
||||||
|
case Byte x -> BigDecimal.valueOf(x);
|
||||||
|
default -> throw new UnsupportedOperationException("Cannot coerce " + o + " to a BigDecimal.");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns true if the object is any supported number. */
|
/** Returns true if the object is any supported number. */
|
||||||
public static boolean isCoercibleToDouble(Object o) {
|
public static boolean isCoercibleToDouble(Object o) {
|
||||||
return isFloatLike(o)|| isCoercibleToLong(o) || o instanceof BigInteger;
|
return isFloatLike(o)|| isCoercibleToLong(o) || o instanceof BigInteger;
|
||||||
@ -66,7 +85,6 @@ public class NumericConverter {
|
|||||||
|
|
||||||
public static boolean isFloatLike(Object o) {
|
public static boolean isFloatLike(Object o) {
|
||||||
return o instanceof Double
|
return o instanceof Double
|
||||||
|| o instanceof BigDecimal
|
|
||||||
|| o instanceof Float;
|
|| o instanceof Float;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,49 @@
|
|||||||
|
package org.enso.table.data.column.builder;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import org.enso.table.data.column.storage.Storage;
|
||||||
|
import org.enso.table.data.column.storage.numeric.BigDecimalStorage;
|
||||||
|
import org.enso.table.data.column.storage.type.BigDecimalType;
|
||||||
|
import org.enso.table.data.column.storage.type.StorageType;
|
||||||
|
import org.enso.table.error.ValueTypeMismatchException;
|
||||||
|
|
||||||
|
/** A builder for BigDecimal columns. */
|
||||||
|
public class BigDecimalBuilder extends TypedBuilderImpl<BigDecimal> {
|
||||||
|
@Override
|
||||||
|
protected BigDecimal[] newArray(int size) {
|
||||||
|
return new BigDecimal[size];
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimalBuilder(int size) {
|
||||||
|
super(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StorageType getType() {
|
||||||
|
return BigDecimalType.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void appendNoGrow(Object o) {
|
||||||
|
try {
|
||||||
|
data[currentSize++] = (BigDecimal) o;
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
throw new ValueTypeMismatchException(getType(), o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void append(Object o) {
|
||||||
|
appendNoGrow(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean accepts(Object o) {
|
||||||
|
return o instanceof BigDecimal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Storage<BigDecimal> doSeal() {
|
||||||
|
return new BigDecimalStorage(data, currentSize);
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ package org.enso.table.data.column.builder;
|
|||||||
|
|
||||||
import org.enso.table.data.column.storage.Storage;
|
import org.enso.table.data.column.storage.Storage;
|
||||||
import org.enso.table.data.column.storage.type.AnyObjectType;
|
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.BigIntegerType;
|
||||||
import org.enso.table.data.column.storage.type.BooleanType;
|
import org.enso.table.data.column.storage.type.BooleanType;
|
||||||
import org.enso.table.data.column.storage.type.DateTimeType;
|
import org.enso.table.data.column.storage.type.DateTimeType;
|
||||||
@ -38,6 +39,7 @@ public abstract class Builder {
|
|||||||
case IntegerType integerType -> NumericBuilder.createLongBuilder(
|
case IntegerType integerType -> NumericBuilder.createLongBuilder(
|
||||||
size, integerType, problemAggregator);
|
size, integerType, problemAggregator);
|
||||||
case TextType textType -> new StringBuilder(size, textType);
|
case TextType textType -> new StringBuilder(size, textType);
|
||||||
|
case BigDecimalType x -> new BigDecimalBuilder(size);
|
||||||
case BigIntegerType x -> new BigIntegerBuilder(size, problemAggregator);
|
case BigIntegerType x -> new BigIntegerBuilder(size, problemAggregator);
|
||||||
case null -> new InferredBuilder(size, problemAggregator);
|
case null -> new InferredBuilder(size, problemAggregator);
|
||||||
};
|
};
|
||||||
|
@ -7,7 +7,7 @@ import org.enso.table.data.column.storage.type.DateType;
|
|||||||
import org.enso.table.data.column.storage.type.StorageType;
|
import org.enso.table.data.column.storage.type.StorageType;
|
||||||
import org.enso.table.error.ValueTypeMismatchException;
|
import org.enso.table.error.ValueTypeMismatchException;
|
||||||
|
|
||||||
/** A builder for string columns. */
|
/** A builder for LocalDate columns. */
|
||||||
public class DateBuilder extends TypedBuilderImpl<LocalDate> {
|
public class DateBuilder extends TypedBuilderImpl<LocalDate> {
|
||||||
@Override
|
@Override
|
||||||
protected LocalDate[] newArray(int size) {
|
protected LocalDate[] newArray(int size) {
|
||||||
|
@ -12,7 +12,7 @@ import org.enso.table.data.column.storage.type.StorageType;
|
|||||||
import org.enso.table.error.ValueTypeMismatchException;
|
import org.enso.table.error.ValueTypeMismatchException;
|
||||||
import org.graalvm.polyglot.Context;
|
import org.graalvm.polyglot.Context;
|
||||||
|
|
||||||
/** A builder for string columns. */
|
/** A builder for ZonedDateTime columns. */
|
||||||
public class DateTimeBuilder extends TypedBuilderImpl<ZonedDateTime> {
|
public class DateTimeBuilder extends TypedBuilderImpl<ZonedDateTime> {
|
||||||
@Override
|
@Override
|
||||||
protected ZonedDateTime[] newArray(int size) {
|
protected ZonedDateTime[] newArray(int size) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.enso.table.data.column.builder;
|
package org.enso.table.data.column.builder;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
@ -115,6 +116,8 @@ public class InferredBuilder extends Builder {
|
|||||||
currentBuilder = new StringBuilder(initialCapacity, TextType.VARIABLE_LENGTH);
|
currentBuilder = new StringBuilder(initialCapacity, TextType.VARIABLE_LENGTH);
|
||||||
} else if (o instanceof BigInteger) {
|
} else if (o instanceof BigInteger) {
|
||||||
currentBuilder = new BigIntegerBuilder(initialCapacity, problemAggregator);
|
currentBuilder = new BigIntegerBuilder(initialCapacity, problemAggregator);
|
||||||
|
} else if (o instanceof BigDecimal) {
|
||||||
|
currentBuilder = new BigDecimalBuilder(initialCapacity);
|
||||||
} else if (o instanceof LocalDate) {
|
} else if (o instanceof LocalDate) {
|
||||||
currentBuilder = new DateBuilder(initialCapacity);
|
currentBuilder = new DateBuilder(initialCapacity);
|
||||||
} else if (o instanceof LocalTime) {
|
} else if (o instanceof LocalTime) {
|
||||||
|
@ -7,7 +7,7 @@ import org.enso.table.data.column.storage.type.StorageType;
|
|||||||
import org.enso.table.data.column.storage.type.TimeOfDayType;
|
import org.enso.table.data.column.storage.type.TimeOfDayType;
|
||||||
import org.enso.table.error.ValueTypeMismatchException;
|
import org.enso.table.error.ValueTypeMismatchException;
|
||||||
|
|
||||||
/** A builder for string columns. */
|
/** A builder for LocalTime columns. */
|
||||||
public class TimeOfDayBuilder extends TypedBuilderImpl<LocalTime> {
|
public class TimeOfDayBuilder extends TypedBuilderImpl<LocalTime> {
|
||||||
@Override
|
@Override
|
||||||
protected LocalTime[] newArray(int size) {
|
protected LocalTime[] newArray(int size) {
|
||||||
|
@ -2,6 +2,7 @@ package org.enso.table.data.column.operation.cast;
|
|||||||
|
|
||||||
import org.enso.table.data.column.storage.Storage;
|
import org.enso.table.data.column.storage.Storage;
|
||||||
import org.enso.table.data.column.storage.type.AnyObjectType;
|
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.BigIntegerType;
|
||||||
import org.enso.table.data.column.storage.type.BooleanType;
|
import org.enso.table.data.column.storage.type.BooleanType;
|
||||||
import org.enso.table.data.column.storage.type.DateTimeType;
|
import org.enso.table.data.column.storage.type.DateTimeType;
|
||||||
@ -29,6 +30,8 @@ public interface StorageConverter<T> {
|
|||||||
case TextType textType -> new ToTextStorageConverter(textType);
|
case TextType textType -> new ToTextStorageConverter(textType);
|
||||||
case TimeOfDayType timeOfDayType -> new ToTimeOfDayStorageConverter();
|
case TimeOfDayType timeOfDayType -> new ToTimeOfDayStorageConverter();
|
||||||
case BigIntegerType bigIntegerType -> new ToBigIntegerConverter();
|
case BigIntegerType bigIntegerType -> new ToBigIntegerConverter();
|
||||||
|
case BigDecimalType bigDecimalType -> throw new UnsupportedOperationException(
|
||||||
|
"Conversion to BigDecimal is not yet supported.");
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.enso.table.data.column.operation.map.numeric.arithmetic;
|
package org.enso.table.data.column.operation.map.numeric.arithmetic;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import org.enso.table.data.column.operation.map.MapOperationProblemAggregator;
|
import org.enso.table.data.column.operation.map.MapOperationProblemAggregator;
|
||||||
import org.enso.table.data.column.storage.Storage;
|
import org.enso.table.data.column.storage.Storage;
|
||||||
@ -32,4 +33,10 @@ public class AddOp<T extends Number, I extends Storage<? super T>>
|
|||||||
BigInteger a, BigInteger b, int ix, MapOperationProblemAggregator problemAggregator) {
|
BigInteger a, BigInteger b, int ix, MapOperationProblemAggregator problemAggregator) {
|
||||||
return a.add(b);
|
return a.add(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal doBigDecimal(
|
||||||
|
BigDecimal a, BigDecimal b, int ix, MapOperationProblemAggregator problemAggregator) {
|
||||||
|
return a.add(b);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
package org.enso.table.data.column.operation.map.numeric.arithmetic;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import org.enso.table.data.column.operation.map.MapOperationProblemAggregator;
|
||||||
|
import org.enso.table.data.column.storage.Storage;
|
||||||
|
|
||||||
|
public class BigDecimalDivideOp<T extends Number, I extends Storage<? super T>>
|
||||||
|
extends NumericBinaryOpReturningBigDecimal<T, I> {
|
||||||
|
public BigDecimalDivideOp() {
|
||||||
|
super(Storage.Maps.DIV);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal doBigDecimal(
|
||||||
|
BigDecimal a, BigDecimal b, int ix, MapOperationProblemAggregator problemAggregator) {
|
||||||
|
try {
|
||||||
|
return a.divide(b);
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
String extraMessage =
|
||||||
|
" Please use `.divide` with an explicit `Math_Context` to limit the numeric precision.";
|
||||||
|
problemAggregator.reportArithmeticError(e.getMessage() + extraMessage, ix);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package org.enso.table.data.column.operation.map.numeric.arithmetic;
|
package org.enso.table.data.column.operation.map.numeric.arithmetic;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import org.enso.table.data.column.operation.map.MapOperationProblemAggregator;
|
import org.enso.table.data.column.operation.map.MapOperationProblemAggregator;
|
||||||
import org.enso.table.data.column.storage.Storage;
|
import org.enso.table.data.column.storage.Storage;
|
||||||
@ -40,4 +41,15 @@ public class ModOp<T extends Number, I extends Storage<? super T>>
|
|||||||
|
|
||||||
return a.mod(b);
|
return a.mod(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal doBigDecimal(
|
||||||
|
BigDecimal a, BigDecimal b, int ix, MapOperationProblemAggregator problemAggregator) {
|
||||||
|
if (b.equals(BigDecimal.ZERO)) {
|
||||||
|
problemAggregator.reportDivisionByZero(ix);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.remainder(b);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.enso.table.data.column.operation.map.numeric.arithmetic;
|
package org.enso.table.data.column.operation.map.numeric.arithmetic;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import org.enso.table.data.column.operation.map.MapOperationProblemAggregator;
|
import org.enso.table.data.column.operation.map.MapOperationProblemAggregator;
|
||||||
import org.enso.table.data.column.storage.Storage;
|
import org.enso.table.data.column.storage.Storage;
|
||||||
@ -32,4 +33,10 @@ public class MulOp<T extends Number, I extends Storage<? super T>>
|
|||||||
BigInteger a, BigInteger b, int ix, MapOperationProblemAggregator problemAggregator) {
|
BigInteger a, BigInteger b, int ix, MapOperationProblemAggregator problemAggregator) {
|
||||||
return a.multiply(b);
|
return a.multiply(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal doBigDecimal(
|
||||||
|
BigDecimal a, BigDecimal b, int ix, MapOperationProblemAggregator problemAggregator) {
|
||||||
|
return a.multiply(b);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.enso.table.data.column.operation.map.numeric.arithmetic;
|
package org.enso.table.data.column.operation.map.numeric.arithmetic;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import org.enso.table.data.column.operation.map.MapOperationProblemAggregator;
|
import org.enso.table.data.column.operation.map.MapOperationProblemAggregator;
|
||||||
|
|
||||||
@ -10,4 +11,7 @@ public interface NumericBinaryOpDefinition {
|
|||||||
|
|
||||||
BigInteger doBigInteger(
|
BigInteger doBigInteger(
|
||||||
BigInteger a, BigInteger b, int ix, MapOperationProblemAggregator problemAggregator);
|
BigInteger a, BigInteger b, int ix, MapOperationProblemAggregator problemAggregator);
|
||||||
|
|
||||||
|
BigDecimal doBigDecimal(
|
||||||
|
BigDecimal a, BigDecimal b, int ix, MapOperationProblemAggregator problemAggregator);
|
||||||
}
|
}
|
||||||
|
@ -2,15 +2,18 @@ package org.enso.table.data.column.operation.map.numeric.arithmetic;
|
|||||||
|
|
||||||
import static org.enso.table.data.column.operation.map.numeric.helpers.DoubleArrayAdapter.fromAnyStorage;
|
import static org.enso.table.data.column.operation.map.numeric.helpers.DoubleArrayAdapter.fromAnyStorage;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
import org.enso.base.polyglot.NumericConverter;
|
import org.enso.base.polyglot.NumericConverter;
|
||||||
import org.enso.table.data.column.operation.map.BinaryMapOperation;
|
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.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.BigIntegerArrayAdapter;
|
||||||
import org.enso.table.data.column.operation.map.numeric.helpers.DoubleArrayAdapter;
|
import org.enso.table.data.column.operation.map.numeric.helpers.DoubleArrayAdapter;
|
||||||
import org.enso.table.data.column.storage.Storage;
|
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.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.BigIntegerStorage;
|
||||||
import org.enso.table.data.column.storage.numeric.DoubleStorage;
|
import org.enso.table.data.column.storage.numeric.DoubleStorage;
|
||||||
import org.enso.table.data.column.storage.numeric.LongStorage;
|
import org.enso.table.data.column.storage.numeric.LongStorage;
|
||||||
@ -41,6 +44,8 @@ public abstract class NumericBinaryOpImplementation<T extends Number, I extends
|
|||||||
BigIntegerArrayAdapter.fromStorage(s), rhs, problemAggregator);
|
BigIntegerArrayAdapter.fromStorage(s), rhs, problemAggregator);
|
||||||
case BigIntegerStorage s -> runBigIntegerMap(
|
case BigIntegerStorage s -> runBigIntegerMap(
|
||||||
BigIntegerArrayAdapter.fromStorage(s), rhs, problemAggregator);
|
BigIntegerArrayAdapter.fromStorage(s), rhs, problemAggregator);
|
||||||
|
case BigDecimalStorage s -> runBigDecimalMap(
|
||||||
|
BigDecimalArrayAdapter.fromStorage(s), new BigDecimal(rhs), problemAggregator);
|
||||||
case DoubleStorage s -> runDoubleMap(s, rhs.doubleValue(), problemAggregator);
|
case DoubleStorage s -> runDoubleMap(s, rhs.doubleValue(), problemAggregator);
|
||||||
default -> throw new IllegalStateException(
|
default -> throw new IllegalStateException(
|
||||||
"Unsupported storage: " + storage.getClass().getCanonicalName());
|
"Unsupported storage: " + storage.getClass().getCanonicalName());
|
||||||
@ -53,6 +58,10 @@ public abstract class NumericBinaryOpImplementation<T extends Number, I extends
|
|||||||
BigIntegerArrayAdapter.fromStorage(s),
|
BigIntegerArrayAdapter.fromStorage(s),
|
||||||
BigInteger.valueOf(argAsLong),
|
BigInteger.valueOf(argAsLong),
|
||||||
problemAggregator);
|
problemAggregator);
|
||||||
|
case BigDecimalStorage s -> runBigDecimalMap(
|
||||||
|
BigDecimalArrayAdapter.fromStorage(s),
|
||||||
|
BigDecimal.valueOf(argAsLong),
|
||||||
|
problemAggregator);
|
||||||
case DoubleStorage s -> runDoubleMap(s, (double) argAsLong, problemAggregator);
|
case DoubleStorage s -> runDoubleMap(s, (double) argAsLong, problemAggregator);
|
||||||
default -> throw new IllegalStateException(
|
default -> throw new IllegalStateException(
|
||||||
"Unsupported storage: " + storage.getClass().getCanonicalName());
|
"Unsupported storage: " + storage.getClass().getCanonicalName());
|
||||||
@ -64,10 +73,17 @@ public abstract class NumericBinaryOpImplementation<T extends Number, I extends
|
|||||||
DoubleArrayAdapter.fromStorage(s), doubleArg, problemAggregator);
|
DoubleArrayAdapter.fromStorage(s), doubleArg, problemAggregator);
|
||||||
case BigIntegerStorage s -> runDoubleMap(
|
case BigIntegerStorage s -> runDoubleMap(
|
||||||
DoubleArrayAdapter.fromStorage(s), doubleArg, problemAggregator);
|
DoubleArrayAdapter.fromStorage(s), doubleArg, problemAggregator);
|
||||||
|
case BigDecimalStorage s -> runBigDecimalMap(
|
||||||
|
BigDecimalArrayAdapter.fromStorage(s),
|
||||||
|
BigDecimal.valueOf(doubleArg),
|
||||||
|
problemAggregator);
|
||||||
case DoubleStorage s -> runDoubleMap(s, doubleArg, problemAggregator);
|
case DoubleStorage s -> runDoubleMap(s, doubleArg, problemAggregator);
|
||||||
default -> throw new IllegalStateException(
|
default -> throw new IllegalStateException(
|
||||||
"Unsupported storage: " + storage.getClass().getCanonicalName());
|
"Unsupported storage: " + storage.getClass().getCanonicalName());
|
||||||
};
|
};
|
||||||
|
} else if (arg instanceof BigDecimal bd) {
|
||||||
|
return runBigDecimalMap(
|
||||||
|
BigDecimalArrayAdapter.fromAnyStorage(storage), bd, problemAggregator);
|
||||||
} else {
|
} else {
|
||||||
throw new UnexpectedTypeException("a Number.");
|
throw new UnexpectedTypeException("a Number.");
|
||||||
}
|
}
|
||||||
@ -78,7 +94,14 @@ public abstract class NumericBinaryOpImplementation<T extends Number, I extends
|
|||||||
public Storage<? extends Number> runZip(
|
public Storage<? extends Number> runZip(
|
||||||
I storage, Storage<?> arg, MapOperationProblemAggregator problemAggregator) {
|
I storage, Storage<?> arg, MapOperationProblemAggregator problemAggregator) {
|
||||||
return switch (storage) {
|
return switch (storage) {
|
||||||
case DoubleStorage lhs -> runDoubleZip(lhs, fromAnyStorage(arg), problemAggregator);
|
case DoubleStorage lhs -> switch (arg) {
|
||||||
|
case BigDecimalStorage rhs -> {
|
||||||
|
BigDecimalArrayAdapter left = BigDecimalArrayAdapter.fromStorage(lhs);
|
||||||
|
BigDecimalArrayAdapter right = BigDecimalArrayAdapter.fromStorage(rhs);
|
||||||
|
yield runBigDecimalZip(left, right, problemAggregator);
|
||||||
|
}
|
||||||
|
default -> runDoubleZip(lhs, fromAnyStorage(arg), problemAggregator);
|
||||||
|
};
|
||||||
|
|
||||||
case AbstractLongStorage lhs -> switch (arg) {
|
case AbstractLongStorage lhs -> switch (arg) {
|
||||||
case AbstractLongStorage rhs -> runLongZip(lhs, rhs, problemAggregator);
|
case AbstractLongStorage rhs -> runLongZip(lhs, rhs, problemAggregator);
|
||||||
@ -89,28 +112,45 @@ public abstract class NumericBinaryOpImplementation<T extends Number, I extends
|
|||||||
}
|
}
|
||||||
case DoubleStorage rhs -> runDoubleZip(
|
case DoubleStorage rhs -> runDoubleZip(
|
||||||
DoubleArrayAdapter.fromStorage(lhs), rhs, problemAggregator);
|
DoubleArrayAdapter.fromStorage(lhs), rhs, problemAggregator);
|
||||||
|
case BigDecimalStorage rhs -> {
|
||||||
|
BigDecimalArrayAdapter left = BigDecimalArrayAdapter.fromStorage(lhs);
|
||||||
|
BigDecimalArrayAdapter right = BigDecimalArrayAdapter.fromStorage(rhs);
|
||||||
|
yield runBigDecimalZip(left, right, problemAggregator);
|
||||||
|
}
|
||||||
default -> throw new IllegalStateException(
|
default -> throw new IllegalStateException(
|
||||||
"Unsupported storage: " + arg.getClass().getCanonicalName());
|
"Unsupported storage: " + arg.getClass().getCanonicalName());
|
||||||
};
|
};
|
||||||
|
|
||||||
case BigIntegerStorage lhs -> {
|
case BigIntegerStorage lhs -> {
|
||||||
BigIntegerArrayAdapter left = BigIntegerArrayAdapter.fromStorage(lhs);
|
|
||||||
yield switch (arg) {
|
yield switch (arg) {
|
||||||
case AbstractLongStorage rhs -> {
|
case AbstractLongStorage rhs -> {
|
||||||
|
BigIntegerArrayAdapter left = BigIntegerArrayAdapter.fromStorage(lhs);
|
||||||
BigIntegerArrayAdapter right = BigIntegerArrayAdapter.fromStorage(rhs);
|
BigIntegerArrayAdapter right = BigIntegerArrayAdapter.fromStorage(rhs);
|
||||||
yield runBigIntegerZip(left, right, problemAggregator);
|
yield runBigIntegerZip(left, right, problemAggregator);
|
||||||
}
|
}
|
||||||
case BigIntegerStorage rhs -> {
|
case BigIntegerStorage rhs -> {
|
||||||
|
BigIntegerArrayAdapter left = BigIntegerArrayAdapter.fromStorage(lhs);
|
||||||
BigIntegerArrayAdapter right = BigIntegerArrayAdapter.fromStorage(rhs);
|
BigIntegerArrayAdapter right = BigIntegerArrayAdapter.fromStorage(rhs);
|
||||||
yield runBigIntegerZip(left, right, problemAggregator);
|
yield runBigIntegerZip(left, right, problemAggregator);
|
||||||
}
|
}
|
||||||
case DoubleStorage rhs -> runDoubleZip(
|
case DoubleStorage rhs -> runDoubleZip(
|
||||||
DoubleArrayAdapter.fromStorage(lhs), rhs, problemAggregator);
|
DoubleArrayAdapter.fromStorage(lhs), rhs, problemAggregator);
|
||||||
|
case BigDecimalStorage rhs -> {
|
||||||
|
BigDecimalArrayAdapter left = BigDecimalArrayAdapter.fromStorage(lhs);
|
||||||
|
BigDecimalArrayAdapter right = BigDecimalArrayAdapter.fromStorage(rhs);
|
||||||
|
yield runBigDecimalZip(left, right, problemAggregator);
|
||||||
|
}
|
||||||
default -> throw new IllegalStateException(
|
default -> throw new IllegalStateException(
|
||||||
"Unsupported storage: " + arg.getClass().getCanonicalName());
|
"Unsupported storage: " + arg.getClass().getCanonicalName());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case BigDecimalStorage lhs -> {
|
||||||
|
BigDecimalArrayAdapter left = BigDecimalArrayAdapter.fromStorage(lhs);
|
||||||
|
BigDecimalArrayAdapter right = BigDecimalArrayAdapter.fromAnyStorage(arg);
|
||||||
|
yield runBigDecimalZip(left, right, problemAggregator);
|
||||||
|
}
|
||||||
|
|
||||||
default -> throw new IllegalStateException(
|
default -> throw new IllegalStateException(
|
||||||
"Unsupported storage: " + storage.getClass().getCanonicalName());
|
"Unsupported storage: " + storage.getClass().getCanonicalName());
|
||||||
};
|
};
|
||||||
@ -276,4 +316,45 @@ public abstract class NumericBinaryOpImplementation<T extends Number, I extends
|
|||||||
|
|
||||||
return new BigIntegerStorage(out, n);
|
return new BigIntegerStorage(out, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected BigDecimalStorage runBigDecimalZip(
|
||||||
|
BigDecimalArrayAdapter a,
|
||||||
|
BigDecimalArrayAdapter b,
|
||||||
|
MapOperationProblemAggregator problemAggregator) {
|
||||||
|
Context context = Context.getCurrent();
|
||||||
|
int n = a.size();
|
||||||
|
int m = Math.min(a.size(), b.size());
|
||||||
|
BigDecimal[] out = new BigDecimal[n];
|
||||||
|
for (int i = 0; i < m; i++) {
|
||||||
|
BigDecimal x = a.getItem(i);
|
||||||
|
BigDecimal y = b.getItem(i);
|
||||||
|
if (x != null && y != null) {
|
||||||
|
BigDecimal r = doBigDecimal(x, y, i, problemAggregator);
|
||||||
|
out[i] = r;
|
||||||
|
}
|
||||||
|
context.safepoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BigDecimalStorage(out, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BigDecimalStorage runBigDecimalMap(
|
||||||
|
BigDecimalArrayAdapter a, BigDecimal b, MapOperationProblemAggregator problemAggregator) {
|
||||||
|
Context context = Context.getCurrent();
|
||||||
|
int n = a.size();
|
||||||
|
BigDecimal[] out = new BigDecimal[n];
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
BigDecimal x = a.getItem(i);
|
||||||
|
if (x == null || b == null) {
|
||||||
|
out[i] = null;
|
||||||
|
} else {
|
||||||
|
BigDecimal r = doBigDecimal(x, b, i, problemAggregator);
|
||||||
|
out[i] = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
context.safepoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BigDecimalStorage(out, n);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,62 @@
|
|||||||
|
package org.enso.table.data.column.operation.map.numeric.arithmetic;
|
||||||
|
|
||||||
|
import static org.enso.table.data.column.operation.map.numeric.helpers.BigDecimalArrayAdapter.fromAnyStorage;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import org.enso.base.polyglot.NumericConverter;
|
||||||
|
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.storage.Storage;
|
||||||
|
import org.enso.table.data.column.storage.numeric.BigDecimalStorage;
|
||||||
|
|
||||||
|
public abstract class NumericBinaryOpReturningBigDecimal<
|
||||||
|
T extends Number, I extends Storage<? super T>>
|
||||||
|
extends NumericBinaryOpImplementation<T, I> {
|
||||||
|
public NumericBinaryOpReturningBigDecimal(String name) {
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Storage<? extends Number> runBinaryMap(
|
||||||
|
I storage, Object arg, MapOperationProblemAggregator problemAggregator) {
|
||||||
|
if (arg == null) {
|
||||||
|
return BigDecimalStorage.makeEmpty(storage.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
BigDecimalArrayAdapter lhs = fromAnyStorage(storage);
|
||||||
|
BigDecimal rhs = NumericConverter.coerceToBigDecimal(arg);
|
||||||
|
return runBigDecimalMap(lhs, rhs, problemAggregator);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Storage<? extends Number> runZip(
|
||||||
|
I storage, Storage<?> arg, MapOperationProblemAggregator problemAggregator) {
|
||||||
|
BigDecimalArrayAdapter left = BigDecimalArrayAdapter.fromAnyStorage(storage);
|
||||||
|
BigDecimalArrayAdapter right = BigDecimalArrayAdapter.fromAnyStorage(arg);
|
||||||
|
return runBigDecimalZip(left, right, problemAggregator);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long doLong(long a, long b, int ix, MapOperationProblemAggregator problemAggregator) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Impossible: should not reach here - a NumericOpReturningBigDecimal should always use the"
|
||||||
|
+ " doBigDecimal branch.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigInteger doBigInteger(
|
||||||
|
BigInteger a, BigInteger b, int ix, MapOperationProblemAggregator problemAggregator) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Impossible: should not reach here - a NumericOpReturningBigDecimal should always use the"
|
||||||
|
+ " doBigDecimal branch.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double doDouble(
|
||||||
|
double a, double b, int ix, MapOperationProblemAggregator problemAggregator) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Impossible: should not reach here - a NumericOpReturningBigDecimal should always use the"
|
||||||
|
+ " doBigDecimal branch.");
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ package org.enso.table.data.column.operation.map.numeric.arithmetic;
|
|||||||
|
|
||||||
import static org.enso.table.data.column.operation.map.numeric.helpers.DoubleArrayAdapter.fromAnyStorage;
|
import static org.enso.table.data.column.operation.map.numeric.helpers.DoubleArrayAdapter.fromAnyStorage;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import org.enso.base.polyglot.NumericConverter;
|
import org.enso.base.polyglot.NumericConverter;
|
||||||
import org.enso.table.data.column.operation.map.MapOperationProblemAggregator;
|
import org.enso.table.data.column.operation.map.MapOperationProblemAggregator;
|
||||||
@ -52,4 +53,12 @@ public abstract class NumericBinaryOpReturningDouble<T extends Number, I extends
|
|||||||
"Impossible: should not reach here - a NumericOpReturningDouble should always use the"
|
"Impossible: should not reach here - a NumericOpReturningDouble should always use the"
|
||||||
+ " doDouble branch.");
|
+ " doDouble branch.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal doBigDecimal(
|
||||||
|
BigDecimal a, BigDecimal b, int ix, MapOperationProblemAggregator problemAggregator) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Impossible: should not reach here - a NumericOpReturningDouble should always use the"
|
||||||
|
+ " doDouble branch.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.enso.table.data.column.operation.map.numeric.arithmetic;
|
package org.enso.table.data.column.operation.map.numeric.arithmetic;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import org.enso.table.data.column.operation.map.MapOperationProblemAggregator;
|
import org.enso.table.data.column.operation.map.MapOperationProblemAggregator;
|
||||||
import org.enso.table.data.column.storage.Storage;
|
import org.enso.table.data.column.storage.Storage;
|
||||||
@ -32,4 +33,10 @@ public class SubOp<T extends Number, I extends Storage<? super T>>
|
|||||||
BigInteger a, BigInteger b, int ix, MapOperationProblemAggregator problemAggregator) {
|
BigInteger a, BigInteger b, int ix, MapOperationProblemAggregator problemAggregator) {
|
||||||
return a.subtract(b);
|
return a.subtract(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal doBigDecimal(
|
||||||
|
BigDecimal a, BigDecimal b, int ix, MapOperationProblemAggregator problemAggregator) {
|
||||||
|
return a.subtract(b);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,124 @@
|
|||||||
|
package org.enso.table.data.column.operation.map.numeric.helpers;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import org.enso.table.data.column.storage.SpecializedStorage;
|
||||||
|
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;
|
||||||
|
|
||||||
|
public interface BigDecimalArrayAdapter {
|
||||||
|
BigDecimal getItem(int i);
|
||||||
|
|
||||||
|
int size();
|
||||||
|
|
||||||
|
static BigDecimalArrayAdapter fromStorage(SpecializedStorage<BigDecimal> storage) {
|
||||||
|
return new BigDecimalStorageAsBigDecimal(storage);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BigDecimalArrayAdapter fromStorage(BigIntegerStorage storage) {
|
||||||
|
return new BigIntegerStorageAsBigDecimal(storage);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BigDecimalArrayAdapter fromStorage(AbstractLongStorage storage) {
|
||||||
|
return new LongStorageAsBigDecimal(storage);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BigDecimalArrayAdapter fromStorage(DoubleStorage storage) {
|
||||||
|
return new DoubleStorageAsBigDecimal(storage);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BigDecimalArrayAdapter fromAnyStorage(Storage<?> storage) {
|
||||||
|
return switch (storage) {
|
||||||
|
case DoubleStorage s -> fromStorage(s);
|
||||||
|
case AbstractLongStorage s -> fromStorage(s);
|
||||||
|
case BigIntegerStorage s -> fromStorage(s);
|
||||||
|
case BigDecimalStorage s -> fromStorage(s);
|
||||||
|
default -> throw new IllegalStateException(
|
||||||
|
"Unsupported storage: " + storage.getClass().getCanonicalName());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class BigDecimalStorageAsBigDecimal implements BigDecimalArrayAdapter {
|
||||||
|
private final SpecializedStorage<BigDecimal> storage;
|
||||||
|
|
||||||
|
private BigDecimalStorageAsBigDecimal(SpecializedStorage<BigDecimal> storage) {
|
||||||
|
this.storage = storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal getItem(int i) {
|
||||||
|
return storage.getItemBoxed(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return storage.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BigIntegerStorageAsBigDecimal implements BigDecimalArrayAdapter {
|
||||||
|
private final BigIntegerStorage storage;
|
||||||
|
|
||||||
|
private BigIntegerStorageAsBigDecimal(BigIntegerStorage storage) {
|
||||||
|
this.storage = storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal getItem(int i) {
|
||||||
|
return new BigDecimal(storage.getItemBoxed(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return storage.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LongStorageAsBigDecimal implements BigDecimalArrayAdapter {
|
||||||
|
private final AbstractLongStorage storage;
|
||||||
|
|
||||||
|
private LongStorageAsBigDecimal(AbstractLongStorage storage) {
|
||||||
|
this.storage = storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal getItem(int i) {
|
||||||
|
if (storage.isNothing(i)) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
long x = storage.getItem(i);
|
||||||
|
return BigDecimal.valueOf(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return storage.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DoubleStorageAsBigDecimal implements BigDecimalArrayAdapter {
|
||||||
|
private final DoubleStorage storage;
|
||||||
|
|
||||||
|
private DoubleStorageAsBigDecimal(DoubleStorage storage) {
|
||||||
|
this.storage = storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal getItem(int i) {
|
||||||
|
if (storage.isNothing(i)) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
double x = storage.getItemAsDouble(i);
|
||||||
|
return BigDecimal.valueOf(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return storage.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,10 @@
|
|||||||
package org.enso.table.data.column.operation.map.numeric.helpers;
|
package org.enso.table.data.column.operation.map.numeric.helpers;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import org.enso.table.data.column.storage.Storage;
|
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.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.BigIntegerStorage;
|
||||||
import org.enso.table.data.column.storage.numeric.DoubleStorage;
|
import org.enso.table.data.column.storage.numeric.DoubleStorage;
|
||||||
|
|
||||||
@ -17,6 +19,10 @@ public interface DoubleArrayAdapter {
|
|||||||
return new BigIntegerStorageAsDouble(storage);
|
return new BigIntegerStorageAsDouble(storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DoubleArrayAdapter fromStorage(BigDecimalStorage storage) {
|
||||||
|
return new BigDecimalStorageAsDouble(storage);
|
||||||
|
}
|
||||||
|
|
||||||
static DoubleArrayAdapter fromStorage(AbstractLongStorage storage) {
|
static DoubleArrayAdapter fromStorage(AbstractLongStorage storage) {
|
||||||
return new LongStorageAsDouble(storage);
|
return new LongStorageAsDouble(storage);
|
||||||
}
|
}
|
||||||
@ -30,6 +36,7 @@ public interface DoubleArrayAdapter {
|
|||||||
case DoubleStorage s -> fromStorage(s);
|
case DoubleStorage s -> fromStorage(s);
|
||||||
case AbstractLongStorage s -> fromStorage(s);
|
case AbstractLongStorage s -> fromStorage(s);
|
||||||
case BigIntegerStorage s -> fromStorage(s);
|
case BigIntegerStorage s -> fromStorage(s);
|
||||||
|
case BigDecimalStorage s -> fromStorage(s);
|
||||||
default -> throw new IllegalStateException(
|
default -> throw new IllegalStateException(
|
||||||
"Unsupported storage: " + storage.getClass().getCanonicalName());
|
"Unsupported storage: " + storage.getClass().getCanonicalName());
|
||||||
};
|
};
|
||||||
@ -82,4 +89,28 @@ public interface DoubleArrayAdapter {
|
|||||||
return storage.size();
|
return storage.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class BigDecimalStorageAsDouble implements DoubleArrayAdapter {
|
||||||
|
private final BigDecimalStorage storage;
|
||||||
|
|
||||||
|
private BigDecimalStorageAsDouble(BigDecimalStorage storage) {
|
||||||
|
this.storage = storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getItemAsDouble(int i) {
|
||||||
|
BigDecimal x = storage.getItem(i);
|
||||||
|
return x.doubleValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNothing(long i) {
|
||||||
|
return storage.getItem(i) == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return storage.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,64 @@
|
|||||||
|
package org.enso.table.data.column.storage.numeric;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import org.enso.table.data.column.operation.map.MapOperationStorage;
|
||||||
|
import org.enso.table.data.column.operation.map.numeric.arithmetic.AddOp;
|
||||||
|
import org.enso.table.data.column.operation.map.numeric.arithmetic.BigDecimalDivideOp;
|
||||||
|
import org.enso.table.data.column.operation.map.numeric.arithmetic.ModOp;
|
||||||
|
import org.enso.table.data.column.operation.map.numeric.arithmetic.MulOp;
|
||||||
|
import org.enso.table.data.column.operation.map.numeric.arithmetic.PowerOp;
|
||||||
|
import org.enso.table.data.column.operation.map.numeric.arithmetic.SubOp;
|
||||||
|
import org.enso.table.data.column.operation.map.numeric.comparisons.EqualsComparison;
|
||||||
|
import org.enso.table.data.column.operation.map.numeric.comparisons.GreaterComparison;
|
||||||
|
import org.enso.table.data.column.operation.map.numeric.comparisons.GreaterOrEqualComparison;
|
||||||
|
import org.enso.table.data.column.operation.map.numeric.comparisons.LessComparison;
|
||||||
|
import org.enso.table.data.column.operation.map.numeric.comparisons.LessOrEqualComparison;
|
||||||
|
import org.enso.table.data.column.storage.ObjectStorage;
|
||||||
|
import org.enso.table.data.column.storage.SpecializedStorage;
|
||||||
|
import org.enso.table.data.column.storage.type.BigDecimalType;
|
||||||
|
import org.enso.table.data.column.storage.type.StorageType;
|
||||||
|
|
||||||
|
public final class BigDecimalStorage extends SpecializedStorage<BigDecimal> {
|
||||||
|
/**
|
||||||
|
* @param data the underlying data
|
||||||
|
* @param size the number of items stored
|
||||||
|
*/
|
||||||
|
public BigDecimalStorage(BigDecimal[] data, int size) {
|
||||||
|
super(data, size, buildOps());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BigDecimalStorage makeEmpty(int size) {
|
||||||
|
return new BigDecimalStorage(new BigDecimal[size], size);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MapOperationStorage<BigDecimal, SpecializedStorage<BigDecimal>> buildOps() {
|
||||||
|
MapOperationStorage<BigDecimal, SpecializedStorage<BigDecimal>> ops =
|
||||||
|
ObjectStorage.buildObjectOps();
|
||||||
|
return ops.add(new AddOp<>())
|
||||||
|
.add(new SubOp<>())
|
||||||
|
.add(new MulOp<>())
|
||||||
|
.add(new BigDecimalDivideOp<>())
|
||||||
|
.add(new PowerOp<>())
|
||||||
|
.add(new ModOp<>())
|
||||||
|
.add(new LessComparison<>())
|
||||||
|
.add(new LessOrEqualComparison<>())
|
||||||
|
.add(new EqualsComparison<>())
|
||||||
|
.add(new GreaterOrEqualComparison<>())
|
||||||
|
.add(new GreaterComparison<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected SpecializedStorage<BigDecimal> newInstance(BigDecimal[] data, int size) {
|
||||||
|
return new BigDecimalStorage(data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected BigDecimal[] newUnderlyingArray(int size) {
|
||||||
|
return new BigDecimal[size];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StorageType getType() {
|
||||||
|
return BigDecimalType.INSTANCE;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package org.enso.table.data.column.storage.type;
|
||||||
|
|
||||||
|
public record BigDecimalType() implements StorageType {
|
||||||
|
public static final BigDecimalType INSTANCE = new BigDecimalType();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNumeric() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasDate() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasTime() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,7 @@ import org.enso.base.polyglot.NumericConverter;
|
|||||||
*/
|
*/
|
||||||
public sealed interface StorageType
|
public sealed interface StorageType
|
||||||
permits AnyObjectType,
|
permits AnyObjectType,
|
||||||
|
BigDecimalType,
|
||||||
BigIntegerType,
|
BigIntegerType,
|
||||||
BooleanType,
|
BooleanType,
|
||||||
DateTimeType,
|
DateTimeType,
|
||||||
|
@ -651,6 +651,9 @@ add_specs suite_builder =
|
|||||||
|
|
||||||
Decimal.new "12" . div (Decimal.new "0") . should_fail_with Arithmetic_Error
|
Decimal.new "12" . div (Decimal.new "0") . should_fail_with Arithmetic_Error
|
||||||
|
|
||||||
|
nt_error = Arithmetic_Error.Error "Non-terminating decimal expansion; no exact representable decimal result. Please use `.divide` with an explicit `Math_Context` to limit the numeric precision."
|
||||||
|
((Decimal.new "1") / (Decimal.new "3")) . should_fail_with nt_error
|
||||||
|
|
||||||
suite_builder.group "pow" group_builder->
|
suite_builder.group "pow" group_builder->
|
||||||
group_builder.specify "should define pow" <|
|
group_builder.specify "should define pow" <|
|
||||||
Decimal.new "10" . pow 3 . should_equal 1000
|
Decimal.new "10" . pow 3 . should_equal 1000
|
||||||
|
@ -16,7 +16,6 @@ import Standard.Database.DB_Table.DB_Table
|
|||||||
|
|
||||||
from Standard.Test import all
|
from Standard.Test import all
|
||||||
|
|
||||||
|
|
||||||
import enso_dev.Base_Tests.Data.Round_Spec
|
import enso_dev.Base_Tests.Data.Round_Spec
|
||||||
|
|
||||||
from project.Common_Table_Operations.Util import run_default_backend
|
from project.Common_Table_Operations.Util import run_default_backend
|
||||||
@ -1789,6 +1788,91 @@ add_specs suite_builder setup =
|
|||||||
c.value_type . should_equal Value_Type.Mixed
|
c.value_type . should_equal Value_Type.Mixed
|
||||||
(empty.set c).at c.name . value_type . should_equal Value_Type.Mixed
|
(empty.set c).at c.name . value_type . should_equal Value_Type.Mixed
|
||||||
|
|
||||||
|
decimal_db_pending = if setup.is_database then "Decimals are currently not implemented for the Database backend."
|
||||||
|
suite_builder.group prefix+"Decimal" pending=decimal_db_pending group_builder->
|
||||||
|
data = Data.setup create_connection_fn
|
||||||
|
|
||||||
|
group_builder.teardown <|
|
||||||
|
data.teardown
|
||||||
|
|
||||||
|
table_builder cols =
|
||||||
|
setup.table_builder cols connection=data.connection
|
||||||
|
|
||||||
|
group_builder.specify "can store and retrieve values" <|
|
||||||
|
t = table_builder [["x", [Decimal.new "23257245345.345345345"]]]
|
||||||
|
t.at "x" . at 0 . should_be_a Decimal
|
||||||
|
t.at "x" . get 0 . should_be_a Decimal
|
||||||
|
|
||||||
|
group_builder.specify "arithmetic (decimal column and decimal column)" <|
|
||||||
|
t = table_builder [["x", [Decimal.new "23257245345.345345345"]], ["y", [Decimal.new "123e50"]], ["z", [Decimal.new "125e50"]], ["w", [Decimal.new 7513]], ["v", [Decimal.new "3.7"]]]
|
||||||
|
(t.at "x" + t.at "y").to_vector . should_equal [Decimal.new "12300000000000000000000000000000000000000023257245345.345345345"]
|
||||||
|
(t.at "x" - t.at "y").to_vector . should_equal [Decimal.new "-12299999999999999999999999999999999999999976742754654.654654655"]
|
||||||
|
(t.at "x" * t.at "y").to_vector . should_equal [Decimal.new "2.860641177477477477435E+62"]
|
||||||
|
(t.at "x" / t.at "z").to_vector . should_equal [Decimal.new "1.8605796276276276276E-42"]
|
||||||
|
(t.at "x" % t.at "w").to_vector . should_equal [Decimal.new "2545.345345345"]
|
||||||
|
(t.at "x" ^ t.at "v").to_vector . should_equal [Decimal.new "2.27125352907938E38" . to_float]
|
||||||
|
|
||||||
|
group_builder.specify "arithmetic (decimal column and non-decimal column)" <|
|
||||||
|
t = table_builder [["x", [Decimal.new "101.25"]], ["y", [30]], ["z", [40.5]], ["w", [2]], ["wf", [2.0]], ["wf2", [2.1]]]
|
||||||
|
|
||||||
|
(t.at "x" + t.at "y").to_vector . should_equal [Decimal.new "131.25"]
|
||||||
|
(t.at "x" - t.at "y").to_vector . should_equal [Decimal.new "71.25"]
|
||||||
|
(t.at "x" * t.at "y").to_vector . should_equal [Decimal.new "3037.5"]
|
||||||
|
(t.at "x" / t.at "y").to_vector . should_equal [Decimal.new "3.375"]
|
||||||
|
(t.at "x" % t.at "y").to_vector . should_equal [Decimal.new "11.25"]
|
||||||
|
|
||||||
|
(t.at "x" + t.at "z").to_vector . should_equal [Decimal.new "141.75"]
|
||||||
|
(t.at "x" - t.at "z").to_vector . should_equal [Decimal.new "60.75"]
|
||||||
|
(t.at "x" * t.at "z").to_vector . should_equal [Decimal.new "4100.625"]
|
||||||
|
(t.at "x" / t.at "z").to_vector . should_equal [Decimal.new "2.5"]
|
||||||
|
(t.at "x" % t.at "z").to_vector . should_equal [Decimal.new "20.25"]
|
||||||
|
|
||||||
|
(t.at "x" ^ t.at "w").to_vector . should_equal [Decimal.new "10251.5625"]
|
||||||
|
(t.at "x" ^ t.at "wf").to_vector . should_equal [Decimal.new "10251.5625"]
|
||||||
|
(t.at "x" ^ t.at "wf2").to_vector . should_equal [16267.827812994828]
|
||||||
|
|
||||||
|
group_builder.specify "arithmetic (column and scalar)" <|
|
||||||
|
t = table_builder [["x", [Decimal.new "23257245345.345345345"]], ["y", [Decimal.new "944548245.68648775"]]]
|
||||||
|
|
||||||
|
(t.at "x" + 10) . to_vector . should_equal [Decimal.new "23257245355.345345345"]
|
||||||
|
(t.at "x" - 10) . to_vector . should_equal [Decimal.new "23257245335.345345345"]
|
||||||
|
(t.at "x" * 10) . to_vector . should_equal [Decimal.new "232572453453.45345345"]
|
||||||
|
(t.at "x" / 10) . to_vector . should_equal [Decimal.new "2325724534.5345345345"]
|
||||||
|
(t.at "x" ^ 2) . to_vector . should_equal [Decimal.new "5.408994610535877E20" . to_float]
|
||||||
|
|
||||||
|
(t.at "x" + 10.1) . to_vector . should_equal [Decimal.new "23257245355.445345345"]
|
||||||
|
(t.at "x" - 10.1) . to_vector . should_equal [Decimal.new "23257245335.245345345"]
|
||||||
|
(t.at "x" * 10.1) . to_vector . should_equal [Decimal.new "234898177987.9879879845"]
|
||||||
|
(t.at "y" / 16.5) . to_vector . should_equal [Decimal.new "57245348.2234235"]
|
||||||
|
(t.at "x" ^ 2.0) . to_vector . should_equal [Decimal.new "5.408994610535877E20" . to_float]
|
||||||
|
|
||||||
|
(t.at "x" + 2^80) . to_vector . should_equal [Decimal.new "1208925819614652431951521.345345345"]
|
||||||
|
(t.at "x" - 2^80) . to_vector . should_equal [Decimal.new "-1208925819614605917460830.654654655"]
|
||||||
|
(t.at "x" * 2^80) . to_vector . should_equal [Decimal.new "28116284391100140971590625398136689.624350720"]
|
||||||
|
(t.at "y" / 2^80) . to_vector . should_equal [Decimal.new "0.0000000000000007813119964528366172913694049826337229003314632791443727910518646240234375"]
|
||||||
|
|
||||||
|
(t.at "x" + (Decimal.new "10.1")) . to_vector . should_equal [Decimal.new "23257245355.445345345"]
|
||||||
|
(t.at "x" - (Decimal.new "10.1")) . to_vector . should_equal [Decimal.new "23257245335.245345345"]
|
||||||
|
(t.at "x" * (Decimal.new "10.1")) . to_vector . should_equal [Decimal.new "234898177987.9879879845"]
|
||||||
|
(t.at "y" / (Decimal.new "16.5")) . to_vector . should_equal [Decimal.new "57245348.2234235"]
|
||||||
|
(t.at "x" ^ (Decimal.new "2.0")) . to_vector . should_equal [Decimal.new "5.408994610535877E20" . to_float]
|
||||||
|
|
||||||
|
group_builder.specify "arithmetic errors" <|
|
||||||
|
t = table_builder [["x", [Decimal.new "1"]], ["y", [Decimal.new "3"]], ["z", [Decimal.new "0"]]]
|
||||||
|
|
||||||
|
r0 = t.at "x" / t.at "y"
|
||||||
|
r0 . to_vector . should_equal [Nothing]
|
||||||
|
nt_error = Arithmetic_Error.Error "Non-terminating decimal expansion; no exact representable decimal result. Please use `.divide` with an explicit `Math_Context` to limit the numeric precision. (at rows [0])."
|
||||||
|
Problems.expect_only_warning nt_error r0
|
||||||
|
|
||||||
|
r1 = t.at "x" / t.at "z"
|
||||||
|
r1 . to_vector . should_equal [Nothing]
|
||||||
|
Problems.expect_only_warning Arithmetic_Error r1
|
||||||
|
|
||||||
|
r2 = t.at "x" % t.at "z"
|
||||||
|
r2 . to_vector . should_equal [Nothing]
|
||||||
|
Problems.expect_only_warning Arithmetic_Error r2
|
||||||
|
|
||||||
# A dummy value used to force the in-memory backend to trigger a infer a mixed type for the given column.
|
# A dummy value used to force the in-memory backend to trigger a infer a mixed type for the given column.
|
||||||
type Mixed_Type_Object
|
type Mixed_Type_Object
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ from Standard.Base import all
|
|||||||
|
|
||||||
import project.Util
|
import project.Util
|
||||||
|
|
||||||
|
import Standard.Base.Data.Vector.Map_Error
|
||||||
import Standard.Base.Errors.Common.Arithmetic_Error
|
import Standard.Base.Errors.Common.Arithmetic_Error
|
||||||
import Standard.Base.Errors.Common.Index_Out_Of_Bounds
|
import Standard.Base.Errors.Common.Index_Out_Of_Bounds
|
||||||
import Standard.Base.Errors.Common.Type_Error
|
import Standard.Base.Errors.Common.Type_Error
|
||||||
@ -95,7 +96,7 @@ add_specs suite_builder =
|
|||||||
if x == 1 then Error.throw "X" else x
|
if x == 1 then Error.throw "X" else x
|
||||||
col = Column.from_vector "Test" [foo 0, foo 1, foo 2]
|
col = Column.from_vector "Test" [foo 0, foo 1, foo 2]
|
||||||
col . should_fail_with Text
|
col . should_fail_with Text
|
||||||
col.catch . should_equal "X"
|
col.catch . should_equal (Map_Error.Error 1 'X')
|
||||||
|
|
||||||
group_builder.specify "should not allow invalid column names" <|
|
group_builder.specify "should not allow invalid column names" <|
|
||||||
c1 = Column.from_vector "" [1, 2, 3]
|
c1 = Column.from_vector "" [1, 2, 3]
|
||||||
|
Loading…
Reference in New Issue
Block a user