/* Copyright 2014 MongoDB Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
* As a special exception, the copyright holders give permission to link the
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
* must comply with the GNU Affero General Public License in all respects
* for all of the code used other than as permitted herein. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you do not
* wish to do so, delete this exception statement from your version. If you
* delete this exception statement from all source files in the program,
* then also delete it in the license file.
*/
#include "mongo/platform/decimal128.h"
#include
#include
#include
#include
#include "mongo/config.h"
#include "mongo/stdx/memory.h"
#include "mongo/unittest/unittest.h"
namespace mongo {
// Tests for Decimal128 constructors
TEST(Decimal128Test, TestDefaultConstructor) {
Decimal128 d;
ASSERT_TRUE(d.isBinaryEqual(Decimal128(0)));
}
TEST(Decimal128Test, TestInt32ConstructorZero) {
int32_t intZero = 0;
Decimal128 d(intZero);
Decimal128::Value val = d.getValue();
// 0x3040000000000000 0000000000000000 = +0E+0
uint64_t highBytes = 0x3040000000000000ull;
uint64_t lowBytes = 0x0000000000000000ull;
ASSERT_EQUALS(val.high64, highBytes);
ASSERT_EQUALS(val.low64, lowBytes);
}
TEST(Decimal128Test, TestInt32ConstructorMax) {
int32_t intMax = std::numeric_limits::max();
Decimal128 d(intMax);
Decimal128::Value val = d.getValue();
// 0x3040000000000000 000000007fffffff = +2147483647E+0
uint64_t highBytes = 0x3040000000000000ull;
uint64_t lowBytes = 0x000000007fffffffull;
ASSERT_EQUALS(val.high64, highBytes);
ASSERT_EQUALS(val.low64, lowBytes);
}
TEST(Decimal128Test, TestInt32ConstructorMin) {
int32_t intMin = std::numeric_limits::lowest();
Decimal128 d(intMin);
Decimal128::Value val = d.getValue();
// 0xb040000000000000 000000007fffffff = -2147483648E+0
uint64_t highBytes = 0xb040000000000000ull;
uint64_t lowBytes = 0x0000000080000000ull;
ASSERT_EQUALS(val.high64, highBytes);
ASSERT_EQUALS(val.low64, lowBytes);
}
TEST(Decimal128Test, TestInt64ConstructorZero) {
int64_t longZero = 0;
Decimal128 d(longZero);
Decimal128::Value val = d.getValue();
// 0x3040000000000000 0000000000000000 = +0E+0
uint64_t highBytes = 0x3040000000000000ull;
uint64_t lowBytes = 0x0000000000000000ull;
ASSERT_EQUALS(val.high64, highBytes);
ASSERT_EQUALS(val.low64, lowBytes);
}
TEST(Decimal128Test, TestInt64ConstructorMax) {
int64_t longMax = std::numeric_limits::max();
Decimal128 d(longMax);
Decimal128::Value val = d.getValue();
// 0x3040000000000000 7fffffffffffffff = +9223372036854775807E+0
uint64_t highBytes = 0x3040000000000000ull;
uint64_t lowBytes = 0x7fffffffffffffffull;
ASSERT_EQUALS(val.high64, highBytes);
ASSERT_EQUALS(val.low64, lowBytes);
}
TEST(Decimal128Test, TestInt64ConstructorMin) {
int64_t longMin = std::numeric_limits::lowest();
Decimal128 d(longMin);
Decimal128::Value val = d.getValue();
// 0xb040000000000000 8000000000000000 = -9223372036854775808E+0
uint64_t highBytes = 0xb040000000000000;
uint64_t lowBytes = 0x8000000000000000;
ASSERT_EQUALS(val.high64, highBytes);
ASSERT_EQUALS(val.low64, lowBytes);
}
TEST(Decimal128Test, TestDoubleConstructorQuant1) {
double dbl = 0.1 / 10;
Decimal128 d(dbl);
ASSERT_EQUALS(d.toString(), "0.0100000000000000");
}
TEST(Decimal128Test, TestDoubleConstructorQuant2) {
double dbl = 0.1 / 10000;
Decimal128 d(dbl);
ASSERT_EQUALS(d.toString(), "0.0000100000000000000");
}
TEST(Decimal128Test, TestDoubleConstructorQuant3) {
double dbl = 0.1 / 1000 / 1000 / 1000 / 1000 / 1000 / 1000;
Decimal128 d(dbl);
ASSERT_EQUALS(d.toString(), "1.00000000000000E-19");
}
TEST(Decimal128Test, TestDoubleConstructorQuant4) {
double dbl = 0.01 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000;
Decimal128 d(dbl);
ASSERT_EQUALS(d.toString(), "1.00000000000000E+16");
}
TEST(Decimal128Test, TestDoubleConstructorQuant5) {
double dbl = 0.0127;
Decimal128 d(dbl);
ASSERT_EQUALS(d.toString(), "0.0127000000000000");
}
TEST(Decimal128Test, TestDoubleConstructorQuant6) {
double dbl = 1234567890.12709;
Decimal128 d(dbl);
ASSERT_EQUALS(d.toString(), "1234567890.12709");
}
TEST(Decimal128Test, TestDoubleConstructorQuant7) {
double dbl = 0.1129857 / 1000 / 1000 / 1000 / 1000 / 1000 / 1000;
Decimal128 d(dbl);
ASSERT_EQUALS(d.toString(), "1.12985700000000E-19");
}
TEST(Decimal128Test, TestDoubleConstructorQuant8) {
double dbl = 724.8799725651578000906738452613353729248046875;
Decimal128 d(dbl);
ASSERT_EQUALS(d.toString(), "724.879972565158");
}
TEST(Decimal128Test, TestDoubleConstructorQuant9) {
double dbl = -0.09645061728395000478;
Decimal128 d(dbl);
ASSERT_EQUALS(d.toString(), "-0.0964506172839500");
}
TEST(Decimal128Test, TestDoubleConstructorQuantFailPoorLog10Of2Estimate) {
double dbl = exp2(1000);
Decimal128 d(dbl);
ASSERT_EQUALS(d.toString(), "1.07150860718627E+301");
}
TEST(Decimal128Test, TestDoubleConstructorZero) {
double doubleZero = 0;
Decimal128 d(doubleZero);
ASSERT_TRUE(d.isEqual(Decimal128(0)));
}
TEST(Decimal128Test, TestDoubleConstructorPos) {
double doubleNeg = 1.0;
Decimal128 d(doubleNeg);
ASSERT_EQUALS(d.toString(), "1.00000000000000");
}
TEST(Decimal128Test, TestDoubleConstructorNeg) {
double doubleNeg = -1.0;
Decimal128 d(doubleNeg);
ASSERT_EQUALS(d.toString(), "-1.00000000000000");
}
TEST(Decimal128Test, TestDoubleConstructorMaxRoundDown) {
double doubleMax = DBL_MAX;
Decimal128 d(
doubleMax, Decimal128::kRoundTo15Digits, Decimal128::RoundingMode::kRoundTowardNegative);
ASSERT_EQUALS(d.toString(), "1.79769313486231E+308");
}
TEST(Decimal128Test, TestDoubleConstructorMaxRoundUp) {
double doubleMax = DBL_MAX;
Decimal128 d(
doubleMax, Decimal128::kRoundTo15Digits, Decimal128::RoundingMode::kRoundTowardPositive);
ASSERT_EQUALS(d.toString(), "1.79769313486232E+308");
}
TEST(Decimal128Test, TestDoubleConstructorRoundAllNines) {
double allNines = 0.999999999999999; // 15 nines
Decimal128 d(
allNines, Decimal128::kRoundTo15Digits, Decimal128::RoundingMode::kRoundTiesToAway);
ASSERT_EQUALS(d.toString(), "0.999999999999999"); // 15 nines
}
TEST(Decimal128Test, TestDoubleConstructorMaxNeg) {
double doubleMax = -1 * DBL_MAX;
Decimal128 d(doubleMax);
ASSERT_EQUALS(d.toString(), "-1.79769313486232E+308");
}
TEST(Decimal128Test, TestDoubleConstructorMin) {
double min = DBL_MIN;
Decimal128 d(min);
ASSERT_EQUALS(d.toString(), "2.22507385850720E-308");
}
TEST(Decimal128Test, TestDoubleConstructorMinNeg) {
double min = -DBL_MIN;
Decimal128 d(min);
ASSERT_EQUALS(d.toString(), "-2.22507385850720E-308");
}
TEST(Decimal128Test, TestDoubleConstructorInfinity) {
double dbl = std::numeric_limits::infinity();
Decimal128 d(dbl);
ASSERT_TRUE(d.isInfinite());
}
TEST(Decimal128Test, TestDoubleConstructorNaN) {
double dbl = std::numeric_limits::quiet_NaN();
Decimal128 d(dbl);
ASSERT_TRUE(d.isNaN());
}
TEST(Decimal128Test, TestStringConstructorInRange) {
std::string s = "+2.010";
Decimal128 d(s);
Decimal128::Value val = d.getValue();
// 0x303a000000000000 00000000000007da = +2.010
uint64_t highBytes = 0x303a000000000000;
uint64_t lowBytes = 0x00000000000007da;
ASSERT_EQUALS(val.high64, highBytes);
ASSERT_EQUALS(val.low64, lowBytes);
}
TEST(Decimal128Test, TestStringConstructorPosInfinity) {
std::string s = "+INFINITY";
Decimal128 d(s);
Decimal128::Value val = d.getValue();
// 0x7800000000000000 0000000000000000 = +Inf
uint64_t highBytes = 0x7800000000000000;
uint64_t lowBytes = 0x0000000000000000;
ASSERT_EQUALS(val.high64, highBytes);
ASSERT_EQUALS(val.low64, lowBytes);
}
TEST(Decimal128Test, TestStringConstructorNegInfinity) {
std::string s = "-INFINITY";
Decimal128 d(s);
Decimal128::Value val = d.getValue();
// 0xf800000000000000 0000000000000000 = -Inf
uint64_t highBytes = 0xf800000000000000;
uint64_t lowBytes = 0x0000000000000000;
ASSERT_EQUALS(val.high64, highBytes);
ASSERT_EQUALS(val.low64, lowBytes);
}
TEST(Decimal128Test, TestStringConstructorNaN) {
std::string s = "I am not a number!";
Decimal128 d(s);
Decimal128::Value val = d.getValue();
// 0x7c00000000000000 0000000000000000 = NaN
uint64_t highBytes = 0x7c00000000000000;
uint64_t lowBytes = 0x0000000000000000;
ASSERT_EQUALS(val.high64, highBytes);
ASSERT_EQUALS(val.low64, lowBytes);
}
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
// when encountered. However, the exponent and sign still matter.
// 0x6c10000000000000 0000000000000000 = non-canonical 0, all ignored bits clear
Decimal128 nonCanonical0E0(Decimal128::Value{0, 0x6c10000000000000ull});
std::string zeroE0 = nonCanonical0E0.toString();
ASSERT_EQUALS(zeroE0, "0");
// 0xec100000deadbeef 0123456789abcdef = non-canonical -0, random stuff in ignored bits
Decimal128 nonCanonicalM0E0(Decimal128::Value{0x0123456789abcdefull, 0xec100000deadbeefull});
std::string minusZeroE0 = nonCanonicalM0E0.toString();
ASSERT_EQUALS(minusZeroE0, "-0");
// 0x6c11fffffffffffff ffffffffffffffff = non-canonical 0.000, all ignored bits set
Decimal128 nonCanonical0E3(Decimal128::Value{0xffffffffffffffffull, 0x6c11ffffffffffffull});
std::string zeroE3 = nonCanonical0E3.toString();
ASSERT_EQUALS(zeroE3, "0E+3");
// Check extraction functions, they should treat this as the corresponding zero as well.
ASSERT_EQUALS(nonCanonical0E3.getBiasedExponent(), Decimal128("0E+3").getBiasedExponent());
ASSERT_EQUALS(nonCanonical0E3.getCoefficientHigh(), 0u);
ASSERT_EQUALS(nonCanonical0E3.getCoefficientLow(), 0u);
// Check doing some arithmetic opations and number conversions
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));
}
// Tests for absolute value function
TEST(Decimal128Test, TestAbsValuePos) {
Decimal128 d(25);
Decimal128 dAbs = d.toAbs();
ASSERT_TRUE(dAbs.isEqual(d));
}
TEST(Decimal128Test, TestAbsValueNeg) {
Decimal128 d(-25);
Decimal128 dAbs = d.toAbs();
ASSERT_TRUE(dAbs.isEqual(Decimal128(25)));
}
// Tests for Decimal128 conversions
TEST(Decimal128Test, TestDecimal128ToInt32Even) {
std::string in[6] = {"-2.7", "-2.5", "-2.2", "2.2", "2.5", "2.7"};
int32_t out[6] = {-3, -2, -2, 2, 2, 3};
std::unique_ptr decPtr;
for (int testNo = 0; testNo < 6; ++testNo) {
decPtr = stdx::make_unique(in[testNo]);
ASSERT_EQUALS(decPtr->toInt(), out[testNo]);
}
}
TEST(Decimal128Test, TestDecimal128ToInt32Neg) {
Decimal128::RoundingMode roundMode = Decimal128::RoundingMode::kRoundTowardNegative;
std::string in[6] = {"-2.7", "-2.5", "-2.2", "2.2", "2.5", "2.7"};
int32_t out[6] = {-3, -3, -3, 2, 2, 2};
std::unique_ptr decPtr;
for (int testNo = 0; testNo < 6; ++testNo) {
decPtr = stdx::make_unique(in[testNo]);
ASSERT_EQUALS(decPtr->toInt(roundMode), out[testNo]);
}
}
TEST(Decimal128Test, TestDecimal128ToInt32Pos) {
Decimal128::RoundingMode roundMode = Decimal128::RoundingMode::kRoundTowardPositive;
std::string in[6] = {"-2.7", "-2.5", "-2.2", "2.2", "2.5", "2.7"};
int32_t out[6] = {-2, -2, -2, 3, 3, 3};
std::unique_ptr decPtr;
for (int testNo = 0; testNo < 6; ++testNo) {
decPtr = stdx::make_unique(in[testNo]);
ASSERT_EQUALS(decPtr->toInt(roundMode), out[testNo]);
}
}
TEST(Decimal128Test, TestDecimal128ToInt32Zero) {
Decimal128::RoundingMode roundMode = Decimal128::RoundingMode::kRoundTowardZero;
std::string in[6] = {"-2.7", "-2.5", "-2.2", "2.2", "2.5", "2.7"};
int32_t out[6] = {-2, -2, -2, 2, 2, 2};
std::unique_ptr decPtr;
for (int testNo = 0; testNo < 6; ++testNo) {
decPtr = stdx::make_unique(in[testNo]);
ASSERT_EQUALS(decPtr->toInt(roundMode), out[testNo]);
}
}
TEST(Decimal128Test, TestDecimal128ToInt32Away) {
Decimal128::RoundingMode roundMode = Decimal128::RoundingMode::kRoundTiesToAway;
std::string in[6] = {"-2.7", "-2.5", "-2.2", "2.2", "2.5", "2.7"};
int32_t out[6] = {-3, -3, -2, 2, 3, 3};
std::unique_ptr decPtr;
for (int testNo = 0; testNo < 6; ++testNo) {
decPtr = stdx::make_unique(in[testNo]);
ASSERT_EQUALS(decPtr->toInt(roundMode), out[testNo]);
}
}
TEST(Decimal128Test, TestDecimal128ToInt64Even) {
std::string in[6] = {"-4294967296.7",
"-4294967296.5",
"-4294967296.2",
"4294967296.2",
"4294967296.5",
"4294967296.7"};
int64_t out[6] = {-4294967297, -4294967296, -4294967296, 4294967296, 4294967296, 4294967297};
std::unique_ptr decPtr;
for (int testNo = 0; testNo < 6; ++testNo) {
decPtr = stdx::make_unique(in[testNo]);
ASSERT_EQUALS(decPtr->toLong(), out[testNo]);
}
}
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 decPtr;
for (int testNo = 0; testNo < 6; ++testNo) {
decPtr = stdx::make_unique(in[testNo]);
ASSERT_EQUALS(decPtr->toLong(roundMode), out[testNo]);
}
}
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 decPtr;
for (int testNo = 0; testNo < 6; ++testNo) {
decPtr = stdx::make_unique(in[testNo]);
ASSERT_EQUALS(decPtr->toLong(roundMode), out[testNo]);
}
}
TEST(Decimal128Test, TestDecimal128ToInt64Zero) {
Decimal128::RoundingMode roundMode = Decimal128::RoundingMode::kRoundTowardZero;
std::string in[6] = {"-4294967296.7",
"-4294967296.5",
"-4294967296.2",
"4294967296.2",
"4294967296.5",
"4294967296.7"};
int64_t out[6] = {-4294967296, -4294967296, -4294967296, 4294967296, 4294967296, 4294967296};
std::unique_ptr decPtr;
for (int testNo = 0; testNo < 6; ++testNo) {
decPtr = stdx::make_unique(in[testNo]);
ASSERT_EQUALS(decPtr->toLong(roundMode), out[testNo]);
}
}
TEST(Decimal128Test, TestDecimal128ToInt64Away) {
Decimal128::RoundingMode roundMode = Decimal128::RoundingMode::kRoundTiesToAway;
std::string in[6] = {"-4294967296.7",
"-4294967296.5",
"-4294967296.2",
"4294967296.2",
"4294967296.5",
"4294967296.7"};
int64_t out[6] = {-4294967297, -4294967297, -4294967296, 4294967296, 4294967297, 4294967297};
std::unique_ptr decPtr;
for (int testNo = 0; testNo < 6; ++testNo) {
decPtr = stdx::make_unique(in[testNo]);
ASSERT_EQUALS(decPtr->toLong(roundMode), out[testNo]);
}
}
TEST(Decimal128Test, TestDecimal128ToInt32ExactEven) {
std::string in[6] = {"-2.7", "-2.5", "-2.2", "2.2", "2.5", "2.7"};
int32_t out[6] = {-3, -2, -2, 2, 2, 3};
std::unique_ptr decPtr;
for (int testNo = 0; testNo < 6; ++testNo) {
decPtr = stdx::make_unique(in[testNo]);
ASSERT_EQUALS(decPtr->toIntExact(), out[testNo]);
}
}
TEST(Decimal128Test, TestDecimal128ToInt32ExactNeg) {
Decimal128::RoundingMode roundMode = Decimal128::RoundingMode::kRoundTowardNegative;
std::string in[6] = {"-2.7", "-2.5", "-2.2", "2.2", "2.5", "2.7"};
int32_t out[6] = {-3, -3, -3, 2, 2, 2};
std::unique_ptr decPtr;
for (int testNo = 0; testNo < 6; ++testNo) {
decPtr = stdx::make_unique(in[testNo]);
ASSERT_EQUALS(decPtr->toIntExact(roundMode), out[testNo]);
}
}
TEST(Decimal128Test, TestDecimal128ToInt32ExactPos) {
Decimal128::RoundingMode roundMode = Decimal128::RoundingMode::kRoundTowardPositive;
std::string in[6] = {"-2.7", "-2.5", "-2.2", "2.2", "2.5", "2.7"};
int32_t out[6] = {-2, -2, -2, 3, 3, 3};
std::unique_ptr decPtr;
for (int testNo = 0; testNo < 6; ++testNo) {
decPtr = stdx::make_unique(in[testNo]);
ASSERT_EQUALS(decPtr->toIntExact(roundMode), out[testNo]);
}
}
TEST(Decimal128Test, TestDecimal128ToInt32ExactZero) {
Decimal128::RoundingMode roundMode = Decimal128::RoundingMode::kRoundTowardZero;
std::string in[6] = {"-2.7", "-2.5", "-2.2", "2.2", "2.5", "2.7"};
int32_t out[6] = {-2, -2, -2, 2, 2, 2};
std::unique_ptr decPtr;
for (int testNo = 0; testNo < 6; ++testNo) {
decPtr = stdx::make_unique(in[testNo]);
ASSERT_EQUALS(decPtr->toIntExact(roundMode), out[testNo]);
}
}
TEST(Decimal128Test, TestDecimal128ToInt32ExactAway) {
Decimal128::RoundingMode roundMode = Decimal128::RoundingMode::kRoundTiesToAway;
std::string in[6] = {"-2.7", "-2.5", "-2.2", "2.2", "2.5", "2.7"};
int32_t out[6] = {-3, -3, -2, 2, 3, 3};
std::unique_ptr decPtr;
for (int testNo = 0; testNo < 6; ++testNo) {
decPtr = stdx::make_unique(in[testNo]);
ASSERT_EQUALS(decPtr->toIntExact(roundMode), out[testNo]);
}
}
TEST(Decimal128Test, TestDecimal128ToInt64ExactEven) {
std::string in[6] = {"-4294967296.7",
"-4294967296.5",
"-4294967296.2",
"4294967296.2",
"4294967296.5",
"4294967296.7"};
int64_t out[6] = {-4294967297, -4294967296, -4294967296, 4294967296, 4294967296, 4294967297};
std::unique_ptr decPtr;
for (int testNo = 0; testNo < 6; ++testNo) {
decPtr = stdx::make_unique(in[testNo]);
ASSERT_EQUALS(decPtr->toLongExact(), out[testNo]);
}
}
TEST(Decimal128Test, TestDecimal128ToInt64ExactNeg) {
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 decPtr;
for (int testNo = 0; testNo < 6; ++testNo) {
decPtr = stdx::make_unique(in[testNo]);
ASSERT_EQUALS(decPtr->toLongExact(roundMode), out[testNo]);
}
}
TEST(Decimal128Test, TestDecimal128ToInt64ExactPos) {
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 decPtr;
for (int testNo = 0; testNo < 6; ++testNo) {
decPtr = stdx::make_unique(in[testNo]);
ASSERT_EQUALS(decPtr->toLongExact(roundMode), out[testNo]);
}
}
TEST(Decimal128Test, TestDecimal128ToInt64ExactZero) {
Decimal128::RoundingMode roundMode = Decimal128::RoundingMode::kRoundTowardZero;
std::string in[6] = {"-4294967296.7",
"-4294967296.5",
"-4294967296.2",
"4294967296.2",
"4294967296.5",
"4294967296.7"};
int64_t out[6] = {-4294967296, -4294967296, -4294967296, 4294967296, 4294967296, 4294967296};
std::unique_ptr decPtr;
for (int testNo = 0; testNo < 6; ++testNo) {
decPtr = stdx::make_unique(in[testNo]);
ASSERT_EQUALS(decPtr->toLongExact(roundMode), out[testNo]);
}
}
TEST(Decimal128Test, TestDecimal128ToInt64ExactAway) {
Decimal128::RoundingMode roundMode = Decimal128::RoundingMode::kRoundTiesToAway;
std::string in[6] = {"-4294967296.7",
"-4294967296.5",
"-4294967296.2",
"4294967296.2",
"4294967296.5",
"4294967296.7"};
int64_t out[6] = {-4294967297, -4294967297, -4294967296, 4294967296, 4294967297, 4294967297};
std::unique_ptr decPtr;
for (int testNo = 0; testNo < 6; ++testNo) {
decPtr = stdx::make_unique(in[testNo]);
ASSERT_EQUALS(decPtr->toLongExact(roundMode), out[testNo]);
}
}
TEST(Decimal128Test, TestDecimal128ToDoubleNormal) {
std::string s = "+2.015";
Decimal128 d(s);
double result = d.toDouble();
ASSERT_EQUALS(result, 2.015);
}
TEST(Decimal128Test, TestDecimal128ToDoubleZero) {
std::string s = "+0.000";
Decimal128 d(s);
double result = d.toDouble();
ASSERT_EQUALS(result, 0.0);
}
TEST(Decimal128Test, TestDecimal128ToDoubleLargerThanInfinity) {
std::string s = "300E2000";
Decimal128 d(s);
double result = d.toDouble();
ASSERT_EQUALS(result, std::numeric_limits::infinity());
}
TEST(Decimal128Test, TestDecimal128ToDoubleLargerThanNegInfinity) {
std::string s = "-300E2000";
Decimal128 d(s);
double result = d.toDouble();
ASSERT_EQUALS(result, -1 * std::numeric_limits::infinity());
}
TEST(Decimal128Test, TestDecimal128ToDoubleSmallerThanSmallestDouble) {
std::string s = "1E-5900";
Decimal128 d(s);
double result = d.toDouble();
ASSERT_EQUALS(result, 0);
}
TEST(Decimal128Test, TestDecimal128ToDoubleSmallerThanNegSmallestDouble) {
std::string s = "-1E-5900";
Decimal128 d(s);
double result = d.toDouble();
ASSERT_EQUALS(result, 0);
}
TEST(Decimal128Test, TestDecimal128ToStringPos) {
std::string s = "2087.015E+281";
Decimal128 d(s);
std::string result = d.toString();
ASSERT_EQUALS(result, "2.087015E+284");
}
TEST(Decimal128Test, TestDecimal128ToStringPos2) {
std::string s = "10.50E3";
Decimal128 d(s);
std::string result = d.toString();
ASSERT_EQUALS(result, "1.050E+4");
}
TEST(Decimal128Test, TestDecimal128ToStringPos3) {
std::string s = "10.51E3";
Decimal128 d(s);
std::string result = d.toString();
ASSERT_EQUALS(result, "1.051E+4");
}
TEST(Decimal128Test, TestDecimal128ToStringNeg) {
std::string s = "-2087.015E-281";
Decimal128 d(s);
std::string result = d.toString();
ASSERT_EQUALS(result, "-2.087015E-278");
}
TEST(Decimal128Test, TestDecimal128ToStringInRangeZero1) {
std::string s = "0";
Decimal128 d(s);
std::string result = d.toString();
ASSERT_EQUALS(result, "0");
}
TEST(Decimal128Test, TestDecimal128ToStringInRangeZero2) {
std::string s = "0.0";
Decimal128 d(s);
std::string result = d.toString();
ASSERT_EQUALS(result, "0.0");
}
TEST(Decimal128Test, TestDecimal128ToStringInRangeZero3) {
std::string s = "0.00";
Decimal128 d(s);
std::string result = d.toString();
ASSERT_EQUALS(result, "0.00");
}
TEST(Decimal128Test, TestDecimal128ToStringInRangeZero4) {
std::string s = "000.0";
Decimal128 d(s);
std::string result = d.toString();
ASSERT_EQUALS(result, "0.0");
}
TEST(Decimal128Test, TestDecimal128ToStringInRangeZero5) {
std::string s = "0.000000000000";
Decimal128 d(s);
std::string result = d.toString();
ASSERT_EQUALS(result, "0E-12");
}
TEST(Decimal128Test, TestDecimal128ToStringInRangePos1) {
std::string s = "1234567890.1234567890";
Decimal128 d(s);
std::string result = d.toString();
ASSERT_EQUALS(result, "1234567890.1234567890");
}
TEST(Decimal128Test, TestDecimal128ToStringInRangePos2) {
std::string s = "5.00";
Decimal128 d(s);
std::string result = d.toString();
ASSERT_EQUALS(result, "5.00");
}
TEST(Decimal128Test, TestDecimal128ToStringInRangePos3) {
std::string s = "50.0";
Decimal128 d(s);
std::string result = d.toString();
ASSERT_EQUALS(result, "50.0");
}
TEST(Decimal128Test, TestDecimal128ToStringInRangePos4) {
std::string s = "5";
Decimal128 d(s);
std::string result = d.toString();
ASSERT_EQUALS(result, "5");
}
TEST(Decimal128Test, TestDecimal128ToStringInRangePos5) {
std::string s = "50";
Decimal128 d(s);
std::string result = d.toString();
ASSERT_EQUALS(result, "50");
}
TEST(Decimal128Test, TestDecimal128ToStringInRangePos5Minus) {
std::string s = "-50";
Decimal128 d(s);
std::string result = d.toString();
ASSERT_EQUALS(result, "-50");
}
TEST(Decimal128Test, TestDecimal128ToStringInRangeNeg1) {
std::string s = ".05";
Decimal128 d(s);
std::string result = d.toString();
ASSERT_EQUALS(result, "0.05");
}
TEST(Decimal128Test, TestDecimal128ToStringInRangeNeg2) {
std::string s = ".5";
Decimal128 d(s);
std::string result = d.toString();
ASSERT_EQUALS(result, "0.5");
}
TEST(Decimal128Test, TestDecimal128ToStringInRangeNeg3) {
std::string s = ".0052";
Decimal128 d(s);
std::string result = d.toString();
ASSERT_EQUALS(result, "0.0052");
}
TEST(Decimal128Test, TestDecimal128ToStringInRangeNeg4) {
std::string s = ".005";
Decimal128 d(s);
std::string result = d.toString();
ASSERT_EQUALS(result, "0.005");
}
TEST(Decimal128Test, TestDecimal128ToStringInRangeNeg4Minus) {
std::string s = "-.005";
Decimal128 d(s);
std::string result = d.toString();
ASSERT_EQUALS(result, "-0.005");
}
TEST(Decimal128Test, TestDecimal128ToStringOutRangeNeg3) {
std::string s = ".012587E-200";
Decimal128 d(s);
std::string result = d.toString();
ASSERT_EQUALS(result, "1.2587E-202");
}
TEST(Decimal128Test, TestDecimal128ToStringOutRangePos2) {
std::string s = "10201.01E14";
Decimal128 d(s);
std::string result = d.toString();
ASSERT_EQUALS(result, "1.020101E+18");
}
TEST(Decimal128Test, TestDecimal128ToStringFinite) {
// General test cases taken from http://speleotrove.com/decimal/daconvs.html#reftostr
std::string s[15] = {"123",
"-123",
"123E1",
"123E3",
"123E-1",
"123E-5",
"123E-10",
"-123E-12",
"0E0",
"0E-2",
"0E2",
"-0",
"5E-6",
"50E-7",
"5E-7"};
std::string expected[15] = {"123",
"-123",
"1.23E+3",
"1.23E+5",
"12.3",
"0.00123",
"1.23E-8",
"-1.23E-10",
"0",
"0.00",
"0E+2",
"-0",
"0.000005",
"0.0000050",
"5E-7"};
for (int i = 0; i < 15; i++) {
Decimal128 d(s[i]);
std::string result = d.toString();
ASSERT_EQUALS(result, expected[i]);
}
}
TEST(Decimal128Test, TestDecimal128ToStringInvalidToNaN) {
std::string s = "Some garbage string";
Decimal128 d(s);
ASSERT_EQUALS(d.toString(), "NaN");
}
TEST(Decimal128Test, TestDecimal128ToStringNaN) {
std::string s[3] = {"-NaN", "+NaN", "NaN"};
for (auto& item : s) {
Decimal128 d(item);
ASSERT_EQUALS(d.toString(), "NaN");
}
// Testing a NaN with a payload
Decimal128 payloadNaN(Decimal128::Value({/*payload*/ 0x1, 0x7cull << 56}));
ASSERT_EQUALS(payloadNaN.toString(), "NaN");
}
TEST(Decimal128Test, TestDecimal128ToStringPosInf) {
std::string s[3] = {"Inf", "Infinity", "+Inf"};
for (auto& item : s) {
Decimal128 d(item);
ASSERT_EQUALS(d.toString(), "Infinity");
}
}
TEST(Decimal128Test, TestDecimal128ToStringNegInf) {
std::string s[2] = {"-Infinity", "-Inf"};
for (auto& item : s) {
Decimal128 d(item);
ASSERT_EQUALS(d.toString(), "-Infinity");
}
}
// Tests for Decimal128 operations that use a signaling flag
TEST(Decimal128Test, TestDecimal128ToIntSignaling) {
Decimal128 d("NaN");
uint32_t sigFlags = Decimal128::SignalingFlag::kNoFlag;
int32_t intVal = d.toInt(&sigFlags);
ASSERT_EQUALS(intVal, std::numeric_limits::min());
ASSERT_TRUE(Decimal128::hasFlag(sigFlags, Decimal128::SignalingFlag::kInvalid));
}
TEST(Decimal128Test, TestDecimal128ToLongSignaling) {
Decimal128 d("Infinity");
uint32_t sigFlags = Decimal128::SignalingFlag::kNoFlag;
int64_t longVal = d.toLong(&sigFlags);
ASSERT_EQUALS(longVal, std::numeric_limits::lowest());
ASSERT_TRUE(Decimal128::hasFlag(sigFlags, Decimal128::SignalingFlag::kInvalid));
}
TEST(Decimal128Test, TestDecimal128ToIntExactSignaling) {
Decimal128 d("10000000000000000");
uint32_t sigFlags = Decimal128::SignalingFlag::kNoFlag;
int32_t intVal = d.toIntExact(&sigFlags);
ASSERT_EQUALS(intVal, std::numeric_limits::lowest());
// TODO: The supported library does not set the kInexact flag even though
// the documentation claims to for exact integer conversions.
// ASSERT_TRUE(Decimal128::hasFlag(sigFlags, Decimal128::SignalingFlag::kInexact));
ASSERT_TRUE(Decimal128::hasFlag(sigFlags, Decimal128::SignalingFlag::kInvalid));
}
TEST(Decimal128Test, TestDecimal128ToLongExactSignaling) {
Decimal128 d("100000000000000000000000000");
uint32_t sigFlags = Decimal128::SignalingFlag::kNoFlag;
int64_t longVal = d.toLongExact(&sigFlags);
ASSERT_EQUALS(longVal, std::numeric_limits::lowest());
// TODO: The supported library does not set the kInexact flag even though
// the documentation claims to for exact integer conversions.
// ASSERT_TRUE(Decimal128::hasFlag(sigFlags, Decimal128::SignalingFlag::kInexact));
ASSERT_TRUE(Decimal128::hasFlag(sigFlags, Decimal128::SignalingFlag::kInvalid));
}
TEST(Decimal128Test, TestDecimal128ToDoubleSignaling) {
Decimal128 d("0.1");
uint32_t sigFlags = Decimal128::SignalingFlag::kNoFlag;
double doubleVal = d.toDouble(&sigFlags);
ASSERT_EQUALS(doubleVal, 0.1);
ASSERT_TRUE(Decimal128::hasFlag(sigFlags, Decimal128::SignalingFlag::kInexact));
}
TEST(Decimal128Test, TestDecimal128AddSignaling) {
Decimal128 d1("0.1");
Decimal128 d2("0.1");
uint32_t sigFlags = Decimal128::SignalingFlag::kNoFlag;
d1.add(d2, &sigFlags);
ASSERT_EQUALS(sigFlags, Decimal128::SignalingFlag::kNoFlag);
}
TEST(Decimal128Test, TestDecimal128SubtractSignaling) {
Decimal128 d = Decimal128::kLargestNegative;
uint32_t sigFlags = Decimal128::SignalingFlag::kNoFlag;
Decimal128 res = d.subtract(Decimal128(1), &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);
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);
ASSERT_TRUE(res.isEqual(Decimal128::kPositiveInfinity));
ASSERT_TRUE(Decimal128::hasFlag(sigFlags, Decimal128::SignalingFlag::kDivideByZero));
}
// Test Decimal128 special comparisons
TEST(Decimal128Test, TestDecimal128IsZero) {
Decimal128 d1(0);
Decimal128 d2(500);
ASSERT_TRUE(d1.isZero());
ASSERT_FALSE(d2.isZero());
}
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());
}
TEST(Decimal128Test, TestDecimal128IsInfinite) {
Decimal128 d1("NaN");
Decimal128 d2("10.5");
Decimal128 d3("Inf");
Decimal128 d4("-Inf");
ASSERT_FALSE(d1.isInfinite());
ASSERT_FALSE(d2.isInfinite());
ASSERT_TRUE(d3.isInfinite());
ASSERT_TRUE(d4.isInfinite());
}
TEST(Decimal128Test, TestDecimal128IsNegative) {
Decimal128 d1("NaN");
Decimal128 d2("-NaN");
Decimal128 d3("10.5");
Decimal128 d4("-10.5");
Decimal128 d5("Inf");
Decimal128 d6("-Inf");
ASSERT_FALSE(d1.isNegative());
ASSERT_FALSE(d3.isNegative());
ASSERT_FALSE(d5.isNegative());
ASSERT_TRUE(d2.isNegative());
ASSERT_TRUE(d4.isNegative());
ASSERT_TRUE(d6.isNegative());
}
// Tests for Decimal128 math operations
TEST(Decimal128Test, TestDecimal128AdditionCase1) {
Decimal128 d1("25.05E20");
Decimal128 d2("-50.5218E19");
Decimal128 result = d1.add(d2);
Decimal128 expected("1.999782E21");
ASSERT_EQUALS(result.getValue().low64, expected.getValue().low64);
ASSERT_EQUALS(result.getValue().high64, expected.getValue().high64);
}
TEST(Decimal128Test, TestDecimal128AdditionCase2) {
Decimal128 d1("1.00");
Decimal128 d2("2.000");
Decimal128 result = d1.add(d2);
Decimal128 expected("3.000");
ASSERT_EQUALS(result.getValue().low64, expected.getValue().low64);
ASSERT_EQUALS(result.getValue().high64, expected.getValue().high64);
}
TEST(Decimal128Test, TestDecimal128SubtractionCase1) {
Decimal128 d1("25.05E20");
Decimal128 d2("-50.5218E19");
Decimal128 result = d1.subtract(d2);
Decimal128 expected("3.010218E21");
ASSERT_EQUALS(result.getValue().low64, expected.getValue().low64);
ASSERT_EQUALS(result.getValue().high64, expected.getValue().high64);
}
TEST(Decimal128Test, TestDecimal128SubtractionCase2) {
Decimal128 d1("1.00");
Decimal128 d2("2.000");
Decimal128 result = d1.subtract(d2);
Decimal128 expected("-1.000");
ASSERT_EQUALS(result.getValue().low64, expected.getValue().low64);
ASSERT_EQUALS(result.getValue().high64, expected.getValue().high64);
}
TEST(Decimal128Test, TestDecimal128MultiplicationCase1) {
Decimal128 d1("25.05E20");
Decimal128 d2("-50.5218E19");
Decimal128 result = d1.multiply(d2);
Decimal128 expected("-1.265571090E42");
ASSERT_EQUALS(result.getValue().low64, expected.getValue().low64);
ASSERT_EQUALS(result.getValue().high64, expected.getValue().high64);
}
TEST(Decimal128Test, TestDecimal128MultiplicationCase2) {
Decimal128 d1("1.00");
Decimal128 d2("2.000");
Decimal128 result = d1.multiply(d2);
Decimal128 expected("2.00000");
ASSERT_EQUALS(result.getValue().low64, expected.getValue().low64);
ASSERT_EQUALS(result.getValue().high64, expected.getValue().high64);
}
TEST(Decimal128Test, TestDecimal128DivisionCase1) {
Decimal128 d1("25.05E20");
Decimal128 d2("-50.5218E19");
Decimal128 result = d1.divide(d2);
Decimal128 expected("-4.958255644098191275845278671781290");
ASSERT_EQUALS(result.getValue().low64, expected.getValue().low64);
ASSERT_EQUALS(result.getValue().high64, expected.getValue().high64);
}
TEST(Decimal128Test, TestDecimal128DivisionCase2) {
Decimal128 d1("1.00");
Decimal128 d2("2.000");
Decimal128 result = d1.divide(d2);
Decimal128 expected("0.5");
ASSERT_EQUALS(result.getValue().low64, expected.getValue().low64);
ASSERT_EQUALS(result.getValue().high64, expected.getValue().high64);
}
TEST(Decimal128Test, TestDecimal128Quantize) {
Decimal128 expected("1.00001");
Decimal128 val("1.000008");
Decimal128 ref("0.00001");
Decimal128 result = val.quantize(ref);
ASSERT_EQUALS(result.getValue().low64, expected.getValue().low64);
ASSERT_EQUALS(result.getValue().high64, expected.getValue().high64);
}
TEST(Decimal128Test, TestDecimal128NormalizeSmallVals) {
Decimal128 d1("500E-2");
Decimal128 d2("5");
Decimal128 d1Norm = d1.normalize();
Decimal128 d2Norm = d2.normalize();
ASSERT_EQUALS(d1Norm.getValue().low64, d2Norm.getValue().low64);
ASSERT_EQUALS(d1Norm.getValue().high64, d2Norm.getValue().high64);
}
TEST(Decimal128Test, TestDecimal128NormalizeLargeVals) {
Decimal128 d1("5E-6174");
Decimal128 d2("500E-6176");
Decimal128 d1Norm = d1.normalize();
Decimal128 d2Norm = d2.normalize();
ASSERT_EQUALS(d1Norm.getValue().low64, d2Norm.getValue().low64);
ASSERT_EQUALS(d1Norm.getValue().high64, d2Norm.getValue().high64);
}
// Tests for Decimal128 comparison operations
TEST(Decimal128Test, TestDecimal128EqualCase1) {
Decimal128 d1("25.05E20");
Decimal128 d2("25.05E20");
bool result = d1.isEqual(d2);
ASSERT_TRUE(result);
}
TEST(Decimal128Test, TestDecimal128EqualCase2) {
Decimal128 d1("1.00");
Decimal128 d2("1.000000000");
bool result = d1.isEqual(d2);
ASSERT_TRUE(result);
}
TEST(Decimal128Test, TestDecimal128EqualCase3) {
Decimal128 d1("0.1");
Decimal128 d2("0.100000000000000005");
bool result = d1.isEqual(d2);
ASSERT_FALSE(result);
}
TEST(Decimal128Test, TestDecimal128EqualCase4) {
Decimal128 d1("inf");
Decimal128 d2("inf");
bool result = d1.isEqual(d2);
ASSERT_TRUE(result);
}
TEST(Decimal128Test, TestDecimal128NotEqualCase1) {
Decimal128 d1("25.05E20");
Decimal128 d2("25.06E20");
bool result = d1.isNotEqual(d2);
ASSERT_TRUE(result);
}
TEST(Decimal128Test, TestDecimal128NotEqualCase2) {
Decimal128 d1("-25.0001E20");
Decimal128 d2("-25.00010E20");
bool result = d1.isNotEqual(d2);
ASSERT_FALSE(result);
}
TEST(Decimal128Test, TestDecimal128GreaterCase1) {
Decimal128 d1("25.05E20");
Decimal128 d2("-25.05E20");
bool result = d1.isGreater(d2);
ASSERT_TRUE(result);
}
TEST(Decimal128Test, TestDecimal128GreaterCase2) {
Decimal128 d1("25.05E20");
Decimal128 d2("25.05E20");
bool result = d1.isGreater(d2);
ASSERT_FALSE(result);
}
TEST(Decimal128Test, TestDecimal128GreaterCase3) {
Decimal128 d1("-INFINITY");
Decimal128 d2("+INFINITY");
bool result = d1.isGreater(d2);
ASSERT_FALSE(result);
}
TEST(Decimal128Test, TestDecimal128GreaterEqualCase1) {
Decimal128 d1("25.05E20");
Decimal128 d2("-25.05E20");
bool result = d1.isGreaterEqual(d2);
ASSERT_TRUE(result);
}
TEST(Decimal128Test, TestDecimal128GreaterEqualCase2) {
Decimal128 d1("25.05E20");
Decimal128 d2("25.05E20");
bool result = d1.isGreaterEqual(d2);
ASSERT_TRUE(result);
}
TEST(Decimal128Test, TestDecimal128GreaterEqualCase3) {
Decimal128 d1("-INFINITY");
Decimal128 d2("+INFINITY");
bool result = d1.isGreaterEqual(d2);
ASSERT_FALSE(result);
}
TEST(Decimal128Test, TestDecimal128LessCase1) {
Decimal128 d1("25.05E20");
Decimal128 d2("-25.05E20");
bool result = d1.isLess(d2);
ASSERT_FALSE(result);
}
TEST(Decimal128Test, TestDecimal128LessCase2) {
Decimal128 d1("25.05E20");
Decimal128 d2("25.05E20");
bool result = d1.isLess(d2);
ASSERT_FALSE(result);
}
TEST(Decimal128Test, TestDecimal128LessCase3) {
Decimal128 d1("-INFINITY");
Decimal128 d2("+INFINITY");
bool result = d1.isLess(d2);
ASSERT_TRUE(result);
}
TEST(Decimal128Test, TestDecimal128LessEqualCase1) {
Decimal128 d1("25.05E20");
Decimal128 d2("-25.05E20");
bool result = d1.isLessEqual(d2);
ASSERT_FALSE(result);
}
TEST(Decimal128Test, TestDecimal128LessEqualCase2) {
Decimal128 d1("25.05E20");
Decimal128 d2("25.05E20");
bool result = d1.isLessEqual(d2);
ASSERT_TRUE(result);
}
TEST(Decimal128Test, TestDecimal128LessEqualCase3) {
Decimal128 d1("-INFINITY");
Decimal128 d2("+INFINITY");
bool result = d1.isLessEqual(d2);
ASSERT_TRUE(result);
}
TEST(Decimal128Test, TestDecimal128GetLargestPositive) {
Decimal128 d = Decimal128::kLargestPositive;
uint64_t largestPositiveDecimalHigh64 = 6917508178773903296ull;
uint64_t largestPositveDecimalLow64 = 4003012203950112767ull;
ASSERT_EQUALS(d.getValue().high64, largestPositiveDecimalHigh64);
ASSERT_EQUALS(d.getValue().low64, largestPositveDecimalLow64);
}
TEST(Decimal128Test, TestDecimal128GetSmallestPositive) {
Decimal128 d = Decimal128::kSmallestPositive;
uint64_t smallestPositiveDecimalHigh64 = 0ull;
uint64_t smallestPositiveDecimalLow64 = 1ull;
ASSERT_EQUALS(d.getValue().high64, smallestPositiveDecimalHigh64);
ASSERT_EQUALS(d.getValue().low64, smallestPositiveDecimalLow64);
}
TEST(Decimal128Test, TestDecimal128GetLargestNegative) {
Decimal128 d = Decimal128::kLargestNegative;
uint64_t largestNegativeDecimalHigh64 = 16140880215628679104ull;
uint64_t largestNegativeDecimalLow64 = 4003012203950112767ull;
ASSERT_EQUALS(d.getValue().high64, largestNegativeDecimalHigh64);
ASSERT_EQUALS(d.getValue().low64, largestNegativeDecimalLow64);
}
TEST(Decimal128Test, TestDecimal128GetSmallestNegative) {
Decimal128 d = Decimal128::kSmallestNegative;
uint64_t smallestNegativeDecimalHigh64 = 9223372036854775808ull;
uint64_t smallestNegativeDecimalLow64 = 1ull;
ASSERT_EQUALS(d.getValue().high64, smallestNegativeDecimalHigh64);
ASSERT_EQUALS(d.getValue().low64, smallestNegativeDecimalLow64);
}
TEST(Decimal128Test, TestDecimal128GetPosInfinity) {
Decimal128 d = Decimal128::kPositiveInfinity;
uint64_t decimalPositiveInfinityHigh64 = 8646911284551352320ull;
uint64_t decimalPositiveInfinityLow64 = 0ull;
ASSERT_EQUALS(d.getValue().high64, decimalPositiveInfinityHigh64);
ASSERT_EQUALS(d.getValue().low64, decimalPositiveInfinityLow64);
}
TEST(Decimal128Test, TestDecimal128GetNegInfinity) {
Decimal128 d = Decimal128::kNegativeInfinity;
uint64_t decimalNegativeInfinityHigh64 = 17870283321406128128ull;
uint64_t decimalNegativeInfinityLow64 = 0ull;
ASSERT_EQUALS(d.getValue().high64, decimalNegativeInfinityHigh64);
ASSERT_EQUALS(d.getValue().low64, decimalNegativeInfinityLow64);
}
TEST(Decimal128Test, TestDecimal128GetPosNaN) {
Decimal128 d = Decimal128::kPositiveNaN;
uint64_t decimalPositiveNaNHigh64 = 8935141660703064064ull;
uint64_t decimalPositiveNaNLow64 = 0ull;
ASSERT_EQUALS(d.getValue().high64, decimalPositiveNaNHigh64);
ASSERT_EQUALS(d.getValue().low64, decimalPositiveNaNLow64);
}
TEST(Decimal128Test, TestDecimal128GetNegNaN) {
Decimal128 d = Decimal128::kNegativeNaN;
uint64_t decimalNegativeNaNHigh64 = 18158513697557839872ull;
uint64_t decimalNegativeNaNLow64 = 0ull;
ASSERT_EQUALS(d.getValue().high64, decimalNegativeNaNHigh64);
ASSERT_EQUALS(d.getValue().low64, decimalNegativeNaNLow64);
}
TEST(Decimal128Test, TestDecimal128GetLargestNegativeExponentZero) {
Decimal128 d = Decimal128::kLargestNegativeExponentZero;
uint64_t largestNegativeExponentZeroHigh64 = 0ull;
uint64_t largestNegativeExponentZeroLow64 = 0ull;
ASSERT_EQUALS(d.getValue().high64, largestNegativeExponentZeroHigh64);
ASSERT_EQUALS(d.getValue().low64, largestNegativeExponentZeroLow64);
}
} // namespace mongo