summaryrefslogtreecommitdiff
path: root/src/mongo/platform
diff options
context:
space:
mode:
authorBilly Donahue <billy.donahue@mongodb.com>2019-05-31 16:54:58 -0400
committerBilly Donahue <billy.donahue@mongodb.com>2019-06-28 15:39:18 -0400
commitabe43b7aaddd8254c51eb2c8bfce99b9e11f8fee (patch)
tree3979d508426860d4f4d939f1bab66a51860a1b0c /src/mongo/platform
parent6e43dbc29112a7d7edce91cb89ec0d396463601e (diff)
downloadmongo-abe43b7aaddd8254c51eb2c8bfce99b9e11f8fee.tar.gz
SERVER-41425 operator"" _dec128 for Decimal128 literals
Also add unary operator+, operator-.
Diffstat (limited to 'src/mongo/platform')
-rw-r--r--src/mongo/platform/decimal128.h24
-rw-r--r--src/mongo/platform/decimal128_test.cpp87
2 files changed, 72 insertions, 39 deletions
diff --git a/src/mongo/platform/decimal128.h b/src/mongo/platform/decimal128.h
index e6876609336..c2f0149a73e 100644
--- a/src/mongo/platform/decimal128.h
+++ b/src/mongo/platform/decimal128.h
@@ -30,6 +30,7 @@
#pragma once
#include <array>
+#include <climits>
#include <cstdint>
#include <iostream>
#include <string>
@@ -342,12 +343,10 @@ public:
/**
* Returns `this` with inverted sign bit
*/
- Decimal128 negate() const {
- Value negated = {_value.low64, _value.high64 ^ (1ULL << 63)};
- return Decimal128(negated);
+ constexpr Decimal128 negate() const {
+ return Decimal128(Value{_value.low64, _value.high64 ^ (std::uint64_t{1} << 63)});
}
-
/**
* This set of functions converts a Decimal128 to a certain integer type with a
* given rounding mode.
@@ -528,6 +527,14 @@ public:
return _value.high64 == other._value.high64 && _value.low64 == other._value.low64;
}
+ constexpr Decimal128 operator-() const {
+ return negate();
+ }
+
+ constexpr Decimal128 operator+() const {
+ return *this;
+ }
+
private:
constexpr static std::uint8_t kSignFieldPos = 64 - 1;
constexpr static std::uint8_t kCombinationFieldPos = kSignFieldPos - 17;
@@ -589,4 +596,13 @@ private:
Value _value;
};
+
+inline Decimal128 operator"" _dec128(const char* s) {
+ return Decimal128(s);
+}
+
+inline Decimal128 operator"" _dec128(const char* s, std::size_t len) {
+ return Decimal128(std::string(s, len));
+}
+
} // namespace mongo
diff --git a/src/mongo/platform/decimal128_test.cpp b/src/mongo/platform/decimal128_test.cpp
index 10029756fbb..c865969b44c 100644
--- a/src/mongo/platform/decimal128_test.cpp
+++ b/src/mongo/platform/decimal128_test.cpp
@@ -293,6 +293,24 @@ TEST(Decimal128Test, TestStringConstructorNaN) {
ASSERT_EQUALS(val.low64, lowBytes);
}
+TEST(Decimal128Test, TestLiteral) {
+#define ASSERT_LITERAL128(x) ASSERT_TRUE((x##_dec128).isBinaryEqual(Decimal128(#x)))
+ ASSERT_LITERAL128(5);
+ ASSERT_LITERAL128(-5);
+ ASSERT_LITERAL128(5.5);
+ ASSERT_LITERAL128(-5.5);
+ ASSERT_LITERAL128(5.1);
+ ASSERT_LITERAL128(-5.1);
+ ASSERT_LITERAL128(5.5E10);
+ ASSERT_LITERAL128(5.5E+10);
+ ASSERT_LITERAL128(5.5E-10);
+ ASSERT_LITERAL128(123456789012345678901234567890); // 30 digits (100 bits)
+ ASSERT_LITERAL128(-123456789012345678901234567890);
+ ASSERT_LITERAL128(+123456789012345678901234567890);
+#undef ASSERT_LITERAL128
+ 12345_dec128;
+}
+
TEST(Decimal128Test, TestNonCanonicalDecimal) {
// It is possible to encode a significand with more than 34 decimal digits.
// Conforming implementations should not generate these, but they must be treated as zero
@@ -324,8 +342,8 @@ TEST(Decimal128Test, TestNonCanonicalDecimal) {
const double minusZeroDouble = nonCanonicalM0E0.toDouble();
ASSERT_EQUALS(minusZeroDouble, 0.0);
ASSERT_EQUALS(-1.0, std::copysign(1.0, minusZeroDouble));
- ASSERT_TRUE(nonCanonical0E3.add(Decimal128(1)).isEqual(Decimal128(1)));
- ASSERT_TRUE(Decimal128(1).divide(nonCanonicalM0E0).isEqual(Decimal128::kNegativeInfinity));
+ ASSERT_TRUE(nonCanonical0E3.add(1_dec128).isEqual(1_dec128));
+ ASSERT_TRUE((1_dec128).divide(nonCanonicalM0E0).isEqual(Decimal128::kNegativeInfinity));
}
// Tests for absolute value function
@@ -414,33 +432,37 @@ TEST(Decimal128Test, TestDecimal128ToInt64Even) {
TEST(Decimal128Test, TestDecimal128ToInt64Neg) {
Decimal128::RoundingMode roundMode = Decimal128::RoundingMode::kRoundTowardNegative;
- std::string in[6] = {"-4294967296.7",
- "-4294967296.5",
- "-4294967296.2",
- "4294967296.2",
- "4294967296.5",
- "4294967296.7"};
- int64_t out[6] = {-4294967297, -4294967297, -4294967297, 4294967296, 4294967296, 4294967296};
- std::unique_ptr<Decimal128> decPtr;
- for (int testNo = 0; testNo < 6; ++testNo) {
- decPtr = std::make_unique<Decimal128>(in[testNo]);
- ASSERT_EQUALS(decPtr->toLong(roundMode), out[testNo]);
+ struct {
+ Decimal128 in;
+ int64_t out;
+ } const specs[] = {
+ {-4294967296.7_dec128, -4294967297},
+ {-4294967296.5_dec128, -4294967297},
+ {-4294967296.2_dec128, -4294967297},
+ {4294967296.2_dec128, 4294967296},
+ {4294967296.5_dec128, 4294967296},
+ {4294967296.7_dec128, 4294967296},
+ };
+ for (const auto& spec : specs) {
+ ASSERT_EQUALS(spec.in.toLong(roundMode), spec.out);
}
}
TEST(Decimal128Test, TestDecimal128ToInt64Pos) {
Decimal128::RoundingMode roundMode = Decimal128::RoundingMode::kRoundTowardPositive;
- std::string in[6] = {"-4294967296.7",
- "-4294967296.5",
- "-4294967296.2",
- "4294967296.2",
- "4294967296.5",
- "4294967296.7"};
- int64_t out[6] = {-4294967296, -4294967296, -4294967296, 4294967297, 4294967297, 4294967297};
- std::unique_ptr<Decimal128> decPtr;
- for (int testNo = 0; testNo < 6; ++testNo) {
- decPtr = std::make_unique<Decimal128>(in[testNo]);
- ASSERT_EQUALS(decPtr->toLong(roundMode), out[testNo]);
+ struct {
+ Decimal128 in;
+ int64_t out;
+ } const specs[] = {
+ {-4294967296.7_dec128, -4294967296},
+ {-4294967296.5_dec128, -4294967296},
+ {-4294967296.2_dec128, -4294967296},
+ {4294967296.2_dec128, 4294967297},
+ {4294967296.5_dec128, 4294967297},
+ {4294967296.7_dec128, 4294967297},
+ };
+ for (const auto& spec : specs) {
+ ASSERT_EQUALS(spec.in.toLong(roundMode), spec.out);
}
}
@@ -938,23 +960,21 @@ TEST(Decimal128Test, TestDecimal128AddSignaling) {
TEST(Decimal128Test, TestDecimal128SubtractSignaling) {
Decimal128 d = Decimal128::kLargestNegative;
uint32_t sigFlags = Decimal128::SignalingFlag::kNoFlag;
- Decimal128 res = d.subtract(Decimal128(1), &sigFlags);
+ Decimal128 res = d.subtract(1_dec128, &sigFlags);
ASSERT_TRUE(res.isEqual(Decimal128::kLargestNegative));
ASSERT_TRUE(Decimal128::hasFlag(sigFlags, Decimal128::SignalingFlag::kInexact));
}
TEST(Decimal128Test, TestDecimal128MultiplySignaling) {
- Decimal128 d("2");
uint32_t sigFlags = Decimal128::SignalingFlag::kNoFlag;
- Decimal128 res = d.multiply(Decimal128::kLargestPositive, &sigFlags);
+ Decimal128 res = (2_dec128).multiply(Decimal128::kLargestPositive, &sigFlags);
ASSERT_TRUE(res.isEqual(Decimal128::kPositiveInfinity));
ASSERT_TRUE(Decimal128::hasFlag(sigFlags, Decimal128::SignalingFlag::kOverflow));
}
TEST(Decimal128Test, TestDecimal128DivideSignaling) {
- Decimal128 d("2");
uint32_t sigFlags = Decimal128::SignalingFlag::kNoFlag;
- Decimal128 res = d.divide(Decimal128(0), &sigFlags);
+ Decimal128 res = (2_dec128).divide(0_dec128, &sigFlags);
ASSERT_TRUE(res.isEqual(Decimal128::kPositiveInfinity));
ASSERT_TRUE(Decimal128::hasFlag(sigFlags, Decimal128::SignalingFlag::kDivideByZero));
}
@@ -968,12 +988,9 @@ TEST(Decimal128Test, TestDecimal128IsZero) {
}
TEST(Decimal128Test, TestDecimal128IsNaN) {
- Decimal128 d1("NaN");
- Decimal128 d2("10.5");
- Decimal128 d3("Inf");
- ASSERT_TRUE(d1.isNaN());
- ASSERT_FALSE(d2.isNaN());
- ASSERT_FALSE(d3.isNaN());
+ ASSERT_TRUE("NaN"_dec128.isNaN());
+ ASSERT_FALSE("10.5"_dec128.isNaN());
+ ASSERT_FALSE("Inf"_dec128.isNaN());
}
TEST(Decimal128Test, TestDecimal128IsInfinite) {