Unified rounding implementation

This commit is contained in:
Robert Bendun 2022-08-21 12:26:45 +02:00
parent eb36ad2c93
commit 617fbac98f

View File

@ -191,12 +191,22 @@ parse_fractional:
return result.simplify(); return result.simplify();
} }
Number Number::floor() const namespace impl
{ {
auto result = *this; enum class Rounding_Mode { Ceil, Floor, Round };
if (den <= -1 || den >= 1) {
static Number round(Number result, Rounding_Mode rm)
{
if (result.den <= -1 || result.den >= 1) {
if (auto const r = result.num % result.den; r != 0) { if (auto const r = result.num % result.den; r != 0) {
result.num += ((num < 0) xor (den < 0) ? 1 : -1) * r; auto const sign = (result.num < 0) xor (result.den < 0) ? -1 : 1;
if (rm == Rounding_Mode::Round)
rm = r * 2 >= result.den ? Rounding_Mode::Ceil : Rounding_Mode::Floor;
if (rm == Rounding_Mode::Floor) result.num -= sign * r;
if (rm == Rounding_Mode::Ceil) result.num += sign * r;
result.num /= result.den; result.num /= result.den;
result.den = 1; result.den = 1;
} else { } else {
@ -205,36 +215,21 @@ Number Number::floor() const
} }
return result; return result;
} }
}
Number Number::floor() const
{
return impl::round(*this, impl::Rounding_Mode::Floor);
}
Number Number::ceil() const Number Number::ceil() const
{ {
auto result = *this; return impl::round(*this, impl::Rounding_Mode::Ceil);
if (den <= -1 || den >= 1) {
if (auto const r = result.num % result.den; r != 0) {
result.num += ((num < 0) xor (den < 0) ? -1 : 1) * r;
result.num /= result.den;
result.den = 1;
} else {
result.simplify_inplace();
}
}
return result;
} }
Number Number::round() const Number Number::round() const
{ {
auto result = *this; return impl::round(*this, impl::Rounding_Mode::Round);
if (den <= -1 || den >= 1) {
if (auto const r = result.num % result.den; r != 0) {
auto const dir = r * 2 >= result.den ? -1 : 1;
result.num += ((num < 0) xor (den < 0) ? dir : -dir) * r;
result.num /= result.den;
result.den = 1;
} else {
result.simplify_inplace();
}
}
return result;
} }
Number Number::inverse() const Number Number::inverse() const