mulDiv returns 0 if numerator is 0 and denominator isn't:

* Otherwise overflow checks result in divide by 0.
* If denominator is 0, let the divide by 0 exception throw.
* Move mulDiv out of STAmount
This commit is contained in:
Edward Hennis
2015-11-10 20:48:43 -05:00
committed by seelabs
parent 2c9c3f4b6e
commit e78b8e4cf3
11 changed files with 266 additions and 81 deletions

View File

@@ -418,35 +418,6 @@ inline bool isXRP(STAmount const& amount)
return isXRP (amount.issue().currency);
}
/**
A utility function to compute (value)*(mul)/(div) while avoiding
overflow but keeping precision.
*/
std::uint64_t
mulDiv(std::uint64_t value, std::uint64_t mul, std::uint64_t div);
/**
A utility function to compute (value)*(mul)/(div) while avoiding
overflow but keeping precision. Will return the max uint64_t
value if mulDiv would overflow anyway.
*/
std::uint64_t
mulDivNoThrow(std::uint64_t value, std::uint64_t mul, std::uint64_t div);
template <class T1, class T2>
void lowestTerms(T1& a, T2& b)
{
std::uint64_t x = a, y = b;
while (y != 0)
{
auto t = x % y;
x = y;
y = t;
}
a /= x;
b /= x;
}
} // ripple
#endif

View File

@@ -1275,40 +1275,6 @@ divRound (STAmount const& num, STAmount const& den,
return result;
}
// compute (value)*(mul)/(div) - avoid overflow but keep precision
std::uint64_t
mulDiv(std::uint64_t value, std::uint64_t mul, std::uint64_t div)
{
lowestTerms(value, div);
lowestTerms(mul, div);
if (value < mul)
std::swap(value, mul);
const auto max = std::numeric_limits<std::uint64_t>::max();
if (value > max / mul)
{
value /= div;
if (value > max / mul)
Throw<std::overflow_error> ("mulDiv");
return value * mul;
}
return value * mul / div;
}
// compute (value)*(mul)/(div) - avoid overflow but keep precision
std::uint64_t
mulDivNoThrow(std::uint64_t value, std::uint64_t mul, std::uint64_t div)
{
try
{
return mulDiv(value, mul, div);
}
catch (std::overflow_error)
{
return std::numeric_limits<std::uint64_t>::max();
}
}
NetClock::time_point
STAmountCalcSwitchovers::enableUnderflowFixCloseTime ()
{