diff options
author | James Wahlin <james@mongodb.com> | 2019-02-14 16:12:50 -0500 |
---|---|---|
committer | James Wahlin <james@mongodb.com> | 2019-03-18 08:25:24 -0400 |
commit | 78ea71891f577b11a3129557948bed6c39692ae3 (patch) | |
tree | 9588ca4919486bb5a9497e19725044dd4bf5c6b3 | |
parent | bc40d082118c20c1f507599d1aaccbb5ce6f4037 (diff) | |
download | mongo-78ea71891f577b11a3129557948bed6c39692ae3.tar.gz |
SERVER-39487 Decimal128::squareRoot() returns result for Decimal128::exponential()
(cherry picked from commit 5aa3f6dbc5e31beaf40e0828f7a24ecf71fb42f9)
(cherry picked from commit c1760b39b29dc412ca1c20361c500e18e90c71cd)
(cherry picked from commit 477ceade3dae70498c0a6b4c89007ac98934e1c6)
-rw-r--r-- | src/mongo/db/pipeline/expression_test.cpp | 88 | ||||
-rw-r--r-- | src/mongo/platform/decimal128.cpp | 6 | ||||
-rw-r--r-- | src/mongo/platform/decimal128_test.cpp | 32 |
3 files changed, 123 insertions, 3 deletions
diff --git a/src/mongo/db/pipeline/expression_test.cpp b/src/mongo/db/pipeline/expression_test.cpp index b6a6b75d966..e4cb167401d 100644 --- a/src/mongo/db/pipeline/expression_test.cpp +++ b/src/mongo/db/pipeline/expression_test.cpp @@ -955,6 +955,94 @@ TEST_F(ExpressionTruncTest, NullArg) { assertEvaluates(Value(BSONNULL), Value(BSONNULL)); } +/* ------------------------- ExpressionSqrt -------------------------- */ + +class ExpressionSqrtTest : public ExpressionNaryTestOneArg { +public: + virtual void assertEvaluates(Value input, Value output) override { + intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + _expr = new ExpressionSqrt(expCtx); + ExpressionNaryTestOneArg::assertEvaluates(input, output); + } +}; + +TEST_F(ExpressionSqrtTest, SqrtIntArg) { + assertEvaluates(Value(0), Value(0.0)); + assertEvaluates(Value(1), Value(1.0)); + assertEvaluates(Value(25), Value(5.0)); +} + +TEST_F(ExpressionSqrtTest, SqrtLongArg) { + assertEvaluates(Value(0LL), Value(0.0)); + assertEvaluates(Value(1LL), Value(1.0)); + assertEvaluates(Value(25LL), Value(5.0)); + assertEvaluates(Value(40000000000LL), Value(200000.0)); +} + +TEST_F(ExpressionSqrtTest, SqrtDoubleArg) { + assertEvaluates(Value(0.0), Value(0.0)); + assertEvaluates(Value(1.0), Value(1.0)); + assertEvaluates(Value(25.0), Value(5.0)); +} + +TEST_F(ExpressionSqrtTest, SqrtDecimalArg) { + assertEvaluates(Value(Decimal128("0")), Value(Decimal128("0"))); + assertEvaluates(Value(Decimal128("1")), Value(Decimal128("1"))); + assertEvaluates(Value(Decimal128("25")), Value(Decimal128("5"))); + assertEvaluates(Value(Decimal128("30.25")), Value(Decimal128("5.5"))); +} + +TEST_F(ExpressionSqrtTest, SqrtNullArg) { + assertEvaluates(Value(BSONNULL), Value(BSONNULL)); +} + +TEST_F(ExpressionSqrtTest, SqrtNaNArg) { + assertEvaluates(Value(std::numeric_limits<double>::quiet_NaN()), + Value(std::numeric_limits<double>::quiet_NaN())); +} + +/* ------------------------- ExpressionExp -------------------------- */ + +class ExpressionExpTest : public ExpressionNaryTestOneArg { +public: + virtual void assertEvaluates(Value input, Value output) override { + intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + _expr = new ExpressionExp(expCtx); + ExpressionNaryTestOneArg::assertEvaluates(input, output); + } + + const Decimal128 decimalE = Decimal128("2.718281828459045235360287471352662"); +}; + +TEST_F(ExpressionExpTest, ExpIntArg) { + assertEvaluates(Value(0), Value(1.0)); + assertEvaluates(Value(1), Value(exp(1.0))); +} + +TEST_F(ExpressionExpTest, ExpLongArg) { + assertEvaluates(Value(0LL), Value(1.0)); + assertEvaluates(Value(1LL), Value(exp(1.0))); +} + +TEST_F(ExpressionExpTest, ExpDoubleArg) { + assertEvaluates(Value(0.0), Value(1.0)); + assertEvaluates(Value(1.0), Value(exp(1.0))); +} + +TEST_F(ExpressionExpTest, ExpDecimalArg) { + assertEvaluates(Value(Decimal128("0")), Value(Decimal128("1"))); + assertEvaluates(Value(Decimal128("1")), Value(decimalE)); +} + +TEST_F(ExpressionExpTest, ExpNullArg) { + assertEvaluates(Value(BSONNULL), Value(BSONNULL)); +} + +TEST_F(ExpressionExpTest, ExpNaNArg) { + assertEvaluates(Value(std::numeric_limits<double>::quiet_NaN()), + Value(std::numeric_limits<double>::quiet_NaN())); +} + /* ------------------------- Old-style tests -------------------------- */ namespace Add { diff --git a/src/mongo/platform/decimal128.cpp b/src/mongo/platform/decimal128.cpp index 6d48fa18d19..c68aa7ca167 100644 --- a/src/mongo/platform/decimal128.cpp +++ b/src/mongo/platform/decimal128.cpp @@ -623,7 +623,7 @@ Decimal128 Decimal128::divide(const Decimal128& other, Decimal128 Decimal128::exponential(RoundingMode roundMode) const { std::uint32_t throwAwayFlag = 0; - return exponential(&throwAwayFlag); + return exponential(&throwAwayFlag, roundMode); } Decimal128 Decimal128::exponential(std::uint32_t* signalingFlags, RoundingMode roundMode) const { @@ -634,7 +634,7 @@ Decimal128 Decimal128::exponential(std::uint32_t* signalingFlags, RoundingMode r Decimal128 Decimal128::logarithm(RoundingMode roundMode) const { std::uint32_t throwAwayFlag = 0; - return logarithm(&throwAwayFlag); + return logarithm(&throwAwayFlag, roundMode); } Decimal128 Decimal128::logarithm(std::uint32_t* signalingFlags, RoundingMode roundMode) const { @@ -716,7 +716,7 @@ Decimal128 Decimal128::quantize(const Decimal128& reference, Decimal128 Decimal128::squareRoot(RoundingMode roundMode) const { std::uint32_t throwAwayFlag = 0; - return exponential(&throwAwayFlag); + return squareRoot(&throwAwayFlag, roundMode); } Decimal128 Decimal128::squareRoot(std::uint32_t* signalingFlags, RoundingMode roundMode) const { diff --git a/src/mongo/platform/decimal128_test.cpp b/src/mongo/platform/decimal128_test.cpp index eea0480780e..3d7174d4586 100644 --- a/src/mongo/platform/decimal128_test.cpp +++ b/src/mongo/platform/decimal128_test.cpp @@ -1289,4 +1289,36 @@ TEST(Decimal128Test, TestDecimal128GetLargestNegativeExponentZero) { ASSERT_EQUALS(d.getValue().low64, largestNegativeExponentZeroLow64); } +/** + * Test data was generated using 64 bit versions of these functions, so we must test + * approximate results. + */ + +void assertDecimal128ApproxEqual(Decimal128 x, Decimal128 y) { + ASSERT_TRUE(x.subtract(y).toAbs().isLess(Decimal128("0.00000005"))); +} + +TEST(Decimal128Test, TestExp) { + assertDecimal128ApproxEqual(Decimal128("-1").exponential(), + Decimal128("0.3678794411714423215955237701614609")); + assertDecimal128ApproxEqual(Decimal128("0").exponential(), Decimal128("1")); + assertDecimal128ApproxEqual(Decimal128("1").exponential(), + Decimal128("2.718281828459045235360287471352662")); + assertDecimal128ApproxEqual(Decimal128("1.5").exponential(), + Decimal128("4.481689070338064822602055460119276")); + assertDecimal128ApproxEqual(Decimal128("1.79769313486231E+308") + .exponential(Decimal128::RoundingMode::kRoundTowardNegative), + Decimal128("9.999999999999999999999999999999999E+6144")); +} + +TEST(Decimal128Test, TestSqrt) { + assertDecimal128ApproxEqual(Decimal128("0").squareRoot(), Decimal128("0")); + assertDecimal128ApproxEqual(Decimal128("1").squareRoot(), Decimal128("1")); + assertDecimal128ApproxEqual(Decimal128("25").squareRoot(), Decimal128("5")); + assertDecimal128ApproxEqual(Decimal128("25.5").squareRoot(), + Decimal128("5.049752469181038976681692958534800")); + assertDecimal128ApproxEqual(Decimal128("1.79769313486231E+308") + .squareRoot(Decimal128::RoundingMode::kRoundTowardNegative), + Decimal128("1.340780792994257506864497209340836E+154")); +} } // namespace mongo |