25 #include "gnc-rational.hpp" 26 #include "gnc-numeric.hpp" 30 m_num(n.num()), m_den(n.denom())
40 m_num (n.num), m_den (n.denom)
65 GncRational::operator gnc_numeric () const noexcept
71 return {
static_cast<int64_t
>(m_num), static_cast<int64_t>(m_den)};
73 catch (std::overflow_error&)
107 *
this = std::move(new_val);
114 *
this = std::move(new_val);
121 *
this = std::move(new_val);
128 *
this = std::move(new_val);
134 if (m_den == b.
denom())
136 auto b_num = b.
num();
137 return m_num < b_num ? -1 : b_num < m_num ? 1 : 0;
141 return a_num < b_num ? -1 : b_num < a_num ? 1 : 0;
144 GncRational::round_param
145 GncRational::prepare_conversion (
GncInt128 new_denom)
const 148 return {m_num, m_den, 0};
150 auto red_conv = conversion.reduce();
152 auto new_num = old_num * red_conv.num();
153 if (new_num.isOverflow())
154 throw std::overflow_error(
"Conversion overflow");
155 auto rem = new_num % red_conv.denom();
156 new_num /= red_conv.denom();
157 return {new_num, red_conv.denom(), rem};
161 GncRational::sigfigs_denom(
unsigned figs)
const noexcept
166 auto num_abs = m_num.abs();
167 bool not_frac = num_abs > m_den;
168 int64_t val{ not_frac ? num_abs / m_den : m_den / num_abs };
176 powten(digits < figs ? figs - digits - 1 : 0) :
177 powten(figs + digits);
183 auto gcd = m_den.
gcd(m_num);
185 throw std::overflow_error(
"Reduce failed, calculation of gcd overflowed.");
192 unsigned int ll_bits = GncInt128::legbits;
195 if (!(m_num.
isBig() || m_den.isBig()))
197 if (m_num.abs() > m_den)
199 auto quot(m_num / m_den);
202 std::ostringstream msg;
203 msg <<
" Cannot be represented as a " 204 <<
"GncNumeric. Its integer value is too large.\n";
205 throw std::overflow_error(msg.str());
212 new_v = convert<RoundType::half_down>(m_den / (m_num.abs() >> ll_bits));
219 catch(
const std::overflow_error& err)
226 auto quot(m_den / m_num);
232 auto divisor = m_den >> ll_bits;
236 oldnum.
div(divisor,
num, rem);
237 auto den = m_den / divisor;
238 num += rem * 2 >= den ? 1 : 0;
247 new_v = convert<RoundType::half_down>(m_den / divisor);
260 if (!(a.valid() && b.
valid()))
261 throw std::range_error(
"Operator+ called with out-of-range operand.");
265 throw std::overflow_error(
"Operator+ overflowed.");
280 if (!(a.valid() && b.
valid()))
281 throw std::range_error(
"Operator* called with out-of-range operand.");
283 if (!(num.valid() && den.valid()))
284 throw std::overflow_error(
"Operator* overflowed.");
292 if (!(a.valid() && b.
valid()))
293 throw std::range_error(
"Operator/ called with out-of-range operand.");
294 auto a_num = a.num(), b_num = b.
num(), a_den = a.denom(), b_den = b.
denom();
296 throw std::underflow_error(
"Divide by 0.");
310 if (a_num.isBig() || a_den.isBig() ||
311 b_num.isBig() || b_den.isBig())
318 GncInt128 num(a_num * b_den), den(a_den * b_num);
319 if (!(num.valid() && den.valid()))
320 throw std::overflow_error(
"Operator/ overflowed.");
bool isBig() const noexcept
GncInt128 gcd(GncInt128 b) const noexcept
Computes the Greatest Common Divisor between the object and parameter.
GncInt128 denom() const noexcept
Denominator accessor.
GncRational inv() const noexcept
Inverts the number, equivalent of /= {1, 1}.
GncRational reduce() const
Return an equivalent fraction with all common factors between the numerator and the denominator remov...
The primary numeric class for representing amounts and values.
Intermediate result overflow.
GncInt128 gcd(int64_t a, int64_t b)
Compute the greatest common denominator of two integers.
bool valid() const noexcept
GncRational abs() const noexcept
Absolute value; return value is always >= 0 and of same magnitude.
gnc_numeric gnc_numeric_error(GNCNumericErrorCode error_code)
Create a gnc_numeric object that signals the error condition noted by error_code, rather than a numbe...
bool isNan() const noexcept
Rational number class using GncInt128 for the numerator and denominator.
bool isZero() const noexcept
GncRational round_to_numeric() const
Round to fit an int64_t, finding the closest possible approximation.
GncInt128 lcm(int64_t a, int64_t b)
Compute the least common multiple of two integers.
GncRational()
Default constructor provides the zero value.
bool is_big() const noexcept
Report if either numerator or denominator are too big to fit in an int64_t.
GncInt128 num() const noexcept
Numerator accessor.
int cmp(GncRational b)
Compare function.
bool valid() const noexcept
Report if both members are valid numbers.
GncRational operator-() const noexcept
Make a new GncRational with the opposite sign.
void div(const GncInt128 &d, GncInt128 &q, GncInt128 &r) const noexcept
Computes a quotient and a remainder, passed as reference parameters.
#define GNC_DENOM_AUTO
Values that can be passed as the 'denom' argument.
bool isOverflow() const noexcept