LF: clean shifting BigNumeric builtin (#9704)

CHANGELOG_BEGIN
CHANGELOG_END
This commit is contained in:
Remy 2021-05-17 19:26:14 +02:00 committed by GitHub
parent 7a97d88f42
commit fc745f2224
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 111 additions and 74 deletions

View File

@ -264,7 +264,7 @@ instance Pretty BuiltinExpr where
BESubBigNumeric -> "SUB_BIGNUMERIC"
BEMulBigNumeric -> "MUl_BIGNUMERIC"
BEDivBigNumeric -> "DIV_BIGNUMERIC"
BEShiftBigNumeric -> "SHIFT_BIGNUMERIC"
BEShiftBigNumeric -> "SHIFT_RIGHT_BIGNUMERIC"
BEToNumericBigNumeric -> "TO_NUMERIC_BIGNUMERIC"
BEFromNumericBigNumeric -> "TO_BIGNUMERIC_NUMERIC"
BEToTextBigNumeric -> "TO_TEXT_BIGNUMERIC"

View File

@ -494,7 +494,7 @@ decodeBuiltinFunction = pure . \case
LF1.BuiltinFunctionSUB_BIGNUMERIC -> BESubBigNumeric
LF1.BuiltinFunctionMUL_BIGNUMERIC -> BEMulBigNumeric
LF1.BuiltinFunctionDIV_BIGNUMERIC -> BEDivBigNumeric
LF1.BuiltinFunctionSHIFT_BIGNUMERIC -> BEShiftBigNumeric
LF1.BuiltinFunctionSHIFT_RIGHT_BIGNUMERIC -> BEShiftBigNumeric
LF1.BuiltinFunctionTO_NUMERIC_BIGNUMERIC -> BEToNumericBigNumeric
LF1.BuiltinFunctionTO_BIGNUMERIC_NUMERIC -> BEFromNumericBigNumeric
LF1.BuiltinFunctionTO_TEXT_BIGNUMERIC -> BEToTextBigNumeric

View File

@ -510,7 +510,7 @@ encodeBuiltinExpr = \case
BESubBigNumeric -> builtin P.BuiltinFunctionSUB_BIGNUMERIC
BEMulBigNumeric -> builtin P.BuiltinFunctionMUL_BIGNUMERIC
BEDivBigNumeric -> builtin P.BuiltinFunctionDIV_BIGNUMERIC
BEShiftBigNumeric -> builtin P.BuiltinFunctionSHIFT_BIGNUMERIC
BEShiftBigNumeric -> builtin P.BuiltinFunctionSHIFT_RIGHT_BIGNUMERIC
BEToNumericBigNumeric -> builtin P.BuiltinFunctionTO_NUMERIC_BIGNUMERIC
BEFromNumericBigNumeric -> builtin P.BuiltinFunctionTO_BIGNUMERIC_NUMERIC
BEToTextBigNumeric -> builtin P.BuiltinFunctionTO_TEXT_BIGNUMERIC

View File

@ -569,7 +569,7 @@ enum BuiltinFunction {
SUB_BIGNUMERIC = 140; // *Available in versions >= 1.13*
MUL_BIGNUMERIC = 141; // *Available in versions >= 1.13*
DIV_BIGNUMERIC = 142; // *Available in versions >= 1.13*
SHIFT_BIGNUMERIC = 143; // *Available in versions >= 1.13*
SHIFT_RIGHT_BIGNUMERIC = 143; // *Available in versions >= 1.13*
TO_NUMERIC_BIGNUMERIC = 144; // *Available in versions >= 1.13*
TO_BIGNUMERIC_NUMERIC = 145; // *Available in versions >= 1.13*
TO_TEXT_BIGNUMERIC = 146; // *Available in versions >= 1.13*

View File

@ -580,7 +580,7 @@ enum BuiltinFunction {
SUB_BIGNUMERIC = 140; // *Available in versions >= 1.13*
MUL_BIGNUMERIC = 141; // *Available in versions >= 1.13*
DIV_BIGNUMERIC = 142; // *Available in versions >= 1.13*
SHIFT_BIGNUMERIC = 143; // *Available in versions >= 1.13*
SHIFT_RIGHT_BIGNUMERIC = 143; // *Available in versions >= 1.13*
TO_NUMERIC_BIGNUMERIC = 144; // *Available in versions >= 1.13*
TO_BIGNUMERIC_NUMERIC = 145; // *Available in versions >= 1.13*
TO_TEXT_BIGNUMERIC = 146; // *Available in versions >= 1.13*

View File

@ -1838,7 +1838,7 @@ private[lf] object DecodeV1 {
BuiltinFunctionInfo(SUB_BIGNUMERIC, BSubBigNumeric, minVersion = bigNumeric),
BuiltinFunctionInfo(MUL_BIGNUMERIC, BMulBigNumeric, minVersion = bigNumeric),
BuiltinFunctionInfo(DIV_BIGNUMERIC, BDivBigNumeric, minVersion = bigNumeric),
BuiltinFunctionInfo(SHIFT_BIGNUMERIC, BShiftBigNumeric, minVersion = bigNumeric),
BuiltinFunctionInfo(SHIFT_RIGHT_BIGNUMERIC, BShiftRightBigNumeric, minVersion = bigNumeric),
BuiltinFunctionInfo(TO_NUMERIC_BIGNUMERIC, BToNumericBigNumeric, minVersion = bigNumeric),
BuiltinFunctionInfo(TO_BIGNUMERIC_NUMERIC, BToBigNumericNumeric, minVersion = bigNumeric),
BuiltinFunctionInfo(TO_TEXT_BIGNUMERIC, BToTextBigNumeric, minVersion = bigNumeric),

View File

@ -300,8 +300,8 @@ class ProtoTest extends AnyWordSpec with Matchers with TableDrivenPropertyChecks
("file", "Linux hash", "windows hash"),
(
"daml_lf_1.proto",
"66c18f32acff0c75cc2cbcb55e175749aedc246ccb9630cc959b462ddf717af4",
"33c4f75472db481862a745d18b7e28843aa284666b79b822172cd7ead1dc6ca8",
"6d0869fd8b326cc82f7507ec9deb37520af23ccc4c03a78af623683eb5df2bee",
"7cc33b6549ce425608858b1cd1c5a56fd4e928bb1df015f8ad24019377eb4154",
),
(
"daml_lf.proto",

View File

@ -26,8 +26,8 @@ module BuiltinMod {
MUL_BIGNUMERIC;
val divBigNumeric: Int64 -> RoundingMode -> BigNumeric -> BigNumeric -> BigNumeric =
DIV_BIGNUMERIC;
val shiftBigNumeric: Int64 -> BigNumeric -> BigNumeric =
SHIFT_BIGNUMERIC;
val shiftRightBigNumeric: Int64 -> BigNumeric -> BigNumeric =
SHIFT_RIGHT_BIGNUMERIC;
val toNumericBigNumeric: forall (n: nat). BigNumeric -> Numeric n =
TO_NUMERIC_BIGNUMERIC;
val toBigNumericNumeric: forall (n: nat). Numeric n -> BigNumeric =

View File

@ -569,7 +569,7 @@ private[lf] final class Compiler(
case BSubBigNumeric => SBSubBigNumeric
case BDivBigNumeric => SBDivBigNumeric
case BMulBigNumeric => SBMulBigNumeric
case BShiftBigNumeric => SBShiftBigNumeric
case BShiftRightBigNumeric => SBShiftRightBigNumeric
case BToBigNumericNumeric => SBToBigNumericNumeric
case BToNumericBigNumeric => SBToNumericBigNumeric
case BToTextBigNumeric => SBToText

View File

@ -911,14 +911,19 @@ private[lf] object SBuiltin {
}
}
final object SBShiftBigNumeric extends SBuiltinPure(2) {
final object SBShiftRightBigNumeric extends SBuiltinPure(2) {
override private[speedy] def executePure(args: util.ArrayList[SValue]): SBigNumeric = {
val shifting = getSInt64(args, 0)
if (shifting.abs > SBigNumeric.MaxPrecision) throw DamlEArithmeticError("overflow/underflow")
rightOrArithmeticError(
"overflow/underflow",
SBigNumeric.fromBigDecimal(getSBigNumeric(args, 1).scaleByPowerOfTen(-shifting.toInt)),
)
val x = getSBigNumeric(args, 1)
if (x.signum() == 0)
SBigNumeric.Zero
else if (shifting.abs > SBigNumeric.MaxPrecision)
throw DamlEArithmeticError("overflow/underflow")
else
rightOrArithmeticError(
"overflow/underflow",
SBigNumeric.fromBigDecimal(x.scaleByPowerOfTen(-shifting.toInt)),
)
}
}

View File

@ -268,6 +268,8 @@ object SValue {
def assertFromBigDecimal(x: java.math.BigDecimal): SBigNumeric =
data.assertRight(fromBigDecimal(x))
val Zero: SBigNumeric = new SBigNumeric(java.math.BigDecimal.ZERO)
def checkScale(s: Long): Either[String, Int] =
Either.cond(test = s.abs <= MaxScale, right = s.toInt, left = "invalide scale")
}

View File

@ -145,16 +145,16 @@ class SBuiltinBigNumericTest extends AnyFreeSpec with Matchers with TableDrivenP
val testCases = Table(
"arguments" -> "success",
s"(SHIFT_BIGNUMERIC ${MinScale} BigNumeric:one) BigNumeric:one" -> true,
s"(SHIFT_BIGNUMERIC ${MinScale} BigNumeric:one) BigNumeric:ten" -> false,
s"(SHIFT_BIGNUMERIC ${MinScale / 2 - 1} BigNumeric:one) (SHIFT_BIGNUMERIC ${MinScale / 2} BigNumeric:one)" -> true,
s"(SHIFT_BIGNUMERIC ${MinScale / 2 - 1} BigNumeric:one) (SHIFT_BIGNUMERIC ${MinScale / 2 - 1} BigNumeric:one)" -> false,
s"(SHIFT_BIGNUMERIC ${MaxScale} BigNumeric:one) BigNumeric:one" -> true,
s"(SHIFT_BIGNUMERIC ${MaxScale} BigNumeric:one) (SHIFT_BIGNUMERIC 1 BigNumeric:one)" -> false,
s"(SHIFT_BIGNUMERIC ${MinScale / 2 - 1} BigNumeric:one) (SHIFT_BIGNUMERIC ${MinScale / 2} BigNumeric:one)" -> true,
s"(SHIFT_BIGNUMERIC ${MinScale / 2 - 1} BigNumeric:one) (SHIFT_BIGNUMERIC ${MinScale / 2 - 1} BigNumeric:one)" -> false,
s"(SHIFT_BIGNUMERIC ${MinScale / 2} BigNumeric:underSqrtOfTen) (SHIFT_BIGNUMERIC ${MinScale / 2 - 1} BigNumeric:underSqrtOfTen)" -> true,
s"(SHIFT_BIGNUMERIC ${MinScale / 2} BigNumeric:overSqrtOfTen) (SHIFT_BIGNUMERIC ${MinScale / 2 - 1} BigNumeric:overSqrtOfTen)" -> false,
s"(SHIFT_RIGHT_BIGNUMERIC ${MinScale} BigNumeric:one) BigNumeric:one" -> true,
s"(SHIFT_RIGHT_BIGNUMERIC ${MinScale} BigNumeric:one) BigNumeric:ten" -> false,
s"(SHIFT_RIGHT_BIGNUMERIC ${MinScale / 2 - 1} BigNumeric:one) (SHIFT_RIGHT_BIGNUMERIC ${MinScale / 2} BigNumeric:one)" -> true,
s"(SHIFT_RIGHT_BIGNUMERIC ${MinScale / 2 - 1} BigNumeric:one) (SHIFT_RIGHT_BIGNUMERIC ${MinScale / 2 - 1} BigNumeric:one)" -> false,
s"(SHIFT_RIGHT_BIGNUMERIC ${MaxScale} BigNumeric:one) BigNumeric:one" -> true,
s"(SHIFT_RIGHT_BIGNUMERIC ${MaxScale} BigNumeric:one) (SHIFT_RIGHT_BIGNUMERIC 1 BigNumeric:one)" -> false,
s"(SHIFT_RIGHT_BIGNUMERIC ${MinScale / 2 - 1} BigNumeric:one) (SHIFT_RIGHT_BIGNUMERIC ${MinScale / 2} BigNumeric:one)" -> true,
s"(SHIFT_RIGHT_BIGNUMERIC ${MinScale / 2 - 1} BigNumeric:one) (SHIFT_RIGHT_BIGNUMERIC ${MinScale / 2 - 1} BigNumeric:one)" -> false,
s"(SHIFT_RIGHT_BIGNUMERIC ${MinScale / 2} BigNumeric:underSqrtOfTen) (SHIFT_RIGHT_BIGNUMERIC ${MinScale / 2 - 1} BigNumeric:underSqrtOfTen)" -> true,
s"(SHIFT_RIGHT_BIGNUMERIC ${MinScale / 2} BigNumeric:overSqrtOfTen) (SHIFT_RIGHT_BIGNUMERIC ${MinScale / 2 - 1} BigNumeric:overSqrtOfTen)" -> false,
)
forEvery(testCases)((args, success) =>
@ -167,40 +167,40 @@ class SBuiltinBigNumericTest extends AnyFreeSpec with Matchers with TableDrivenP
"throws an exception in case of overflow" in {
val testCases = Table(
"arguments" -> "success",
s"-1000 ROUNDING_DOWN (SHIFT_BIGNUMERIC ${MinScale / 2} BigNumeric:one) (SHIFT_BIGNUMERIC ${-(MinScale / 2 - 1)} BigNumeric:one)" -> true,
s"-1000 ROUNDING_DOWN (SHIFT_BIGNUMERIC ${MinScale / 2 - 1} BigNumeric:one) (SHIFT_BIGNUMERIC ${-(MinScale / 2 - 1)} BigNumeric:one)" -> false,
s"-1000 ROUNDING_DOWN (SHIFT_BIGNUMERIC ${MinScale} BigNumeric:one) BigNumeric:one" -> true,
s"-1000 ROUNDING_DOWN (SHIFT_BIGNUMERIC ${MinScale} BigNumeric:one) (SHIFT_BIGNUMERIC 1 BigNumeric:one)" -> false,
s"-1000 ROUNDING_DOWN (SHIFT_BIGNUMERIC ${MinScale / 2 - 1} BigNumeric:underSqrtOfTen) (SHIFT_BIGNUMERIC ${-(MinScale / 2 - 1)} BigNumeric:overSqrtOfTen)" -> true,
s"-1000 ROUNDING_DOWN (SHIFT_BIGNUMERIC ${MinScale / 2 - 1} BigNumeric:overSqrtOfTen) (SHIFT_BIGNUMERIC ${-(MinScale / 2 - 1)} BigNumeric:overSqrtOfTen)" -> false,
s"${MinScale} ROUNDING_UP BigNumeric:nineteen (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:two)" -> false,
s"${MinScale} ROUNDING_DOWN BigNumeric:nineteen (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:two)" -> true,
s"${MinScale} ROUNDING_CEILING BigNumeric:nineteen (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:two)" -> false,
s"${MinScale} ROUNDING_FLOOR BigNumeric:nineteen (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:two)" -> true,
s"${MinScale} ROUNDING_HALF_UP BigNumeric:nineteen (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:two)" -> false,
s"${MinScale} ROUNDING_HALF_DOWN BigNumeric:nineteen (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:two)" -> true,
s"${MinScale} ROUNDING_HALF_EVEN BigNumeric:nineteen (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:two)" -> false,
s"${MinScale} ROUNDING_UP BigNumeric:twentyEight (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> false,
s"${MinScale} ROUNDING_DOWN BigNumeric:twentyEight (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> true,
s"${MinScale} ROUNDING_CEILING BigNumeric:twentyEight (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> false,
s"${MinScale} ROUNDING_FLOOR BigNumeric:twentyEight (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> true,
s"${MinScale} ROUNDING_HALF_UP BigNumeric:twentyEight (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> true,
s"${MinScale} ROUNDING_HALF_DOWN BigNumeric:twentyEight (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> true,
s"${MinScale} ROUNDING_HALF_EVEN BigNumeric:twentyEight (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> true,
s"${MinScale} ROUNDING_UP BigNumeric:twentyNine (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> false,
s"${MinScale} ROUNDING_DOWN BigNumeric:twentyNine (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> true,
s"${MinScale} ROUNDING_CEILING BigNumeric:twentyNine (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> false,
s"${MinScale} ROUNDING_FLOOR BigNumeric:twentyNine (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> true,
s"${MinScale} ROUNDING_HALF_UP BigNumeric:twentyNine (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> false,
s"${MinScale} ROUNDING_HALF_DOWN BigNumeric:twentyNine (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> false,
s"${MinScale} ROUNDING_HALF_EVEN BigNumeric:twentyNine (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> false,
s"${MinScale} ROUNDING_UP BigNumeric:nineteen (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:minusTwo)" -> false,
s"${MinScale} ROUNDING_DOWN BigNumeric:nineteen (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:minusTwo)" -> true,
s"${MinScale} ROUNDING_CEILING BigNumeric:nineteen (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:minusTwo)" -> true,
s"${MinScale} ROUNDING_FLOOR BigNumeric:nineteen (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:minusTwo)" -> false,
s"${MinScale} ROUNDING_HALF_UP BigNumeric:nineteen (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:minusTwo)" -> false,
s"${MinScale} ROUNDING_HALF_DOWN BigNumeric:nineteen (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:minusTwo)" -> true,
s"${MinScale} ROUNDING_HALF_EVEN BigNumeric:nineteen (SHIFT_BIGNUMERIC ${-MinScale} BigNumeric:minusTwo)" -> false,
s"-1000 ROUNDING_DOWN (SHIFT_RIGHT_BIGNUMERIC ${MinScale / 2} BigNumeric:one) (SHIFT_RIGHT_BIGNUMERIC ${-(MinScale / 2 - 1)} BigNumeric:one)" -> true,
s"-1000 ROUNDING_DOWN (SHIFT_RIGHT_BIGNUMERIC ${MinScale / 2 - 1} BigNumeric:one) (SHIFT_RIGHT_BIGNUMERIC ${-(MinScale / 2 - 1)} BigNumeric:one)" -> false,
s"-1000 ROUNDING_DOWN (SHIFT_RIGHT_BIGNUMERIC ${MinScale} BigNumeric:one) BigNumeric:one" -> true,
s"-1000 ROUNDING_DOWN (SHIFT_RIGHT_BIGNUMERIC ${MinScale} BigNumeric:one) (SHIFT_RIGHT_BIGNUMERIC 1 BigNumeric:one)" -> false,
s"-1000 ROUNDING_DOWN (SHIFT_RIGHT_BIGNUMERIC ${MinScale / 2 - 1} BigNumeric:underSqrtOfTen) (SHIFT_RIGHT_BIGNUMERIC ${-(MinScale / 2 - 1)} BigNumeric:overSqrtOfTen)" -> true,
s"-1000 ROUNDING_DOWN (SHIFT_RIGHT_BIGNUMERIC ${MinScale / 2 - 1} BigNumeric:overSqrtOfTen) (SHIFT_RIGHT_BIGNUMERIC ${-(MinScale / 2 - 1)} BigNumeric:overSqrtOfTen)" -> false,
s"${MinScale} ROUNDING_UP BigNumeric:nineteen (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:two)" -> false,
s"${MinScale} ROUNDING_DOWN BigNumeric:nineteen (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:two)" -> true,
s"${MinScale} ROUNDING_CEILING BigNumeric:nineteen (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:two)" -> false,
s"${MinScale} ROUNDING_FLOOR BigNumeric:nineteen (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:two)" -> true,
s"${MinScale} ROUNDING_HALF_UP BigNumeric:nineteen (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:two)" -> false,
s"${MinScale} ROUNDING_HALF_DOWN BigNumeric:nineteen (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:two)" -> true,
s"${MinScale} ROUNDING_HALF_EVEN BigNumeric:nineteen (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:two)" -> false,
s"${MinScale} ROUNDING_UP BigNumeric:twentyEight (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> false,
s"${MinScale} ROUNDING_DOWN BigNumeric:twentyEight (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> true,
s"${MinScale} ROUNDING_CEILING BigNumeric:twentyEight (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> false,
s"${MinScale} ROUNDING_FLOOR BigNumeric:twentyEight (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> true,
s"${MinScale} ROUNDING_HALF_UP BigNumeric:twentyEight (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> true,
s"${MinScale} ROUNDING_HALF_DOWN BigNumeric:twentyEight (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> true,
s"${MinScale} ROUNDING_HALF_EVEN BigNumeric:twentyEight (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> true,
s"${MinScale} ROUNDING_UP BigNumeric:twentyNine (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> false,
s"${MinScale} ROUNDING_DOWN BigNumeric:twentyNine (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> true,
s"${MinScale} ROUNDING_CEILING BigNumeric:twentyNine (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> false,
s"${MinScale} ROUNDING_FLOOR BigNumeric:twentyNine (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> true,
s"${MinScale} ROUNDING_HALF_UP BigNumeric:twentyNine (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> false,
s"${MinScale} ROUNDING_HALF_DOWN BigNumeric:twentyNine (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> false,
s"${MinScale} ROUNDING_HALF_EVEN BigNumeric:twentyNine (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:three)" -> false,
s"${MinScale} ROUNDING_UP BigNumeric:nineteen (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:minusTwo)" -> false,
s"${MinScale} ROUNDING_DOWN BigNumeric:nineteen (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:minusTwo)" -> true,
s"${MinScale} ROUNDING_CEILING BigNumeric:nineteen (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:minusTwo)" -> true,
s"${MinScale} ROUNDING_FLOOR BigNumeric:nineteen (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:minusTwo)" -> false,
s"${MinScale} ROUNDING_HALF_UP BigNumeric:nineteen (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:minusTwo)" -> false,
s"${MinScale} ROUNDING_HALF_DOWN BigNumeric:nineteen (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:minusTwo)" -> true,
s"${MinScale} ROUNDING_HALF_EVEN BigNumeric:nineteen (SHIFT_RIGHT_BIGNUMERIC ${-MinScale} BigNumeric:minusTwo)" -> false,
)
forEvery(testCases)((args, success) =>
eval(e"DIV_BIGNUMERIC $args") shouldBe (if (success) a[Right[_, _]] else a[Left[_, _]])
@ -264,7 +264,7 @@ class SBuiltinBigNumericTest extends AnyFreeSpec with Matchers with TableDrivenP
}
"SHIFT_BIGNUMERIC" - {
"SHIFT_RIGHT_BIGNUMERIC" - {
import java.math.BigDecimal
import SBigNumeric.assertFromBigDecimal
@ -282,7 +282,7 @@ class SBuiltinBigNumericTest extends AnyFreeSpec with Matchers with TableDrivenP
)
forEvery(testCases) { (inputScale, shifting, input, output) =>
eval(
e"SHIFT_BIGNUMERIC $shifting (TO_BIGNUMERIC_NUMERIC @$inputScale $input)"
e"SHIFT_RIGHT_BIGNUMERIC $shifting (TO_BIGNUMERIC_NUMERIC @$inputScale $input)"
) shouldBe Right(assertFromBigDecimal(new BigDecimal(output)))
}
}
@ -290,7 +290,6 @@ class SBuiltinBigNumericTest extends AnyFreeSpec with Matchers with TableDrivenP
"throws an exception in case of underflow/overflow" in {
val testCases = Table(
"arguments" -> "success",
"0 BigNumeric:maxPositive" -> true,
"1 BigNumeric:maxPositive" -> false,
"-1 BigNumeric:maxPositive" -> false,
s"${MaxScale} BigNumeric:one" -> true,
@ -300,9 +299,31 @@ class SBuiltinBigNumericTest extends AnyFreeSpec with Matchers with TableDrivenP
)
forEvery(testCases)((args, success) =>
eval(e"SHIFT_BIGNUMERIC $args") shouldBe (if (success) a[Right[_, _]] else a[Left[_, _]])
eval(e"SHIFT_RIGHT_BIGNUMERIC $args") shouldBe (if (success) a[Right[_, _]]
else a[Left[_, _]])
)
}
"never throw an exception when trying to shifting 0" in {
val testCases = Table(
"argument",
Long.MinValue,
Int.MinValue.toLong,
MinScale.toLong - 1,
MinScale.toLong,
-1L,
0L,
1L,
MaxScale.toLong,
MaxScale.toLong + 1,
Int.MaxValue.toLong,
Long.MaxValue,
)
forEvery(testCases)(arg =>
eval(e"SHIFT_RIGHT_BIGNUMERIC $arg BigNumeric:zero") shouldBe Right(SBigNumeric.Zero)
)
}
}
}
@ -335,19 +356,19 @@ object SBuiltinBigNumericTest {
val twentyNine: BigNumeric =
TO_BIGNUMERIC_NUMERIC @0 29.;
val minPositive: BigNumeric =
SHIFT_BIGNUMERIC BigNumeric:maxScale BigNumeric:one;
SHIFT_RIGHT_BIGNUMERIC BigNumeric:maxScale BigNumeric:one;
val maxPositive: BigNumeric =
let x: BigNumeric = SUB_BIGNUMERIC BigNumeric:one BigNumeric:minPositive in
ADD_BIGNUMERIC x (SHIFT_BIGNUMERIC (SUB_INT64 0 BigNumeric:maxScale) x);
ADD_BIGNUMERIC x (SHIFT_RIGHT_BIGNUMERIC (SUB_INT64 0 BigNumeric:maxScale) x);
val maxNegative: BigNumeric =
SHIFT_BIGNUMERIC BigNumeric:maxScale BigNumeric:minusOne;
SHIFT_RIGHT_BIGNUMERIC BigNumeric:maxScale BigNumeric:minusOne;
val minNegative: BigNumeric =
let x: BigNumeric = ADD_BIGNUMERIC BigNumeric:minusOne BigNumeric:minPositive in
ADD_BIGNUMERIC x (SHIFT_BIGNUMERIC (SUB_INT64 0 BigNumeric:maxScale) x);
ADD_BIGNUMERIC x (SHIFT_RIGHT_BIGNUMERIC (SUB_INT64 0 BigNumeric:maxScale) x);
val tenPower: Int64 -> BigNumeric = \(n: Int64) ->
SHIFT_BIGNUMERIC (SUB_INT64 0 n) BigNumeric:one;
val x: BigNumeric = SHIFT_BIGNUMERIC ${SValue.SBigNumeric.MinScale} (TO_BIGNUMERIC_NUMERIC @0 5.);
SHIFT_RIGHT_BIGNUMERIC (SUB_INT64 0 n) BigNumeric:one;
val x: BigNumeric = SHIFT_RIGHT_BIGNUMERIC ${SValue.SBigNumeric.MinScale} (TO_BIGNUMERIC_NUMERIC @0 5.);
val almostX: BigNumeric = SUB_BIGNUMERIC BigNumeric:x BigNumeric:minPositive;
val minusX: BigNumeric = SUB_BIGNUMERIC BigNumeric:zero BigNumeric:x;
}

View File

@ -453,7 +453,8 @@ object Ast {
final case object BMulBigNumeric extends BuiltinFunction // : BigNumeric BigNumeric BigNumeric
final case object BDivBigNumeric
extends BuiltinFunction // : Int64 -> RoundingMode BigNumeric BigNumeric BigNumeric s
final case object BShiftBigNumeric extends BuiltinFunction // : Int64 BigNumeric BigNumeric
final case object BShiftRightBigNumeric
extends BuiltinFunction // : Int64 BigNumeric BigNumeric
final case object BToNumericBigNumeric extends BuiltinFunction // : s. BigNumeric Numeric s
final case object BToBigNumericNumeric extends BuiltinFunction // : s. Numeric s BigNumeric
final case object BToTextBigNumeric extends BuiltinFunction // : BigNumeric Text

View File

@ -319,7 +319,7 @@ private[parser] class ExprParser[P](parserParameters: ParserParameters[P]) {
"SUB_BIGNUMERIC" -> BSubBigNumeric,
"MUL_BIGNUMERIC" -> BMulBigNumeric,
"DIV_BIGNUMERIC" -> BDivBigNumeric,
"SHIFT_BIGNUMERIC" -> BShiftBigNumeric,
"SHIFT_RIGHT_BIGNUMERIC" -> BShiftRightBigNumeric,
"TO_NUMERIC_BIGNUMERIC" -> BToNumericBigNumeric,
"TO_BIGNUMERIC_NUMERIC" -> BToBigNumericNumeric,
"TO_TEXT_BIGNUMERIC" -> BToTextBigNumeric,

View File

@ -3842,6 +3842,14 @@ BigNumeric functions
[*Available in version ≥ 1.13*]
* ``SHIFT_RIGHT_BIGNUMERIC : 'Int64' → 'BigNumeric' → 'BigNumeric'``
Multiply the second argument by 10 to the negative power of the first
argument. Throws an ``ArithmeticError`` in case the result cannot be
represented without loss of precision.
[*Available in version ≥ 1.13*]
* ``TO_TEXT_BIGNUMERIC : 'BigNumeric' → 'Text'``
Returns the numeric string representation of the BigNumeric. The

View File

@ -230,7 +230,7 @@ private[validation] object Typing {
BSubBigNumeric -> (TBigNumeric ->: TBigNumeric ->: TBigNumeric),
BMulBigNumeric -> (TBigNumeric ->: TBigNumeric ->: TBigNumeric),
BDivBigNumeric -> (TInt64 ->: TRoundingMode ->: TBigNumeric ->: TBigNumeric ->: TBigNumeric),
BShiftBigNumeric -> (TInt64 ->: TBigNumeric ->: TBigNumeric),
BShiftRightBigNumeric -> (TInt64 ->: TBigNumeric ->: TBigNumeric),
BToNumericBigNumeric -> TForall(alpha.name -> KNat, TBigNumeric ->: TNumeric(alpha)),
BToBigNumericNumeric -> TForall(alpha.name -> KNat, TNumeric(alpha) ->: TBigNumeric),
BToTextBigNumeric -> (TBigNumeric ->: TText),