Move mulDiv and lowestTerms to STAmount.cpp

This commit is contained in:
Edward Hennis
2015-07-10 17:47:47 -04:00
parent 656a6c5eb5
commit 382adcc93c
3 changed files with 41 additions and 35 deletions

View File

@@ -25,41 +25,6 @@
namespace ripple { namespace ripple {
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;
}
// TODO REMOVE!
static
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;
}
// Scale from fee units to millionths of a ripple // Scale from fee units to millionths of a ripple
std::uint64_t std::uint64_t
LoadFeeTrack::scaleFeeBase (std::uint64_t fee, std::uint64_t baseFee, LoadFeeTrack::scaleFeeBase (std::uint64_t fee, std::uint64_t baseFee,

View File

@@ -400,6 +400,27 @@ inline bool isXRP(STAmount const& amount)
return isXRP (amount.issue().currency); 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);
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 } // ripple
#endif #endif

View File

@@ -1257,4 +1257,24 @@ divRound (STAmount const& num, STAmount const& den,
return STAmount (issue, amount, offset, resultNegative); return STAmount (issue, amount, offset, resultNegative);
} }
// 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;
}
} // ripple } // ripple