mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-27 22:45:52 +00:00
Move mulDiv and lowestTerms to STAmount.cpp
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user