Convert GncRational to throw instead of using a status byte.

More consistent with GncNumeric and saves a word of memory per instance.
Still bleeping huge because the two GncInt128s each need 128 bits (2 or 4 words)
plus a word for status (for 3 bits!).
Also provide a couple of convenience functions, is_big() and valid() to
test if the either numerator and denominator is big or overflowed or NaN.
This commit is contained in:
John Ralls 2017-01-30 15:01:27 -08:00
parent ff7e6a37d5
commit c633e80a24
7 changed files with 169 additions and 148 deletions

View File

@ -211,6 +211,12 @@ GncInt128::isNan () const noexcept
return (m_flags & NaN); return (m_flags & NaN);
} }
bool
GncInt128::valid() const noexcept
{
return !(m_flags & (overflow | NaN));
}
bool bool
GncInt128::isZero() const noexcept GncInt128::isZero() const noexcept
{ {

View File

@ -210,6 +210,10 @@ enum // Values for m_flags
* @return true if the object represents 0. * @return true if the object represents 0.
*/ */
bool isZero() const noexcept; bool isZero() const noexcept;
/**
* @return true if neither the overflow nor nan flags are set.
*/
bool valid() const noexcept;
/** /**
* @return the number of bits used to represent the value * @return the number of bits used to represent the value

View File

@ -328,14 +328,7 @@ GncNumeric::to_decimal(unsigned int max_places) const
return GncNumeric(m_num / excess, powten(max_places)); return GncNumeric(m_num / excess, powten(max_places));
} }
GncRational rr(*this); GncRational rr(*this);
rr.round(powten(max_places), RoundType::never); rr.round(powten(max_places), RoundType::never); //May throw
if (rr.m_error)
{
std::ostringstream msg;
msg << "GncNumeric " << *this
<< " could not be represented as a decimal without rounding.\n";
throw std::range_error(msg.str());
}
/* rr might have gotten reduced a bit too much; if so, put it back: */ /* rr might have gotten reduced a bit too much; if so, put it back: */
unsigned int pwr{1}; unsigned int pwr{1};
for (; pwr <= max_places && !(rr.m_den % powten(pwr)); ++pwr); for (; pwr <= max_places && !(rr.m_den % powten(pwr)); ++pwr);
@ -804,11 +797,8 @@ gnc_numeric_add(gnc_numeric a, gnc_numeric b,
GncRational ar(a), br(b); GncRational ar(a), br(b);
auto sum = ar + br; auto sum = ar + br;
sum.round(denom, static_cast<RoundType>(how & GNC_NUMERIC_RND_MASK)); sum.round(denom, static_cast<RoundType>(how & GNC_NUMERIC_RND_MASK));
if (sum.m_error)
return gnc_numeric_error(sum.m_error); if (sum.is_big() || !sum.valid())
if (sum.m_num.isBig() || sum.m_den.isBig() ||
sum.m_num.isOverflow() || sum.m_den.isOverflow() ||
sum.m_num.isNan() || sum.m_den.isNan())
return gnc_numeric_error(GNC_ERROR_OVERFLOW); return gnc_numeric_error(GNC_ERROR_OVERFLOW);
return GncNumeric(sum); return GncNumeric(sum);
} }
@ -827,6 +817,11 @@ gnc_numeric_add(gnc_numeric a, gnc_numeric b,
PWARN("%s", err.what()); PWARN("%s", err.what());
return gnc_numeric_error(GNC_ERROR_OVERFLOW); return gnc_numeric_error(GNC_ERROR_OVERFLOW);
} }
catch (const std::domain_error& err)
{
PWARN("%s", err.what());
return gnc_numeric_error(GNC_ERROR_REMAINDER);
}
} }
/* ******************************************************************* /* *******************************************************************
@ -854,11 +849,7 @@ gnc_numeric_sub(gnc_numeric a, gnc_numeric b,
GncRational ar(a), br(b); GncRational ar(a), br(b);
auto sum = ar - br; auto sum = ar - br;
sum.round(denom, static_cast<RoundType>(how & GNC_NUMERIC_RND_MASK)); sum.round(denom, static_cast<RoundType>(how & GNC_NUMERIC_RND_MASK));
if (sum.m_error) if (sum.is_big() || !sum.valid())
return gnc_numeric_error(sum.m_error);
if (sum.m_num.isBig() || sum.m_den.isBig() ||
sum.m_num.isOverflow() || sum.m_den.isOverflow() ||
sum.m_num.isNan() || sum.m_den.isNan())
return gnc_numeric_error(GNC_ERROR_OVERFLOW); return gnc_numeric_error(GNC_ERROR_OVERFLOW);
return GncNumeric(sum); return GncNumeric(sum);
} }
@ -877,6 +868,11 @@ gnc_numeric_sub(gnc_numeric a, gnc_numeric b,
PWARN("%s", err.what()); PWARN("%s", err.what());
return gnc_numeric_error(GNC_ERROR_OVERFLOW); return gnc_numeric_error(GNC_ERROR_OVERFLOW);
} }
catch (const std::domain_error& err)
{
PWARN("%s", err.what());
return gnc_numeric_error(GNC_ERROR_REMAINDER);
}
} }
/* ******************************************************************* /* *******************************************************************
@ -903,11 +899,7 @@ gnc_numeric_mul(gnc_numeric a, gnc_numeric b,
GncRational ar(a), br(b); GncRational ar(a), br(b);
auto prod = ar * br; auto prod = ar * br;
prod.round(denom, static_cast<RoundType>(how & GNC_NUMERIC_RND_MASK)); prod.round(denom, static_cast<RoundType>(how & GNC_NUMERIC_RND_MASK));
if (prod.m_error) if (prod.is_big() || !prod.valid())
return gnc_numeric_error(prod.m_error);
if (prod.m_num.isBig() || prod.m_den.isBig() ||
prod.m_num.isOverflow() || prod.m_den.isOverflow() ||
prod.m_num.isNan() || prod.m_den.isNan())
return gnc_numeric_error(GNC_ERROR_OVERFLOW); return gnc_numeric_error(GNC_ERROR_OVERFLOW);
return GncNumeric(prod); return GncNumeric(prod);
} }
@ -926,6 +918,11 @@ gnc_numeric_mul(gnc_numeric a, gnc_numeric b,
PWARN("%s", err.what()); PWARN("%s", err.what());
return gnc_numeric_error(GNC_ERROR_OVERFLOW); return gnc_numeric_error(GNC_ERROR_OVERFLOW);
} }
catch (const std::domain_error& err)
{
PWARN("%s", err.what());
return gnc_numeric_error(GNC_ERROR_REMAINDER);
}
} }
@ -953,11 +950,7 @@ gnc_numeric_div(gnc_numeric a, gnc_numeric b,
GncRational ar(a), br(b); GncRational ar(a), br(b);
auto quot = ar / br; auto quot = ar / br;
quot.round(denom, static_cast<RoundType>(how & GNC_NUMERIC_RND_MASK)); quot.round(denom, static_cast<RoundType>(how & GNC_NUMERIC_RND_MASK));
if (quot.m_error) if (quot.is_big() || !quot.valid())
return gnc_numeric_error(quot.m_error);
if (quot.m_num.isBig() || quot.m_den.isBig() ||
quot.m_num.isOverflow() || quot.m_den.isOverflow() ||
quot.m_num.isNan() || quot.m_den.isNan())
return gnc_numeric_error(GNC_ERROR_OVERFLOW); return gnc_numeric_error(GNC_ERROR_OVERFLOW);
return GncNumeric(quot); return GncNumeric(quot);
} }
@ -976,6 +969,11 @@ gnc_numeric_div(gnc_numeric a, gnc_numeric b,
PWARN("%s", err.what()); PWARN("%s", err.what());
return gnc_numeric_error(GNC_ERROR_OVERFLOW); return gnc_numeric_error(GNC_ERROR_OVERFLOW);
} }
catch (const std::domain_error& err)
{
PWARN("%s", err.what());
return gnc_numeric_error(GNC_ERROR_REMAINDER);
}
} }
/* ******************************************************************* /* *******************************************************************
@ -1056,7 +1054,11 @@ gnc_numeric_reduce(gnc_numeric in)
PWARN("%s", err.what()); PWARN("%s", err.what());
return gnc_numeric_error(GNC_ERROR_ARG); return gnc_numeric_error(GNC_ERROR_ARG);
} }
catch (const std::domain_error& err)
{
PWARN("%s", err.what());
return gnc_numeric_error(GNC_ERROR_REMAINDER);
}
} }
@ -1112,6 +1114,11 @@ gnc_numeric_invert(gnc_numeric num)
PWARN("%s", err.what()); PWARN("%s", err.what());
return gnc_numeric_error(GNC_ERROR_ARG); return gnc_numeric_error(GNC_ERROR_ARG);
} }
catch (const std::domain_error& err)
{
PWARN("%s", err.what());
return gnc_numeric_error(GNC_ERROR_REMAINDER);
}
} }
/* ******************************************************************* /* *******************************************************************
@ -1144,6 +1151,11 @@ double_to_gnc_numeric(double in, gint64 denom, gint how)
PWARN("%s", err.what()); PWARN("%s", err.what());
return gnc_numeric_error(GNC_ERROR_ARG); return gnc_numeric_error(GNC_ERROR_ARG);
} }
catch (const std::domain_error& err)
{
PWARN("%s", err.what());
return gnc_numeric_error(GNC_ERROR_REMAINDER);
}
} }
/* ******************************************************************* /* *******************************************************************

View File

@ -26,7 +26,7 @@
GncRational::GncRational(GncNumeric n) noexcept : GncRational::GncRational(GncNumeric n) noexcept :
m_num(n.num()), m_den(n.denom()), m_error(GNC_ERROR_OK) m_num(n.num()), m_den(n.denom())
{ {
if (m_den.isNeg()) if (m_den.isNeg())
{ {
@ -36,7 +36,7 @@ GncRational::GncRational(GncNumeric n) noexcept :
} }
GncRational::GncRational (gnc_numeric n) noexcept : GncRational::GncRational (gnc_numeric n) noexcept :
m_num (n.num), m_den (n.denom), m_error {GNC_ERROR_OK} m_num (n.num), m_den (n.denom)
{ {
if (m_den.isNeg()) if (m_den.isNeg())
{ {
@ -45,13 +45,26 @@ GncRational::GncRational (gnc_numeric n) noexcept :
} }
} }
bool
GncRational::valid() const noexcept
{
if (m_num.valid() && m_den.valid())
return true;
return false;
}
bool
GncRational::is_big() const noexcept
{
if (m_num.isBig() || m_den.isBig())
return true;
return false;
}
GncRational::operator gnc_numeric () const noexcept GncRational::operator gnc_numeric () const noexcept
{ {
if (m_num.isOverflow() || m_num.isNan() || if (!valid())
m_den.isOverflow() || m_den.isNan())
return gnc_numeric_error(GNC_ERROR_OVERFLOW); return gnc_numeric_error(GNC_ERROR_OVERFLOW);
if (m_error != GNC_ERROR_OK)
return gnc_numeric_error (m_error);
try try
{ {
return {static_cast<int64_t>(m_num), static_cast<int64_t>(m_den)}; return {static_cast<int64_t>(m_num), static_cast<int64_t>(m_den)};
@ -87,16 +100,12 @@ GncRational::inv () noexcept
GncRational GncRational
operator+(GncRational a, GncRational b) operator+(GncRational a, GncRational b)
{ {
if (a.m_error || b.m_error) if (!(a.valid() && b.valid()))
{ throw std::range_error("Operator+ called with out-of-range operand.");
if (b.m_error)
return GncRational(0, 1, b.m_error);
return GncRational(0, 1, a.m_error);
}
GncInt128 lcm = a.m_den.lcm(b.m_den); GncInt128 lcm = a.m_den.lcm(b.m_den);
GncInt128 num(a.m_num * lcm / a.m_den + b.m_num * lcm / b.m_den); GncInt128 num(a.m_num * lcm / a.m_den + b.m_num * lcm / b.m_den);
if (lcm.isOverflow() || lcm.isNan() || num.isOverflow() || num.isNan()) if (!(lcm.valid() && num.valid()))
return GncRational(0, 1, GNC_ERROR_OVERFLOW); throw std::overflow_error("Operator+ overflowed.");
GncRational retval(num, lcm); GncRational retval(num, lcm);
return retval; return retval;
} }
@ -111,15 +120,11 @@ operator-(GncRational a, GncRational b)
GncRational GncRational
operator*(GncRational a, GncRational b) operator*(GncRational a, GncRational b)
{ {
if (a.m_error || b.m_error) if (!(a.valid() && b.valid()))
{ throw std::range_error("Operator* called with out-of-range operand.");
if (b.m_error)
return GncRational(0, 1, b.m_error);
return GncRational(0, 1, a.m_error);
}
GncInt128 num (a.m_num * b.m_num), den(a.m_den * b.m_den); GncInt128 num (a.m_num * b.m_num), den(a.m_den * b.m_den);
if (num.isOverflow() || num.isNan() || den.isOverflow() || den.isNan()) if (!(num.valid() && den.valid()))
return GncRational(0, 1, GNC_ERROR_OVERFLOW); throw std::overflow_error("Operator* overflowed.");
GncRational retval(num, den); GncRational retval(num, den);
return retval; return retval;
} }
@ -127,12 +132,10 @@ operator*(GncRational a, GncRational b)
GncRational GncRational
operator/(GncRational a, GncRational b) operator/(GncRational a, GncRational b)
{ {
if (a.m_error || b.m_error) if (!(a.valid() && b.valid()))
{ throw std::range_error("Operator/ called with out-of-range operand.");
if (b.m_error) if (b.m_num == 0)
return GncRational(0, 1, b.m_error); throw std::underflow_error("Divide by 0.");
return GncRational(0, 1, a.m_error);
}
if (b.m_num.isNeg()) if (b.m_num.isNeg())
{ {
a.m_num = -a.m_num; a.m_num = -a.m_num;
@ -155,8 +158,8 @@ operator/(GncRational a, GncRational b)
} }
GncInt128 num(a.m_num * b.m_den), den(a.m_den * b.m_num); GncInt128 num(a.m_num * b.m_den), den(a.m_den * b.m_num);
if (num.isOverflow() || num.isNan() || den.isOverflow() || den.isNan()) if (!(num.valid() && den.valid()))
return GncRational(0, 1, GNC_ERROR_OVERFLOW); throw std::overflow_error("Operator/ overflowed.");
return GncRational(num, den); return GncRational(num, den);
} }
@ -261,8 +264,7 @@ GncRational::round (GncInt128 new_den, RoundType rtype)
switch (rtype) switch (rtype)
{ {
case RoundType::never: case RoundType::never:
m_error = GNC_ERROR_REMAINDER; throw std::domain_error("Rounding required when 'never round' specified.");
return;
case RoundType::floor: case RoundType::floor:
if (new_num.isNeg()) ++new_num; if (new_num.isNeg()) ++new_num;
break; break;

View File

@ -37,16 +37,23 @@ enum class DenomType;
class GncRational class GncRational
{ {
public: public:
GncRational() : m_num(0), m_den(1), m_error(GNC_ERROR_OK) {} GncRational() : m_num(0), m_den(1) {}
GncRational (gnc_numeric n) noexcept; GncRational (gnc_numeric n) noexcept;
GncRational(GncNumeric n) noexcept; GncRational(GncNumeric n) noexcept;
GncRational (GncInt128 num, GncInt128 den, GncRational (GncInt128 num, GncInt128 den) noexcept
GNCNumericErrorCode err=GNC_ERROR_OK) noexcept : m_num(num), m_den(den) {}
: m_num(num), m_den(den), m_error(err) {}
GncRational(const GncRational& rhs) = default; GncRational(const GncRational& rhs) = default;
GncRational(GncRational&& rhs) = default; GncRational(GncRational&& rhs) = default;
GncRational& operator=(const GncRational& rhs) = default; GncRational& operator=(const GncRational& rhs) = default;
GncRational& operator=(GncRational&& rhs) = default; GncRational& operator=(GncRational&& rhs) = default;
/** Report if both members are valid numbers.
* \return true if neither numerator nor denominator are Nan or Overflowed.
*/
bool valid() const noexcept;
/** Report if either numerator or denominator are too big to fit in an int64_t.
* \return true if either is too big.
*/
bool is_big() const noexcept;
/** Conversion operator; use static_cast<gnc_numeric>(foo). */ /** Conversion operator; use static_cast<gnc_numeric>(foo). */
operator gnc_numeric() const noexcept; operator gnc_numeric() const noexcept;
/** Make a new GncRational with the opposite sign. */ /** Make a new GncRational with the opposite sign. */
@ -78,7 +85,6 @@ public:
GncInt128 m_num; GncInt128 m_num;
GncInt128 m_den; GncInt128 m_den;
GNCNumericErrorCode m_error;
}; };
GncRational operator+(GncRational a, GncRational b); GncRational operator+(GncRational a, GncRational b);

View File

@ -499,7 +499,7 @@ TEST(gnc_numeric_functions, test_conversion_to_decimal)
EXPECT_EQ(1000, r.denom()); EXPECT_EQ(1000, r.denom());
EXPECT_THROW(r = a.to_decimal(2), std::range_error); EXPECT_THROW(r = a.to_decimal(2), std::range_error);
GncNumeric b(123456789, 456); GncNumeric b(123456789, 456);
EXPECT_THROW(r = b.to_decimal(), std::range_error); EXPECT_THROW(r = b.to_decimal(), std::domain_error);
GncNumeric c(123456789, 450); GncNumeric c(123456789, 450);
EXPECT_NO_THROW(r = c.to_decimal()); EXPECT_NO_THROW(r = c.to_decimal());
EXPECT_EQ(27434842, r.num()); EXPECT_EQ(27434842, r.num());

View File

@ -28,118 +28,109 @@
TEST(gncrational_constructors, test_default_constructor) TEST(gncrational_constructors, test_default_constructor)
{ {
GncRational value; EXPECT_NO_THROW({
EXPECT_EQ(value.m_num, 0); GncRational value;
EXPECT_EQ(value.m_den, 1); EXPECT_EQ(value.m_num, 0);
EXPECT_EQ(value.m_error, GNC_ERROR_OK); EXPECT_EQ(value.m_den, 1);
});
} }
TEST(gncrational_constructors, test_gnc_numeric_constructor) TEST(gncrational_constructors, test_gnc_numeric_constructor)
{ {
gnc_numeric input = gnc_numeric_create(123, 456); gnc_numeric input = gnc_numeric_create(123, 456);
GncRational value(input); EXPECT_NO_THROW({
EXPECT_EQ(input.num, value.m_num); GncRational value(input);
EXPECT_EQ(input.denom, value.m_den); EXPECT_EQ(input.num, value.m_num);
EXPECT_EQ(value.m_error, GNC_ERROR_OK); EXPECT_EQ(input.denom, value.m_den);
});
} }
TEST(gncrational_constructors, test_gnc_int128_constructor) TEST(gncrational_constructors, test_gnc_int128_constructor)
{ {
GncInt128 num(123), denom(456); GncInt128 num(123), denom(456);
GncRational value(num, denom); EXPECT_NO_THROW({
EXPECT_EQ(123, value.m_num); GncRational value(num, denom);
EXPECT_EQ(456, value.m_den); EXPECT_EQ(123, value.m_num);
EXPECT_EQ(GNC_ERROR_OK, value.m_error); EXPECT_EQ(456, value.m_den);
});
} }
TEST(gncrational_constructors, test_implicit_int_constructor) TEST(gncrational_constructors, test_implicit_int_constructor)
{ {
int num(123), denom(456); int num(123), denom(456);
GncRational value(num, denom); EXPECT_NO_THROW({
EXPECT_EQ(123, value.m_num); GncRational value(num, denom);
EXPECT_EQ(456, value.m_den); EXPECT_EQ(123, value.m_num);
EXPECT_EQ(GNC_ERROR_OK, value.m_error); EXPECT_EQ(456, value.m_den);
} });
TEST(gncrational_constructors, test_with_error_code)
{
int num(123), denom(456);
GncRational value(num, denom, GNC_ERROR_OVERFLOW);
EXPECT_EQ(123, value.m_num);
EXPECT_EQ(456, value.m_den);
EXPECT_EQ(GNC_ERROR_OVERFLOW, value.m_error);
} }
TEST(gncrational_operators, test_addition) TEST(gncrational_operators, test_addition)
{ {
GncRational a(123456789987654321, 1000000000); EXPECT_NO_THROW({
GncRational b(65432198765432198, 100000000); GncRational a(123456789987654321, 1000000000);
GncRational c = a + b; GncRational b(65432198765432198, 100000000);
EXPECT_EQ (777778777641976301, c.m_num); GncRational c = a + b;
EXPECT_EQ (1000000000, c.m_den); EXPECT_EQ (777778777641976301, c.m_num);
EXPECT_EQ (GNC_ERROR_OK, c.m_error); EXPECT_EQ (1000000000, c.m_den);
a += b; a += b;
EXPECT_EQ (777778777641976301, a.m_num); EXPECT_EQ (777778777641976301, a.m_num);
EXPECT_EQ (1000000000, a.m_den); EXPECT_EQ (1000000000, a.m_den);
EXPECT_EQ (GNC_ERROR_OK, a.m_error); });
} }
TEST(gncrational_operators, test_subtraction) TEST(gncrational_operators, test_subtraction)
{ {
GncRational a(123456789987654321, 1000000000); EXPECT_NO_THROW({
GncRational b(65432198765432198, 100000000); GncRational a(123456789987654321, 1000000000);
GncRational c = a - b; GncRational b(65432198765432198, 100000000);
EXPECT_EQ (-530865197666667659, c.m_num); GncRational c = a - b;
EXPECT_TRUE(c.m_num.isNeg()); EXPECT_EQ (-530865197666667659, c.m_num);
EXPECT_EQ (1000000000, c.m_den); EXPECT_TRUE(c.m_num.isNeg());
EXPECT_EQ (GNC_ERROR_OK, c.m_error); EXPECT_EQ (1000000000, c.m_den);
c = b - a; c = b - a;
EXPECT_EQ (530865197666667659, c.m_num); EXPECT_EQ (530865197666667659, c.m_num);
EXPECT_FALSE(c.m_num.isNeg()); EXPECT_FALSE(c.m_num.isNeg());
EXPECT_EQ (1000000000, c.m_den); EXPECT_EQ (1000000000, c.m_den);
EXPECT_EQ (GNC_ERROR_OK, c.m_error); a -= b;
a -= b; EXPECT_EQ (-530865197666667659, a.m_num);
EXPECT_EQ (-530865197666667659, a.m_num); EXPECT_TRUE(a.m_num.isNeg());
EXPECT_TRUE(a.m_num.isNeg()); EXPECT_EQ (1000000000, a.m_den);
EXPECT_EQ (1000000000, a.m_den); });
EXPECT_EQ (GNC_ERROR_OK, a.m_error);
} }
TEST(gncrational_operators, test_multiplication) TEST(gncrational_operators, test_multiplication)
{ {
GncRational a(123456789987654321, 1000000000); EXPECT_NO_THROW({
GncRational b(65432198765432198, 100000000); GncRational a(123456789987654321, 1000000000);
GncRational c = a * b; GncRational b(65432198765432198, 100000000);
EXPECT_EQ (GncInt128(UINT64_C(437911925765117), GncRational c = a * b;
UINT64_C(8081008345983448486)), c.m_num); EXPECT_EQ (GncInt128(UINT64_C(437911925765117),
EXPECT_EQ (100000000000000000, c.m_den); UINT64_C(8081008345983448486)), c.m_num);
EXPECT_EQ (GNC_ERROR_OK, c.m_error); EXPECT_EQ (100000000000000000, c.m_den);
a *= b; a *= b;
EXPECT_EQ (GncInt128(UINT64_C(437911925765117), EXPECT_EQ (GncInt128(UINT64_C(437911925765117),
UINT64_C(8081008345983448486)), a.m_num); UINT64_C(8081008345983448486)), a.m_num);
EXPECT_EQ (100000000000000000, a.m_den); EXPECT_EQ (100000000000000000, a.m_den);
EXPECT_EQ (GNC_ERROR_OK, a.m_error); });
} }
TEST(gncrational_operators, test_division) TEST(gncrational_operators, test_division)
{ {
GncRational a(123456789987654321, 1000000000); EXPECT_NO_THROW({
GncRational b(65432198765432198, 100000000); GncRational a(123456789987654321, 1000000000);
GncRational c = a / b; GncRational b(65432198765432198, 100000000);
EXPECT_EQ (GncInt128(UINT64_C(669260), UINT64_C(11059994577585475840)), GncRational c = a / b;
c.m_num); EXPECT_EQ (GncInt128(UINT64_C(669260),
EXPECT_EQ (GncInt128(UINT64_C(3547086), UINT64_C(11115994079396609024)), UINT64_C(11059994577585475840)), c.m_num);
c.m_den); EXPECT_EQ (GncInt128(UINT64_C(3547086),
EXPECT_EQ (GNC_ERROR_OK, c.m_error); UINT64_C(11115994079396609024)), c.m_den);
a /= b;
a /= b; EXPECT_EQ (GncInt128(UINT64_C(669260),
EXPECT_EQ (GncInt128(UINT64_C(669260), UINT64_C(11059994577585475840)), UINT64_C(11059994577585475840)), a.m_num);
a.m_num); EXPECT_EQ (GncInt128(UINT64_C(3547086),
EXPECT_EQ (GncInt128(UINT64_C(3547086), UINT64_C(11115994079396609024)), UINT64_C(11115994079396609024)), a.m_den);
a.m_den); });
EXPECT_EQ (GNC_ERROR_OK, c.m_error);
} }
TEST(gncrational_functions, test_round_to_numeric) TEST(gncrational_functions, test_round_to_numeric)