24 #include "gnc-rational.hpp" 25 #include "gnc-numeric.hpp" 29 m_num(n.num()), m_den(n.denom())
39 m_num (n.num), m_den (n.denom)
64 GncRational::operator gnc_numeric () const noexcept
70 return {
static_cast<int64_t
>(m_num), static_cast<int64_t>(m_den)};
72 catch (std::overflow_error&)
106 *
this = std::move(new_val);
113 *
this = std::move(new_val);
120 *
this = std::move(new_val);
127 *
this = std::move(new_val);
133 if (m_den == b.
denom())
135 auto b_num = b.
num();
136 return m_num < b_num ? -1 : b_num < m_num ? 1 : 0;
140 return a_num < b_num ? -1 : b_num < a_num ? 1 : 0;
143 GncRational::round_param
144 GncRational::prepare_conversion (
GncInt128 new_denom)
const 147 return {m_num, m_den, 0};
149 auto red_conv = conversion.reduce();
151 auto new_num = old_num * red_conv.num();
152 if (new_num.isOverflow())
153 throw std::overflow_error(
"Conversion overflow");
154 auto rem = new_num % red_conv.denom();
155 new_num /= red_conv.denom();
156 return {new_num, red_conv.denom(), rem};
160 GncRational::sigfigs_denom(
unsigned figs)
const noexcept
165 auto num_abs = m_num.abs();
166 bool not_frac = num_abs > m_den;
167 int64_t val{ not_frac ? num_abs / m_den : m_den / num_abs };
175 powten(digits < figs ? figs - digits - 1 : 0) :
176 powten(figs + digits);
182 auto gcd = m_den.
gcd(m_num);
184 throw std::overflow_error(
"Reduce failed, calculation of gcd overflowed.");
191 unsigned int ll_bits = GncInt128::legbits;
194 if (!(m_num.
isBig() || m_den.isBig()))
196 if (m_num.abs() > m_den)
198 auto quot(m_num / m_den);
201 std::ostringstream msg;
202 msg <<
" Cannot be represented as a " 203 <<
"GncNumeric. Its integer value is too large.\n";
204 throw std::overflow_error(msg.str());
211 new_v = convert<RoundType::half_down>(m_den / (m_num.abs() >> ll_bits));
218 catch(
const std::overflow_error& err)
225 auto quot(m_den / m_num);
231 auto divisor = m_den >> ll_bits;
235 oldnum.
div(divisor,
num, rem);
236 auto den = m_den / divisor;
237 num += rem * 2 >= den ? 1 : 0;
246 new_v = convert<RoundType::half_down>(m_den / divisor);
259 if (!(a.valid() && b.
valid()))
260 throw std::range_error(
"Operator+ called with out-of-range operand.");
264 throw std::overflow_error(
"Operator+ overflowed.");
279 if (!(a.valid() && b.
valid()))
280 throw std::range_error(
"Operator* called with out-of-range operand.");
282 if (!(num.valid() && den.valid()))
283 throw std::overflow_error(
"Operator* overflowed.");
291 if (!(a.valid() && b.
valid()))
292 throw std::range_error(
"Operator/ called with out-of-range operand.");
293 auto a_num = a.num(), b_num = b.
num(), a_den = a.denom(), b_den = b.
denom();
295 throw std::underflow_error(
"Divide by 0.");
309 if (a_num.isBig() || a_den.isBig() ||
310 b_num.isBig() || b_den.isBig())
317 GncInt128 num(a_num * b_den), den(a_den * b_num);
318 if (!(num.valid() && den.valid()))
319 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