mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
* Otherwise overflow checks result in divide by 0. * If denominator is 0, let the divide by 0 exception throw. * Move mulDiv out of STAmount
81 lines
2.6 KiB
C++
81 lines
2.6 KiB
C++
//------------------------------------------------------------------------------
|
|
/*
|
|
This file is part of rippled: https://github.com/ripple/rippled
|
|
Copyright (c) 2012-2015 Ripple Labs Inc.
|
|
|
|
Permission to use, copy, modify, and/or distribute this software for any
|
|
purpose with or without fee is hereby granted, provided that the above
|
|
copyright notice and this permission notice appear in all copies.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
//==============================================================================
|
|
|
|
#ifndef RIPPLE_BASICS_MULDIV_H_INCLUDED
|
|
#define RIPPLE_BASICS_MULDIV_H_INCLUDED
|
|
|
|
#include <cstdint>
|
|
#include <type_traits>
|
|
#include <utility>
|
|
|
|
namespace ripple
|
|
{
|
|
|
|
/** Return value*mul/div accurately.
|
|
Computes the result of the multiplication and division in
|
|
a single step, avoiding overflow and retaining precision.
|
|
Throws:
|
|
None
|
|
Returns:
|
|
`std::pair`:
|
|
`first` is `false` if the calculation overflows,
|
|
`true` if the calculation is safe.
|
|
`second` is the result of the calculation if
|
|
`first` is `false`, max value of `uint64_t`
|
|
if `true`.
|
|
*/
|
|
std::pair<bool, std::uint64_t>
|
|
mulDiv(std::uint64_t value, std::uint64_t mul, std::uint64_t div);
|
|
|
|
/** Return value*mul/div accurately.
|
|
Computes the result of the multiplication and division in
|
|
a single step, avoiding overflow and retaining precision.
|
|
Throws:
|
|
std::overflow_error
|
|
*/
|
|
std::uint64_t
|
|
mulDivThrow(std::uint64_t value, std::uint64_t mul, std::uint64_t div);
|
|
|
|
template <class T1, class T2,
|
|
class = std::enable_if_t <
|
|
std::is_integral<T1>::value &&
|
|
std::is_unsigned<T1>::value &&
|
|
sizeof(T1) <= sizeof(std::uint64_t) >,
|
|
class = std::enable_if_t <
|
|
std::is_integral<T2>::value &&
|
|
std::is_unsigned<T2>::value &&
|
|
sizeof(T2) <= sizeof(std::uint64_t) >
|
|
>
|
|
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
|