diff options
author | Patrick Meredith <pmeredit@gmail.com> | 2018-10-22 17:01:46 -0400 |
---|---|---|
committer | Charlie Swanson <charlie.swanson@mongodb.com> | 2019-02-14 17:54:56 -0500 |
commit | 814b1f8237db9ecb27dd0ffa96f11edd58bac73e (patch) | |
tree | 4e13cadda4f9dc3ea4f4d7156476f31c77ba9726 /src/mongo/platform/decimal128.cpp | |
parent | f1da8170c1c568762b29e44910afbcc6f01a644f (diff) | |
download | mongo-814b1f8237db9ecb27dd0ffa96f11edd58bac73e.tar.gz |
SERVER-15926: Implement $round function and allow a precision argument for $trunc
Closes #1297
Signed-off-by: Charlie Swanson <charlie.swanson@mongodb.com>
Diffstat (limited to 'src/mongo/platform/decimal128.cpp')
-rw-r--r-- | src/mongo/platform/decimal128.cpp | 42 |
1 files changed, 32 insertions, 10 deletions
diff --git a/src/mongo/platform/decimal128.cpp b/src/mongo/platform/decimal128.cpp index 23b2fc0ff56..9df4185db99 100644 --- a/src/mongo/platform/decimal128.cpp +++ b/src/mongo/platform/decimal128.cpp @@ -275,7 +275,7 @@ Decimal128::Decimal128(double doubleValue, base10Exp--; Decimal128 Q(0, base10Exp - 14 + Decimal128::kExponentBias, 0, 1); - *this = convertedDoubleValue.quantize(Q, roundMode); + *this = convertedDoubleValue.nonNormalizingQuantize(Q, roundMode); // Check if the quantization was done correctly: _value stores exactly 15 // decimal digits of precision (15 digits can fit into the low 64 bits of the decimal) @@ -285,7 +285,7 @@ Decimal128::Decimal128(double doubleValue, // If we didn't precisely get 15 digits of precision, the original base 10 exponent // guess was 1 off, so quantize once more with base10Exp + 1 Q = Decimal128(0, base10Exp - 13 + Decimal128::kExponentBias, 0, 1); - *this = convertedDoubleValue.quantize(Q, roundMode); + *this = convertedDoubleValue.nonNormalizingQuantize(Q, roundMode); } // The decimal must have exactly 15 digits of precision @@ -848,14 +848,15 @@ Decimal128 Decimal128::power(const Decimal128& other, return Decimal128{libraryTypeToValue(result)}.add(kLargestNegativeExponentZero); } -Decimal128 Decimal128::quantize(const Decimal128& other, RoundingMode roundMode) const { +Decimal128 Decimal128::nonNormalizingQuantize(const Decimal128& other, + RoundingMode roundMode) const { std::uint32_t throwAwayFlag = 0; - return quantize(other, &throwAwayFlag, roundMode); + return nonNormalizingQuantize(other, &throwAwayFlag, roundMode); } -Decimal128 Decimal128::quantize(const Decimal128& reference, - std::uint32_t* signalingFlags, - RoundingMode roundMode) const { +Decimal128 Decimal128::nonNormalizingQuantize(const Decimal128& reference, + std::uint32_t* signalingFlags, + RoundingMode roundMode) const { BID_UINT128 current = decimal128ToLibraryType(_value); BID_UINT128 q = decimal128ToLibraryType(reference.getValue()); BID_UINT128 quantizedResult = bid128_quantize(current, q, roundMode, signalingFlags); @@ -864,6 +865,26 @@ Decimal128 Decimal128::quantize(const Decimal128& reference, return result; } +Decimal128 Decimal128::quantize(const Decimal128& other, RoundingMode roundMode) const { + std::uint32_t throwAwayFlag = 0; + return quantize(other, &throwAwayFlag, roundMode); +} + +Decimal128 Decimal128::quantize(const Decimal128& reference, + std::uint32_t* signalingFlags, + RoundingMode roundMode) const { + + auto normalizedThis = this->normalize(); + auto normalizedReferenceExponent = + static_cast<int32_t>(reference.normalize().getBiasedExponent()); + if (normalizedReferenceExponent != 0 && + (static_cast<int32_t>(normalizedThis.getBiasedExponent()) - normalizedReferenceExponent) > + 33) { + return normalizedThis; + } + return nonNormalizingQuantize(reference, signalingFlags, roundMode); +} + Decimal128 Decimal128::squareRoot(RoundingMode roundMode) const { std::uint32_t throwAwayFlag = 0; return exponential(&throwAwayFlag); @@ -958,9 +979,6 @@ const Decimal128 Decimal128::kSmallestNegative(1, 0, 0, 1); const Decimal128 Decimal128::kNormalizedZero(Decimal128::Value( {0, static_cast<uint64_t>(Decimal128::kExponentBias) << Decimal128::kExponentFieldPos})); -// Get the representation of 0 with the most negative exponent -const Decimal128 Decimal128::kLargestNegativeExponentZero(Decimal128::Value({0ull, 0ull})); - // Shift the format of the combination bits to the right position to get Inf and NaN // +Inf = 0111 1000 ... ... = 0x78 ... ..., -Inf = 1111 1000 ... ... = 0xf8 ... ... // +NaN = 0111 1100 ... ... = 0x7c ... ..., -NaN = 1111 1100 ... ... = 0xfc ... ... @@ -969,10 +987,14 @@ const Decimal128 Decimal128::kNegativeInfinity(Decimal128::Value({0ull, 0xf8ull const Decimal128 Decimal128::kPositiveNaN(Decimal128::Value({0ull, 0x7cull << 56})); const Decimal128 Decimal128::kNegativeNaN(Decimal128::Value({0ull, 0xfcull << 56})); +// Get the representation of 0 with the most negative exponent +const Decimal128 Decimal128::kLargestNegativeExponentZero(Decimal128::Value({0ull, 0ull})); + const Decimal128 Decimal128::kPi("3.14159265358979323846264338327950288419716939937510"); const Decimal128 Decimal128::kPiOver180(Decimal128::kPi.divide(Decimal128("180"))); const Decimal128 Decimal128::k180OverPi(Decimal128("180").divide(Decimal128::kPi)); + std::ostream& operator<<(std::ostream& stream, const Decimal128& value) { return stream << value.toString(); } |