mirror of
https://github.com/XRPLF/rippled.git
synced 2026-02-11 01:12:32 +00:00
Fix formatting
This commit is contained in:
@@ -646,11 +646,7 @@ private:
|
||||
*/
|
||||
template <bool expectNormal = true, detail::UnsignedMantissa Rep = internalrep>
|
||||
void
|
||||
fromInternal(
|
||||
bool negative,
|
||||
Rep mantissa,
|
||||
int exponent,
|
||||
MantissaRange const* pRange);
|
||||
fromInternal(bool negative, Rep mantissa, int exponent, MantissaRange const* pRange);
|
||||
|
||||
/** Rebuilds the number from components.
|
||||
*
|
||||
@@ -662,9 +658,7 @@ private:
|
||||
* bring it back into range.
|
||||
*
|
||||
*/
|
||||
template <
|
||||
bool expectNormal = true,
|
||||
detail::UnsignedMantissa Rep = internalrep>
|
||||
template <bool expectNormal = true, detail::UnsignedMantissa Rep = internalrep>
|
||||
void
|
||||
fromInternal(bool negative, Rep mantissa, int exponent);
|
||||
|
||||
@@ -674,13 +668,8 @@ public:
|
||||
constexpr static internalrep largestMantissa = largeRange.max;
|
||||
};
|
||||
|
||||
inline constexpr Number::Number(
|
||||
bool negative,
|
||||
internalrep mantissa,
|
||||
int exponent,
|
||||
unchecked) noexcept
|
||||
: mantissa_{(negative ? -1 : 1) * static_cast<rep>(mantissa)}
|
||||
, exponent_{exponent}
|
||||
inline constexpr Number::Number(bool negative, internalrep mantissa, int exponent, unchecked) noexcept
|
||||
: mantissa_{(negative ? -1 : 1) * static_cast<rep>(mantissa)}, exponent_{exponent}
|
||||
{
|
||||
}
|
||||
|
||||
@@ -691,8 +680,7 @@ inline constexpr Number::Number(internalrep mantissa, int exponent, unchecked) n
|
||||
|
||||
constexpr static Number numZero{};
|
||||
|
||||
inline Number::Number(internalrep mantissa, int exponent, normalized)
|
||||
: Number(false, mantissa, exponent, normalized{})
|
||||
inline Number::Number(internalrep mantissa, int exponent, normalized) : Number(false, mantissa, exponent, normalized{})
|
||||
{
|
||||
}
|
||||
|
||||
@@ -856,10 +844,7 @@ Number::normalizeToRange(T minMantissa, T maxMantissa) const
|
||||
|
||||
if constexpr (std::is_unsigned_v<T>)
|
||||
{
|
||||
XRPL_ASSERT_PARTS(
|
||||
!negative,
|
||||
"xrpl::Number::normalizeToRange",
|
||||
"Number is non-negative for unsigned range.");
|
||||
XRPL_ASSERT_PARTS(!negative, "xrpl::Number::normalizeToRange", "Number is non-negative for unsigned range.");
|
||||
// To avoid logical errors in release builds, throw if the Number is
|
||||
// negative for an unsigned range.
|
||||
if (negative)
|
||||
|
||||
@@ -522,8 +522,7 @@ STAmount::fromNumber(A const& a, Number const& number)
|
||||
}
|
||||
|
||||
XRPL_ASSERT_PARTS(working.signum() >= 0, "xrpl::STAmount::fromNumber", "non-negative Number to normalize");
|
||||
auto const [mantissa, exponent] =
|
||||
working.normalizeToRange(cMinValue, cMaxValue);
|
||||
auto const [mantissa, exponent] = working.normalizeToRange(cMinValue, cMaxValue);
|
||||
|
||||
return STAmount{asset, mantissa, exponent, negative};
|
||||
}
|
||||
|
||||
@@ -367,15 +367,9 @@ Number::toInternal() const
|
||||
*/
|
||||
template <bool expectNormal, detail::UnsignedMantissa Rep>
|
||||
void
|
||||
Number::fromInternal(
|
||||
bool negative,
|
||||
Rep mantissa,
|
||||
int exponent,
|
||||
MantissaRange const* pRange)
|
||||
Number::fromInternal(bool negative, Rep mantissa, int exponent, MantissaRange const* pRange)
|
||||
{
|
||||
if constexpr (std::is_same_v<
|
||||
std::bool_constant<expectNormal>,
|
||||
std::false_type>)
|
||||
if constexpr (std::is_same_v<std::bool_constant<expectNormal>, std::false_type>)
|
||||
{
|
||||
if (!pRange)
|
||||
throw std::runtime_error("Missing range to Number::fromInternal!");
|
||||
@@ -419,9 +413,7 @@ void
|
||||
Number::fromInternal(bool negative, Rep mantissa, int exponent)
|
||||
{
|
||||
MantissaRange const* pRange = nullptr;
|
||||
if constexpr (std::is_same_v<
|
||||
std::bool_constant<expectNormal>,
|
||||
std::false_type>)
|
||||
if constexpr (std::is_same_v<std::bool_constant<expectNormal>, std::false_type>)
|
||||
{
|
||||
pRange = &Number::range_.get();
|
||||
}
|
||||
@@ -432,11 +424,7 @@ Number::fromInternal(bool negative, Rep mantissa, int exponent)
|
||||
constexpr Number
|
||||
Number::oneSmall()
|
||||
{
|
||||
return Number{
|
||||
false,
|
||||
Number::smallRange.referenceMin,
|
||||
-Number::smallRange.log,
|
||||
Number::unchecked{}};
|
||||
return Number{false, Number::smallRange.referenceMin, -Number::smallRange.log, Number::unchecked{}};
|
||||
};
|
||||
|
||||
constexpr Number oneSml = Number::oneSmall();
|
||||
@@ -444,11 +432,7 @@ constexpr Number oneSml = Number::oneSmall();
|
||||
constexpr Number
|
||||
Number::oneLarge()
|
||||
{
|
||||
return Number{
|
||||
false,
|
||||
Number::largeRange.referenceMin,
|
||||
-Number::largeRange.log,
|
||||
Number::unchecked{}};
|
||||
return Number{false, Number::largeRange.referenceMin, -Number::largeRange.log, Number::unchecked{}};
|
||||
};
|
||||
|
||||
constexpr Number oneLrg = Number::oneLarge();
|
||||
@@ -517,28 +501,15 @@ doNormalize(
|
||||
return;
|
||||
}
|
||||
|
||||
XRPL_ASSERT_PARTS(
|
||||
m <= maxMantissa,
|
||||
"xrpl::doNormalize",
|
||||
"intermediate mantissa fits in int64");
|
||||
XRPL_ASSERT_PARTS(m <= maxMantissa, "xrpl::doNormalize", "intermediate mantissa fits in int64");
|
||||
mantissa = m;
|
||||
|
||||
g.doRoundUp(
|
||||
negative,
|
||||
mantissa,
|
||||
exponent,
|
||||
minMantissa,
|
||||
maxMantissa,
|
||||
"Number::normalize 2");
|
||||
g.doRoundUp(negative, mantissa, exponent, minMantissa, maxMantissa, "Number::normalize 2");
|
||||
|
||||
XRPL_ASSERT_PARTS(
|
||||
mantissa >= minMantissa && mantissa <= maxMantissa,
|
||||
"xrpl::doNormalize",
|
||||
"final mantissa fits in range");
|
||||
mantissa >= minMantissa && mantissa <= maxMantissa, "xrpl::doNormalize", "final mantissa fits in range");
|
||||
XRPL_ASSERT_PARTS(
|
||||
exponent >= minExponent && exponent <= maxExponent,
|
||||
"xrpl::doNormalize",
|
||||
"final exponent fits in range");
|
||||
exponent >= minExponent && exponent <= maxExponent, "xrpl::doNormalize", "final exponent fits in range");
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -641,9 +612,7 @@ Number::operator+=(Number const& y)
|
||||
return *this;
|
||||
}
|
||||
|
||||
XRPL_ASSERT(
|
||||
isnormal(range) && y.isnormal(range),
|
||||
"xrpl::Number::operator+=(Number) : is normal");
|
||||
XRPL_ASSERT(isnormal(range) && y.isnormal(range), "xrpl::Number::operator+=(Number) : is normal");
|
||||
// *n = negative
|
||||
// *s = sign
|
||||
// *m = mantissa
|
||||
@@ -793,12 +762,7 @@ Number::operator*=(Number const& y)
|
||||
xm = static_cast<internalrep>(zm);
|
||||
xe = ze;
|
||||
g.doRoundUp(
|
||||
zn,
|
||||
xm,
|
||||
xe,
|
||||
minMantissa,
|
||||
maxMantissa,
|
||||
"Number::multiplication overflow : exponent is " + std::to_string(xe));
|
||||
zn, xm, xe, minMantissa, maxMantissa, "Number::multiplication overflow : exponent is " + std::to_string(xe));
|
||||
|
||||
normalize(zn, xm, xe, minMantissa, maxMantissa);
|
||||
fromInternal(zn, xm, xe, &range);
|
||||
@@ -840,10 +804,8 @@ Number::operator/=(Number const& y)
|
||||
static_assert(smallRange.log == 15);
|
||||
static_assert(largeRange.log == 18);
|
||||
bool small = range.scale == MantissaRange::small;
|
||||
uint128_t const f =
|
||||
small ? 100'000'000'000'000'000 : 10'000'000'000'000'000'000ULL;
|
||||
XRPL_ASSERT_PARTS(
|
||||
f >= minMantissa * 10, "Number::operator/=", "factor expected size");
|
||||
uint128_t const f = small ? 100'000'000'000'000'000 : 10'000'000'000'000'000'000ULL;
|
||||
XRPL_ASSERT_PARTS(f >= minMantissa * 10, "Number::operator/=", "factor expected size");
|
||||
|
||||
// unsigned denominator
|
||||
auto const dmu = static_cast<uint128_t>(dm);
|
||||
@@ -892,8 +854,7 @@ Number::operator/=(Number const& y)
|
||||
}
|
||||
normalize(zn, zm, ze, minMantissa, maxMantissa);
|
||||
fromInternal(zn, zm, ze, &range);
|
||||
XRPL_ASSERT_PARTS(
|
||||
isnormal(range), "xrpl::Number::operator/=", "result is normalized");
|
||||
XRPL_ASSERT_PARTS(isnormal(range), "xrpl::Number::operator/=", "result is normalized");
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -959,12 +920,10 @@ to_string(Number const& amount)
|
||||
|
||||
// Use scientific notation for exponents that are too small or too large
|
||||
auto const rangeLog = range.log;
|
||||
if (((exponent != 0 && amount.exponent() != 0) &&
|
||||
((exponent < -(rangeLog + 10)) || (exponent > -(rangeLog - 10)))))
|
||||
if (((exponent != 0 && amount.exponent() != 0) && ((exponent < -(rangeLog + 10)) || (exponent > -(rangeLog - 10)))))
|
||||
{
|
||||
// Remove trailing zeroes from the mantissa.
|
||||
while (mantissa != 0 && mantissa % 10 == 0 &&
|
||||
exponent < Number::maxExponent)
|
||||
while (mantissa != 0 && mantissa % 10 == 0 && exponent < Number::maxExponent)
|
||||
{
|
||||
mantissa /= 10;
|
||||
++exponent;
|
||||
@@ -1098,10 +1057,8 @@ Number::root(MantissaRange const& range, Number f, unsigned d)
|
||||
return std::make_tuple(e, di);
|
||||
}();
|
||||
|
||||
XRPL_ASSERT_PARTS(
|
||||
e % di == 0, "xrpl::root(Number, unsigned)", "e is divisible by d");
|
||||
XRPL_ASSERT_PARTS(
|
||||
f.isnormal(range), "xrpl::root(Number, unsigned)", "f is normalized");
|
||||
XRPL_ASSERT_PARTS(e % di == 0, "xrpl::root(Number, unsigned)", "e is divisible by d");
|
||||
XRPL_ASSERT_PARTS(f.isnormal(range), "xrpl::root(Number, unsigned)", "f is normalized");
|
||||
bool neg = false;
|
||||
if (f < zero)
|
||||
{
|
||||
@@ -1134,10 +1091,7 @@ Number::root(MantissaRange const& range, Number f, unsigned d)
|
||||
|
||||
// return r * 10^(e/d) to reverse scaling
|
||||
auto const result = r.shiftExponent(e / di);
|
||||
XRPL_ASSERT_PARTS(
|
||||
result.isnormal(range),
|
||||
"xrpl::root(Number, unsigned)",
|
||||
"result is normalized");
|
||||
XRPL_ASSERT_PARTS(result.isnormal(range), "xrpl::root(Number, unsigned)", "result is normalized");
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1182,8 +1136,7 @@ root2(Number f)
|
||||
f = f.shiftExponent(-e); // f /= 10^e;
|
||||
return e;
|
||||
}();
|
||||
XRPL_ASSERT_PARTS(
|
||||
f.isnormal(range), "xrpl::root2(Number)", "f is normalized");
|
||||
XRPL_ASSERT_PARTS(f.isnormal(range), "xrpl::root2(Number)", "f is normalized");
|
||||
|
||||
// Quadratic least squares curve fit of f^(1/d) in the range [0, 1]
|
||||
auto const D = 105;
|
||||
@@ -1205,8 +1158,7 @@ root2(Number f)
|
||||
|
||||
// return r * 10^(e/2) to reverse scaling
|
||||
auto const result = r.shiftExponent(e / 2);
|
||||
XRPL_ASSERT_PARTS(
|
||||
result.isnormal(range), "xrpl::root2(Number)", "result is normalized");
|
||||
XRPL_ASSERT_PARTS(result.isnormal(range), "xrpl::root2(Number)", "result is normalized");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -160,17 +160,9 @@ public:
|
||||
{Number{5'555'555'555'555'555'555, -32768}, Number{-5'555'555'555'555'555'554, -32768}, Number{0}},
|
||||
{Number{true, 9'999'999'999'999'999'999ULL, -37, Number::normalized{}},
|
||||
Number{1'000'000'000'000'000'000, -18},
|
||||
Number{
|
||||
false,
|
||||
9'999'999'999'999'999'990ULL,
|
||||
-19,
|
||||
Number::normalized{}}},
|
||||
{Number{Number::largestMantissa},
|
||||
Number{6, -1},
|
||||
Number{Number::largestMantissa / 10, 1}},
|
||||
{Number{Number::largestMantissa - 1},
|
||||
Number{1, 0},
|
||||
Number{Number::largestMantissa}},
|
||||
Number{false, 9'999'999'999'999'999'990ULL, -19, Number::normalized{}}},
|
||||
{Number{Number::largestMantissa}, Number{6, -1}, Number{Number::largestMantissa / 10, 1}},
|
||||
{Number{Number::largestMantissa - 1}, Number{1, 0}, Number{Number::largestMantissa}},
|
||||
// Test extremes
|
||||
{
|
||||
// Each Number operand rounds up, so the actual mantissa is
|
||||
@@ -185,40 +177,16 @@ public:
|
||||
// result will overflow. With addition using uint128_t,
|
||||
// there's no problem. After normalizing, the resulting
|
||||
// mantissa ends up less than largestMantissa.
|
||||
Number{
|
||||
false,
|
||||
Number::largestMantissa,
|
||||
0,
|
||||
Number::normalized{}},
|
||||
Number{
|
||||
false,
|
||||
Number::largestMantissa,
|
||||
0,
|
||||
Number::normalized{}},
|
||||
Number{
|
||||
false,
|
||||
Number::largestMantissa * 2,
|
||||
0,
|
||||
Number::normalized{}},
|
||||
Number{false, Number::largestMantissa, 0, Number::normalized{}},
|
||||
Number{false, Number::largestMantissa, 0, Number::normalized{}},
|
||||
Number{false, Number::largestMantissa * 2, 0, Number::normalized{}},
|
||||
},
|
||||
{
|
||||
// These mantissas round down, so adding them together won't
|
||||
// have any consequences.
|
||||
Number{
|
||||
false,
|
||||
9'999'999'999'999'999'990ULL,
|
||||
0,
|
||||
Number::normalized{}},
|
||||
Number{
|
||||
false,
|
||||
9'999'999'999'999'999'990ULL,
|
||||
0,
|
||||
Number::normalized{}},
|
||||
Number{
|
||||
false,
|
||||
1'999'999'999'999'999'998ULL,
|
||||
1,
|
||||
Number::normalized{}},
|
||||
Number{false, 9'999'999'999'999'999'990ULL, 0, Number::normalized{}},
|
||||
Number{false, 9'999'999'999'999'999'990ULL, 0, Number::normalized{}},
|
||||
Number{false, 1'999'999'999'999'999'998ULL, 1, Number::normalized{}},
|
||||
},
|
||||
});
|
||||
auto test = [this](auto const& c) {
|
||||
@@ -302,21 +270,11 @@ public:
|
||||
{Number{1'000'000'000'000'000'001, -18},
|
||||
Number{1'000'000'000'000'000'000, -18},
|
||||
Number{1'000'000'000'000'000'000, -36}},
|
||||
{Number{Number::largestMantissa},
|
||||
Number{6, -1},
|
||||
Number{Number::largestMantissa - 1}},
|
||||
{Number{
|
||||
false,
|
||||
Number::largestMantissa + 1,
|
||||
0,
|
||||
Number::normalized{}},
|
||||
{Number{Number::largestMantissa}, Number{6, -1}, Number{Number::largestMantissa - 1}},
|
||||
{Number{false, Number::largestMantissa + 1, 0, Number::normalized{}},
|
||||
Number{1, 0},
|
||||
Number{Number::largestMantissa / 10 + 1, 1}},
|
||||
{Number{
|
||||
false,
|
||||
Number::largestMantissa + 1,
|
||||
0,
|
||||
Number::normalized{}},
|
||||
{Number{false, Number::largestMantissa + 1, 0, Number::normalized{}},
|
||||
Number{3, 0},
|
||||
Number{Number::largestMantissa}},
|
||||
{power(2, 63), Number{3, 0}, Number{Number::largestMantissa}},
|
||||
@@ -350,8 +308,7 @@ public:
|
||||
auto const result = x * y;
|
||||
std::stringstream ss;
|
||||
ss << x << " * " << y << " = " << result << ". Expected: " << z;
|
||||
BEAST_EXPECTS(
|
||||
result == z, ss.str() + " line: " + std::to_string(line));
|
||||
BEAST_EXPECTS(result == z, ss.str() + " line: " + std::to_string(line));
|
||||
}
|
||||
};
|
||||
auto tests = [&](auto const& cSmall, auto const& cLarge) {
|
||||
@@ -362,19 +319,13 @@ public:
|
||||
};
|
||||
auto const maxMantissa = Number::maxMantissa();
|
||||
auto const maxInternalMantissa =
|
||||
static_cast<std::uint64_t>(
|
||||
static_cast<std::int64_t>(power(10, Number::mantissaLog()))) *
|
||||
10 -
|
||||
1;
|
||||
static_cast<std::uint64_t>(static_cast<std::int64_t>(power(10, Number::mantissaLog()))) * 10 - 1;
|
||||
|
||||
saveNumberRoundMode save{Number::setround(Number::to_nearest)};
|
||||
{
|
||||
auto const cSmall = std::to_array<Case>({
|
||||
{Number{7}, Number{8}, Number{56}, __LINE__},
|
||||
{Number{1414213562373095, -15},
|
||||
Number{1414213562373095, -15},
|
||||
Number{2000000000000000, -15},
|
||||
__LINE__},
|
||||
{Number{1414213562373095, -15}, Number{1414213562373095, -15}, Number{2000000000000000, -15}, __LINE__},
|
||||
{Number{-1414213562373095, -15},
|
||||
Number{1414213562373095, -15},
|
||||
Number{-2000000000000000, -15},
|
||||
@@ -383,14 +334,8 @@ public:
|
||||
Number{-1414213562373095, -15},
|
||||
Number{2000000000000000, -15},
|
||||
__LINE__},
|
||||
{Number{3214285714285706, -15},
|
||||
Number{3111111111111119, -15},
|
||||
Number{1000000000000000, -14},
|
||||
__LINE__},
|
||||
{Number{1000000000000000, -32768},
|
||||
Number{1000000000000000, -32768},
|
||||
Number{0},
|
||||
__LINE__},
|
||||
{Number{3214285714285706, -15}, Number{3111111111111119, -15}, Number{1000000000000000, -14}, __LINE__},
|
||||
{Number{1000000000000000, -32768}, Number{1000000000000000, -32768}, Number{0}, __LINE__},
|
||||
// Maximum mantissa range
|
||||
{Number{9'999'999'999'999'999, 0},
|
||||
Number{9'999'999'999'999'999, 0},
|
||||
@@ -416,16 +361,9 @@ public:
|
||||
__LINE__},
|
||||
{Number{3214285714285706, -15},
|
||||
Number{3111111111111119, -15},
|
||||
Number{
|
||||
false,
|
||||
9'999'999'999'999'999'579ULL,
|
||||
-18,
|
||||
Number::normalized{}},
|
||||
__LINE__},
|
||||
{Number{1000000000000000000, -32768},
|
||||
Number{1000000000000000000, -32768},
|
||||
Number{0},
|
||||
Number{false, 9'999'999'999'999'999'579ULL, -18, Number::normalized{}},
|
||||
__LINE__},
|
||||
{Number{1000000000000000000, -32768}, Number{1000000000000000000, -32768}, Number{0}, __LINE__},
|
||||
// Items from cSmall expanded for the larger mantissa,
|
||||
// except duplicates. Sadly, it looks like sqrt(2)^2 != 2
|
||||
// with higher precision
|
||||
@@ -441,10 +379,7 @@ public:
|
||||
Number{-1414213562373095049, -18},
|
||||
Number{1999999999999999999, -18},
|
||||
__LINE__},
|
||||
{Number{3214285714285714278, -18},
|
||||
Number{3111111111111111119, -18},
|
||||
Number{10, 0},
|
||||
__LINE__},
|
||||
{Number{3214285714285714278, -18}, Number{3111111111111111119, -18}, Number{10, 0}, __LINE__},
|
||||
// Maximum internal mantissa range - rounds up to 1e19
|
||||
{Number{false, maxInternalMantissa, 0, Number::normalized{}},
|
||||
Number{false, maxInternalMantissa, 0, Number::normalized{}},
|
||||
@@ -484,10 +419,7 @@ public:
|
||||
Number{3111111111111119, -15},
|
||||
Number{9999999999999999, -15},
|
||||
__LINE__},
|
||||
{Number{1000000000000000, -32768},
|
||||
Number{1000000000000000, -32768},
|
||||
Number{0},
|
||||
__LINE__}});
|
||||
{Number{1000000000000000, -32768}, Number{1000000000000000, -32768}, Number{0}, __LINE__}});
|
||||
auto const cLarge = std::to_array<Case>(
|
||||
// Note that items with extremely large mantissas need to be
|
||||
// calculated, because otherwise they overflow uint64. Items
|
||||
@@ -508,23 +440,13 @@ public:
|
||||
__LINE__},
|
||||
{Number{3214285714285706, -15},
|
||||
Number{3111111111111119, -15},
|
||||
Number{
|
||||
false,
|
||||
9999999999999999579ULL,
|
||||
-18,
|
||||
Number::normalized{}},
|
||||
__LINE__},
|
||||
{Number{1000000000000000000, -32768},
|
||||
Number{1000000000000000000, -32768},
|
||||
Number{0},
|
||||
Number{false, 9999999999999999579ULL, -18, Number::normalized{}},
|
||||
__LINE__},
|
||||
{Number{1000000000000000000, -32768}, Number{1000000000000000000, -32768}, Number{0}, __LINE__},
|
||||
// Items from cSmall expanded for the larger mantissa,
|
||||
// except duplicates. Sadly, it looks like sqrt(2)^2 != 2
|
||||
// with higher precision
|
||||
{Number{1414213562373095049, -18},
|
||||
Number{1414213562373095049, -18},
|
||||
Number{2, 0},
|
||||
__LINE__},
|
||||
{Number{1414213562373095049, -18}, Number{1414213562373095049, -18}, Number{2, 0}, __LINE__},
|
||||
{Number{-1414213562373095048, -18},
|
||||
Number{1414213562373095048, -18},
|
||||
Number{-1999999999999999997, -18},
|
||||
@@ -533,22 +455,13 @@ public:
|
||||
Number{-1414213562373095049, -18},
|
||||
Number{1999999999999999999, -18},
|
||||
__LINE__},
|
||||
{Number{3214285714285714278, -18},
|
||||
Number{3111111111111111119, -18},
|
||||
Number{10, 0},
|
||||
__LINE__},
|
||||
{Number{3214285714285714278, -18}, Number{3111111111111111119, -18}, Number{10, 0}, __LINE__},
|
||||
// Maximum internal mantissa range - rounds down to
|
||||
// maxMantissa/10e1
|
||||
// 99'999'999'999'999'999'800'000'000'000'000'000'100
|
||||
{Number{
|
||||
false, maxInternalMantissa, 0, Number::normalized{}},
|
||||
Number{
|
||||
false, maxInternalMantissa, 0, Number::normalized{}},
|
||||
Number{
|
||||
false,
|
||||
maxInternalMantissa / 10 - 1,
|
||||
20,
|
||||
Number::normalized{}},
|
||||
{Number{false, maxInternalMantissa, 0, Number::normalized{}},
|
||||
Number{false, maxInternalMantissa, 0, Number::normalized{}},
|
||||
Number{false, maxInternalMantissa / 10 - 1, 20, Number::normalized{}},
|
||||
__LINE__},
|
||||
// Maximum actual mantissa range - same as int64
|
||||
{Number{false, maxMantissa, 0, Number::normalized{}},
|
||||
@@ -585,10 +498,7 @@ public:
|
||||
Number{3111111111111119, -15},
|
||||
Number{9999999999999999, -15},
|
||||
__LINE__},
|
||||
{Number{1000000000000000, -32768},
|
||||
Number{1000000000000000, -32768},
|
||||
Number{0},
|
||||
__LINE__}});
|
||||
{Number{1000000000000000, -32768}, Number{1000000000000000, -32768}, Number{0}, __LINE__}});
|
||||
auto const cLarge = std::to_array<Case>(
|
||||
// Note that items with extremely large mantissas need to be
|
||||
// calculated, because otherwise they overflow uint64. Items
|
||||
@@ -609,23 +519,13 @@ public:
|
||||
__LINE__},
|
||||
{Number{3214285714285706, -15},
|
||||
Number{3111111111111119, -15},
|
||||
Number{
|
||||
false,
|
||||
9'999'999'999'999'999'579ULL,
|
||||
-18,
|
||||
Number::normalized{}},
|
||||
__LINE__},
|
||||
{Number{1000000000000000000, -32768},
|
||||
Number{1000000000000000000, -32768},
|
||||
Number{0},
|
||||
Number{false, 9'999'999'999'999'999'579ULL, -18, Number::normalized{}},
|
||||
__LINE__},
|
||||
{Number{1000000000000000000, -32768}, Number{1000000000000000000, -32768}, Number{0}, __LINE__},
|
||||
// Items from cSmall expanded for the larger mantissa,
|
||||
// except duplicates. Sadly, it looks like sqrt(2)^2 != 2
|
||||
// with higher precision
|
||||
{Number{1414213562373095049, -18},
|
||||
Number{1414213562373095049, -18},
|
||||
Number{2, 0},
|
||||
__LINE__},
|
||||
{Number{1414213562373095049, -18}, Number{1414213562373095049, -18}, Number{2, 0}, __LINE__},
|
||||
{Number{-1414213562373095048, -18},
|
||||
Number{1414213562373095048, -18},
|
||||
Number{-1999999999999999998, -18},
|
||||
@@ -634,22 +534,13 @@ public:
|
||||
Number{-1414213562373095049, -18},
|
||||
Number{1999999999999999999, -18},
|
||||
__LINE__},
|
||||
{Number{3214285714285714278, -18},
|
||||
Number{3111111111111111119, -18},
|
||||
Number{10, 0},
|
||||
__LINE__},
|
||||
{Number{3214285714285714278, -18}, Number{3111111111111111119, -18}, Number{10, 0}, __LINE__},
|
||||
// Maximum internal mantissa range - rounds down to
|
||||
// maxMantissa/10-1
|
||||
// 99'999'999'999'999'999'800'000'000'000'000'000'100
|
||||
{Number{
|
||||
false, maxInternalMantissa, 0, Number::normalized{}},
|
||||
Number{
|
||||
false, maxInternalMantissa, 0, Number::normalized{}},
|
||||
Number{
|
||||
false,
|
||||
maxInternalMantissa / 10 - 1,
|
||||
20,
|
||||
Number::normalized{}},
|
||||
{Number{false, maxInternalMantissa, 0, Number::normalized{}},
|
||||
Number{false, maxInternalMantissa, 0, Number::normalized{}},
|
||||
Number{false, maxInternalMantissa / 10 - 1, 20, Number::normalized{}},
|
||||
__LINE__},
|
||||
// Maximum mantissa range - same as int64
|
||||
{Number{false, maxMantissa, 0, Number::normalized{}},
|
||||
@@ -686,10 +577,7 @@ public:
|
||||
Number{3111111111111119, -15},
|
||||
Number{1000000000000000, -14},
|
||||
__LINE__},
|
||||
{Number{1000000000000000, -32768},
|
||||
Number{1000000000000000, -32768},
|
||||
Number{0},
|
||||
__LINE__}});
|
||||
{Number{1000000000000000, -32768}, Number{1000000000000000, -32768}, Number{0}, __LINE__}});
|
||||
auto const cLarge = std::to_array<Case>(
|
||||
// Note that items with extremely large mantissas need to be
|
||||
// calculated, because otherwise they overflow uint64. Items
|
||||
@@ -712,10 +600,7 @@ public:
|
||||
Number{3111111111111119, -15},
|
||||
Number{999999999999999958, -17},
|
||||
__LINE__},
|
||||
{Number{1000000000000000000, -32768},
|
||||
Number{1000000000000000000, -32768},
|
||||
Number{0},
|
||||
__LINE__},
|
||||
{Number{1000000000000000000, -32768}, Number{1000000000000000000, -32768}, Number{0}, __LINE__},
|
||||
// Items from cSmall expanded for the larger mantissa,
|
||||
// except duplicates. Sadly, it looks like sqrt(2)^2 != 2
|
||||
// with higher precision
|
||||
@@ -727,20 +612,15 @@ public:
|
||||
Number{1414213562373095048, -18},
|
||||
Number{-1999999999999999997, -18},
|
||||
__LINE__},
|
||||
{Number{-1414213562373095048, -18},
|
||||
Number{-1414213562373095049, -18},
|
||||
Number{2, 0},
|
||||
__LINE__},
|
||||
{Number{-1414213562373095048, -18}, Number{-1414213562373095049, -18}, Number{2, 0}, __LINE__},
|
||||
{Number{3214285714285714278, -18},
|
||||
Number{3111111111111111119, -18},
|
||||
Number{1000000000000000001, -17},
|
||||
__LINE__},
|
||||
// Maximum internal mantissa range - rounds up to
|
||||
// minMantissa*10 1e19*1e19=1e38
|
||||
{Number{
|
||||
false, maxInternalMantissa, 0, Number::normalized{}},
|
||||
Number{
|
||||
false, maxInternalMantissa, 0, Number::normalized{}},
|
||||
{Number{false, maxInternalMantissa, 0, Number::normalized{}},
|
||||
Number{false, maxInternalMantissa, 0, Number::normalized{}},
|
||||
Number{1, 38},
|
||||
__LINE__},
|
||||
// Maximum mantissa range - same as int64
|
||||
@@ -969,10 +849,7 @@ public:
|
||||
*/
|
||||
|
||||
auto const maxInternalMantissa =
|
||||
static_cast<std::uint64_t>(
|
||||
static_cast<std::int64_t>(power(10, Number::mantissaLog()))) *
|
||||
10 -
|
||||
1;
|
||||
static_cast<std::uint64_t>(static_cast<std::int64_t>(power(10, Number::mantissaLog()))) * 10 - 1;
|
||||
|
||||
auto const cSmall = std::to_array<Case>(
|
||||
{{Number{2}, 2, Number{1414213562373095049, -18}},
|
||||
@@ -990,14 +867,9 @@ public:
|
||||
Number{false, 999'999'999'999'999'999, -9, Number::normalized{}}},
|
||||
{Number{false, maxInternalMantissa - 9, 0, Number::normalized{}},
|
||||
2,
|
||||
Number{
|
||||
false, 3'162'277'660'168'379'330, -9, Number::normalized{}}},
|
||||
{Number{Number::largestMantissa},
|
||||
2,
|
||||
Number{false, 3'037'000'499'976049692, -9, Number::normalized{}}},
|
||||
{Number{Number::largestMantissa},
|
||||
4,
|
||||
Number{false, 55'108'98747006743627, -14, Number::normalized{}}},
|
||||
Number{false, 3'162'277'660'168'379'330, -9, Number::normalized{}}},
|
||||
{Number{Number::largestMantissa}, 2, Number{false, 3'037'000'499'976049692, -9, Number::normalized{}}},
|
||||
{Number{Number::largestMantissa}, 4, Number{false, 55'108'98747006743627, -14, Number::normalized{}}},
|
||||
});
|
||||
test(cSmall);
|
||||
if (Number::getMantissaScale() != MantissaRange::small)
|
||||
@@ -1044,8 +916,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
auto const maxInternalMantissa =
|
||||
power(10, Number::mantissaLog()) * 10 - 1;
|
||||
auto const maxInternalMantissa = power(10, Number::mantissaLog()) * 10 - 1;
|
||||
|
||||
auto const cSmall = std::to_array<Number>({
|
||||
Number{2},
|
||||
@@ -1409,12 +1280,8 @@ public:
|
||||
|
||||
auto const maxMantissa = Number::maxMantissa();
|
||||
BEAST_EXPECT(maxMantissa == 9'223'372'036'854'775'807ULL);
|
||||
test(
|
||||
Number{false, maxMantissa, 0, Number::normalized{}},
|
||||
"9223372036854775807");
|
||||
test(
|
||||
Number{true, maxMantissa, 0, Number::normalized{}},
|
||||
"-9223372036854775807");
|
||||
test(Number{false, maxMantissa, 0, Number::normalized{}}, "9223372036854775807");
|
||||
test(Number{true, maxMantissa, 0, Number::normalized{}}, "-9223372036854775807");
|
||||
|
||||
test(Number{std::numeric_limits<std::int64_t>::max(), 0}, "9223372036854775807");
|
||||
test(-(Number{std::numeric_limits<std::int64_t>::max(), 0}), "-9223372036854775807");
|
||||
@@ -1618,44 +1485,27 @@ public:
|
||||
|
||||
{
|
||||
auto const maxInternalMantissa =
|
||||
static_cast<std::uint64_t>(static_cast<std::int64_t>(
|
||||
power(10, Number::mantissaLog()))) *
|
||||
10 -
|
||||
1;
|
||||
static_cast<std::uint64_t>(static_cast<std::int64_t>(power(10, Number::mantissaLog()))) * 10 - 1;
|
||||
|
||||
// Rounds down to fit under 2^63
|
||||
Number const max =
|
||||
Number{false, maxInternalMantissa, 0, Number::normalized{}};
|
||||
Number const max = Number{false, maxInternalMantissa, 0, Number::normalized{}};
|
||||
// No alterations by the accessors
|
||||
BEAST_EXPECT(max.mantissa() == maxInternalMantissa / 10);
|
||||
BEAST_EXPECT(max.exponent() == 1);
|
||||
// 99'999'999'999'999'999'800'000'000'000'000'000'100 - also 38
|
||||
// digits
|
||||
BEAST_EXPECT(
|
||||
(power(max, 2) ==
|
||||
Number{
|
||||
false,
|
||||
maxInternalMantissa / 10 - 1,
|
||||
20,
|
||||
Number::normalized{}}));
|
||||
BEAST_EXPECT((power(max, 2) == Number{false, maxInternalMantissa / 10 - 1, 20, Number::normalized{}}));
|
||||
}
|
||||
|
||||
{
|
||||
auto const maxMantissa = Number::maxMantissa();
|
||||
Number const max =
|
||||
Number{false, maxMantissa, 0, Number::normalized{}};
|
||||
Number const max = Number{false, maxMantissa, 0, Number::normalized{}};
|
||||
// No alterations by the accessors
|
||||
BEAST_EXPECT(max.mantissa() == maxMantissa);
|
||||
BEAST_EXPECT(max.exponent() == 0);
|
||||
// 85'070'591'730'234'615'847'396'907'784'232'501'249 - also 38
|
||||
// digits
|
||||
BEAST_EXPECT(
|
||||
(power(max, 2) ==
|
||||
Number{
|
||||
false,
|
||||
85'070'591'730'234'615'84,
|
||||
19,
|
||||
Number::normalized{}}));
|
||||
BEAST_EXPECT((power(max, 2) == Number{false, 85'070'591'730'234'615'84, 19, Number::normalized{}}));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1677,18 +1527,14 @@ public:
|
||||
auto const normalized = n.normalizeToRange(rangeMin, rangeMax);
|
||||
BEAST_EXPECTS(
|
||||
normalized.first == expectedMantissa,
|
||||
"Number " + to_string(n) + " scaled to " +
|
||||
std::to_string(rangeMax) +
|
||||
"Number " + to_string(n) + " scaled to " + std::to_string(rangeMax) +
|
||||
". Expected mantissa:" + std::to_string(expectedMantissa) +
|
||||
", got: " + std::to_string(normalized.first) + " @ " +
|
||||
std::to_string(line));
|
||||
", got: " + std::to_string(normalized.first) + " @ " + std::to_string(line));
|
||||
BEAST_EXPECTS(
|
||||
normalized.second == expectedExponent,
|
||||
"Number " + to_string(n) + " scaled to " +
|
||||
std::to_string(rangeMax) +
|
||||
"Number " + to_string(n) + " scaled to " + std::to_string(rangeMax) +
|
||||
". Expected exponent:" + std::to_string(expectedExponent) +
|
||||
", got: " + std::to_string(normalized.second) + " @ " +
|
||||
std::to_string(line));
|
||||
", got: " + std::to_string(normalized.second) + " @ " + std::to_string(line));
|
||||
};
|
||||
|
||||
std::int64_t constexpr iRangeMin = 100;
|
||||
@@ -1708,39 +1554,15 @@ public:
|
||||
auto const expectedLargeMantissa,
|
||||
auto const expectedLargeExponent,
|
||||
auto const line) {
|
||||
test(
|
||||
n,
|
||||
iRangeMin,
|
||||
iRangeMax,
|
||||
expectedSmallMantissa,
|
||||
expectedSmallExponent,
|
||||
line);
|
||||
test(
|
||||
n,
|
||||
iBigMin,
|
||||
iBigMax,
|
||||
expectedLargeMantissa,
|
||||
expectedLargeExponent,
|
||||
line);
|
||||
test(n, iRangeMin, iRangeMax, expectedSmallMantissa, expectedSmallExponent, line);
|
||||
test(n, iBigMin, iBigMax, expectedLargeMantissa, expectedLargeExponent, line);
|
||||
|
||||
// Only test non-negative. testing a negative number with an
|
||||
// unsigned range will assert, and asserts can't be tested.
|
||||
if (n.signum() >= 0)
|
||||
{
|
||||
test(
|
||||
n,
|
||||
uRangeMin,
|
||||
uRangeMax,
|
||||
expectedSmallMantissa,
|
||||
expectedSmallExponent,
|
||||
line);
|
||||
test(
|
||||
n,
|
||||
largeRange.min,
|
||||
largeRange.max,
|
||||
expectedLargeMantissa,
|
||||
expectedLargeExponent,
|
||||
line);
|
||||
test(n, uRangeMin, uRangeMax, expectedSmallMantissa, expectedSmallExponent, line);
|
||||
test(n, largeRange.min, largeRange.max, expectedLargeMantissa, expectedLargeExponent, line);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1748,13 +1570,7 @@ public:
|
||||
// zero
|
||||
Number const n{0};
|
||||
|
||||
testSuite(
|
||||
n,
|
||||
0,
|
||||
std::numeric_limits<int>::lowest(),
|
||||
0,
|
||||
std::numeric_limits<int>::lowest(),
|
||||
__LINE__);
|
||||
testSuite(n, 0, std::numeric_limits<int>::lowest(), 0, std::numeric_limits<int>::lowest(), __LINE__);
|
||||
}
|
||||
{
|
||||
// Small positive number
|
||||
@@ -1783,8 +1599,7 @@ public:
|
||||
}
|
||||
{
|
||||
// Biggest valid mantissa + 1
|
||||
Number const n{
|
||||
Number::largestMantissa + 1, 0, Number::normalized{}};
|
||||
Number const n{Number::largestMantissa + 1, 0, Number::normalized{}};
|
||||
|
||||
if (scale == MantissaRange::small)
|
||||
// With the small mantissa range, the value rounds up. Because
|
||||
@@ -1797,8 +1612,7 @@ public:
|
||||
}
|
||||
{
|
||||
// Biggest valid mantissa + 2
|
||||
Number const n{
|
||||
Number::largestMantissa + 2, 0, Number::normalized{}};
|
||||
Number const n{Number::largestMantissa + 2, 0, Number::normalized{}};
|
||||
|
||||
if (scale == MantissaRange::small)
|
||||
// With the small mantissa range, the value rounds up. Because
|
||||
@@ -1811,8 +1625,7 @@ public:
|
||||
}
|
||||
{
|
||||
// Biggest valid mantissa + 3
|
||||
Number const n{
|
||||
Number::largestMantissa + 3, 0, Number::normalized{}};
|
||||
Number const n{Number::largestMantissa + 3, 0, Number::normalized{}};
|
||||
|
||||
if (scale == MantissaRange::small)
|
||||
// With the small mantissa range, the value rounds up. Because
|
||||
@@ -1847,9 +1660,7 @@ public:
|
||||
// number to avoid overflow and UB
|
||||
Number const n{
|
||||
true,
|
||||
-static_cast<std::uint64_t>(
|
||||
std::numeric_limits<std::int64_t>::min()) +
|
||||
1,
|
||||
-static_cast<std::uint64_t>(std::numeric_limits<std::int64_t>::min()) + 1,
|
||||
0,
|
||||
Number::normalized{}};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user