6 #ifndef VNIX_RAT_RATIONAL_HPP 7 #define VNIX_RAT_RATIONAL_HPP 10 #include <vnix/rat/common-denom.hpp> 11 #include <vnix/rat/encoding.hpp> 32 using typename P::stype;
33 using typename P::utype;
54 template <
unsigned ONB,
unsigned ODB>
60 if (d() != 1) {
throw "attempted conversion to integer from fraction"; }
65 constexpr bool to_bool()
const {
return n() != 0; }
68 constexpr float to_float()
const {
return n() * 1.0f / d(); }
71 constexpr double to_double()
const {
return n() * 1.0 / d(); }
78 template <
unsigned ONB,
unsigned ODB>
86 template <
unsigned ONB,
unsigned ODB>
91 if (n() == 0) {
throw "attempt to take reciprocal of zero"; }
92 if (n() < 0) {
return rational(-d(), -n()); }
101 template <
unsigned ONB,
unsigned ODB>
109 template <
unsigned ONB,
unsigned ODB>
127 template <
unsigned NB1,
unsigned DB1,
unsigned NB2,
unsigned DB2>
129 return r1.n() == r2.n() && r1.d() == r2.d();
140 template <
unsigned NB1,
unsigned DB1,
unsigned NB2,
unsigned DB2>
153 template <
unsigned NB1,
unsigned DB1,
unsigned NB2,
unsigned DB2>
155 auto const c = common_denom(r1, r2);
167 template <
unsigned NB1,
unsigned DB1,
unsigned NB2,
unsigned DB2>
169 auto const c = common_denom(r1, r2);
181 template <
unsigned NB1,
unsigned DB1,
unsigned NB2,
unsigned DB2>
194 template <
unsigned NB1,
unsigned DB1,
unsigned NB2,
unsigned DB2>
205 template <
unsigned NB,
unsigned DB>
216 template <
unsigned NB,
unsigned DB>
218 return rational<NB, DB>(-r.n(), r.d());
230 template <
unsigned NB1,
unsigned DB1,
unsigned NB2,
unsigned DB2>
232 auto const c = common_denom(r1, r2);
233 return rational<c.NMR_BITS, c.LCD_BITS>(c.n1 + c.n2, c.lcd);
238 template <
unsigned NB,
unsigned DB>
239 template <
unsigned ONB,
unsigned ODB>
242 return *
this = *
this + r;
254 template <
unsigned NB1,
unsigned DB1,
unsigned NB2,
unsigned DB2>
261 template <
unsigned NB,
unsigned DB>
262 template <
unsigned ONB,
unsigned ODB>
265 return *
this = *
this - r;
277 template <
unsigned NB1,
unsigned DB1,
unsigned NB2,
unsigned DB2>
279 auto const n1 = r1.n();
280 auto const n2 = r2.n();
281 auto const d1 = r1.d();
282 auto const d2 = r2.d();
283 auto const ga = gcd(n1, d2);
284 auto const gb = gcd(n2, d1);
285 enum { NB = (NB1 > NB2 ? NB1 : NB2), DB = (DB1 > DB2 ? DB1 : DB2) };
288 return rational<NB, DB>(S(n1) / ga * n2 / gb, U(d1) / gb * d2 / ga);
300 template <
unsigned NB1,
unsigned DB1,
unsigned NB2,
unsigned DB2>
302 return r1 * r2.reciprocal();
312 template <
unsigned NB1,
unsigned DB1>
314 typename rational<NB1, DB1>::stype r2) {
315 return r1 *
rational<NB1, DB1>(r2).reciprocal();
320 template <
unsigned NB,
unsigned DB>
321 template <
unsigned ONB,
unsigned ODB>
324 return *
this = (*
this) * r;
329 template <
unsigned NB,
unsigned DB>
330 template <
unsigned ONB,
unsigned ODB>
333 return *
this = (*
this) / r;
343 template <
unsigned NB,
unsigned DB>
344 std::ostream &operator<<(std::ostream &s,
rational<NB, DB> r) {
345 s << int_fast64_t(r.n());
346 if (r.d() != 1) { s <<
'/' << uint_fast64_t(r.d()); }
static constexpr utype encode(rational r)
Encoding from rational number.
constexpr auto operator-(rational< NB1, DB1 > r1, rational< NB2, DB2 > r2)
Difference between two rational numbers.
constexpr rational(utype u, dummy_arg)
Construct from encoding.
constexpr rational< NB, DB > & operator-=(rational< ONB, ODB > r)
Numerator and denominator of a rational number as separate numbers, not encoded into the same word...
static constexpr rational decode(utype u)
Rational number from encoding.
constexpr auto operator+(rational< NB, DB > r)
Copy rational number by way of unary operator+.
constexpr float to_float() const
Convert to float.
constexpr auto operator/(rational< NB1, DB1 > r1, typename rational< NB1, DB1 >::stype r2)
Quotient of two rational numbers.
constexpr rational< NB, DB > & operator/=(rational< ONB, ODB > r)
constexpr auto operator*(rational< NB1, DB1 > r1, rational< NB2, DB2 > r2)
Product of two rational numbers.
constexpr double to_double() const
Convert to double.
constexpr rational(rational< ONB, ODB > r)
Initialize from other rational.
constexpr auto operator+(rational< NB1, DB1 > r1, rational< NB2, DB2 > r2)
Sum of two rational numbers.
constexpr rational(stype n=0, stype d=1)
Initialize from numerator and denominator.
Smallest integer types for holding certain number of bits.
constexpr rational reciprocal() const
Reciprocal of this rational number.
constexpr auto operator-(rational< NB, DB > r)
Negate rational number.
constexpr rational< NB, DB > & operator+=(rational< ONB, ODB > r)
constexpr bool operator>(rational< NB1, DB1 > r1, rational< NB2, DB2 > r2)
Compare for greater-than ordering with another rational.
constexpr auto operator/(rational< NB1, DB1 > r1, rational< NB2, DB2 > r2)
Quotient of two rational numbers.
constexpr stype to_int() const
Convert to (signed) integer.
constexpr bool operator==(rational< NB1, DB1 > r1, rational< NB2, DB2 > r2)
Compare rationals for equality.
constexpr bool operator!=(rational< NB1, DB1 > r1, rational< NB2, DB2 > r2)
Compare rationals for inequality.
constexpr bool to_bool() const
Automatically convert to boolean.
constexpr bool operator>=(rational< NB1, DB1 > r1, rational< NB2, DB2 > r2)
Compare for greater-than-or-equal ordering with another rational.
Thomas E. Vaughan's public software.
constexpr bool operator<(rational< NB1, DB1 > r1, rational< NB2, DB2 > r2)
Compare for less-than ordering with another rational.
Model of a fixed-precision rational number.
constexpr rational< NB, DB > & operator*=(rational< ONB, ODB > r)
constexpr bool operator<=(rational< NB1, DB1 > r1, rational< NB2, DB2 > r2)
Compare for less-than-or-equal ordering with another rational.
Classes and functions supporting a model of a fixed-precision rational number.
Encoding of numerator and denominator into unsigned word.