Iros
 
Loading...
Searching...
No Matches
rational.h
Go to the documentation of this file.
1#pragma once
2
4#include "di/math/lcm.h"
6
7namespace di::math {
8template<concepts::SignedInteger T>
9class Rational {
10public:
11 constexpr Rational() : m_numerator(1), m_denominator(1) {}
12
14 DI_ASSERT(m_denominator != T(0));
15
16 normalize();
17 }
18
19 template<concepts::SignedInteger U>
21 constexpr explicit(sizeof(U) <= sizeof(T)) operator Rational<U>() const {
22 return Rational<U> { U(numerator()), U(denominator()) };
23 }
24
25 constexpr auto numerator() const -> T { return m_numerator; }
26 constexpr auto denominator() const -> T { return m_denominator; }
27
28 constexpr auto negative() const -> bool { return m_numerator < 0; }
29
30 constexpr auto add(Rational other) const -> Rational {
31 auto common_denominator = math::lcm(this->denominator(), other.denominator());
32
33 auto a_scaled_numerator = this->numerator() * (common_denominator / this->denominator());
34 auto b_scaled_numerator = other.numerator() * (common_denominator / other.denominator());
35
36 return Rational { a_scaled_numerator + b_scaled_numerator, common_denominator };
37 }
38
39 constexpr auto multiply(Rational other) const -> Rational {
40 return Rational { this->numerator() * other.numerator(), this->denominator() * other.denominator() };
41 }
42
43 constexpr auto subtract(Rational other) const -> Rational { return add(other.negated()); }
44 constexpr auto divide(Rational other) const -> Rational { return multiply(other.inverted()); }
45
46 constexpr auto negated() const -> Rational { return Rational { -numerator(), denominator() }; }
47 constexpr auto inverted() const -> Rational { return Rational { denominator(), numerator() }; }
48
49 constexpr auto round() const -> T {
50 if (negative()) {
51 return -negated().round();
52 }
53
54 auto result = m_numerator / m_denominator;
55 auto midpoint = m_denominator / 2 + (m_denominator % 2 == 1);
56 return result + (m_numerator % m_denominator >= midpoint);
57 }
58
59 constexpr auto operator++() -> Rational& { return *this = add({}); }
60 constexpr auto operator++(int) -> Rational {
61 auto save = *this;
62 *this = add({});
63 return save;
64 }
65
66 constexpr auto operator--() -> Rational& { return *this = subtract({}); }
67 constexpr auto operator--(int) -> Rational {
68 auto save = *this;
69 *this = subtract({});
70 return save;
71 }
72
73 constexpr auto operator+=(Rational a) -> Rational& { return *this = add(a); }
74 constexpr auto operator+(Rational a) const -> Rational { return add(a); }
75
76 constexpr auto operator-=(Rational a) -> Rational& { return *this = subtract(a); }
77 constexpr auto operator-(Rational a) const -> Rational { return subtract(a); }
78
79 constexpr auto operator*=(Rational a) -> Rational& { return *this = multiply(a); }
80 constexpr auto operator*(Rational a) const -> Rational { return multiply(a); }
81
82 constexpr auto operator/=(Rational a) -> Rational& { return *this = divide(a); }
83 constexpr auto operator/(Rational a) const -> Rational { return divide(a); }
84
85 constexpr auto operator-() const -> Rational { return negated(); }
86
87 // These fields are public to enable this class to be used
88 // as a template argument.
91
92private:
93 constexpr friend auto operator==(Rational, Rational) -> bool = default;
94
95 constexpr friend auto operator<=>(Rational a, Rational b) -> strong_ordering {
96 if (auto result = b.negative() <=> a.negative(); result != 0) {
97 return result;
98 }
99
100 auto difference = a.subtract(b);
101 return difference.numerator() <=> T(0);
102 }
103
104 constexpr void normalize() {
105 if ((numerator() < T(0) && denominator() < T(0)) || (numerator() >= T(0) && denominator() < T(0))) {
108 }
109
110 if (numerator() == T(0)) {
111 m_denominator = 1;
112 return;
113 }
114
115 auto gcd = math::gcd(numerator(), denominator());
116 m_numerator /= gcd;
118 }
119};
120
121template<typename T, typename U>
123}
124
125namespace di {
126using math::Rational;
127}
#define DI_ASSERT(...)
Definition assert_bool.h:7
Definition rational.h:9
constexpr auto operator++() -> Rational &
Definition rational.h:59
constexpr auto numerator() const -> T
Definition rational.h:25
constexpr auto round() const -> T
Definition rational.h:49
constexpr auto operator--() -> Rational &
Definition rational.h:66
constexpr friend auto operator==(Rational, Rational) -> bool=default
constexpr auto multiply(Rational other) const -> Rational
Definition rational.h:39
constexpr auto subtract(Rational other) const -> Rational
Definition rational.h:43
constexpr friend auto operator<=>(Rational a, Rational b) -> strong_ordering
Definition rational.h:95
constexpr auto operator-() const -> Rational
Definition rational.h:85
constexpr auto operator--(int) -> Rational
Definition rational.h:67
constexpr auto operator-(Rational a) const -> Rational
Definition rational.h:77
constexpr auto operator++(int) -> Rational
Definition rational.h:60
constexpr auto operator/=(Rational a) -> Rational &
Definition rational.h:82
constexpr auto divide(Rational other) const -> Rational
Definition rational.h:44
constexpr auto operator+=(Rational a) -> Rational &
Definition rational.h:73
constexpr auto operator/(Rational a) const -> Rational
Definition rational.h:83
constexpr Rational()
Definition rational.h:11
constexpr auto inverted() const -> Rational
Definition rational.h:47
constexpr auto negated() const -> Rational
Definition rational.h:46
constexpr auto operator*=(Rational a) -> Rational &
Definition rational.h:79
constexpr auto add(Rational other) const -> Rational
Definition rational.h:30
constexpr Rational(T numerator, T denominator=1)
Definition rational.h:13
constexpr auto operator-=(Rational a) -> Rational &
Definition rational.h:76
constexpr auto negative() const -> bool
Definition rational.h:28
T m_denominator
Definition rational.h:90
constexpr auto operator+(Rational a) const -> Rational
Definition rational.h:74
constexpr auto operator*(Rational a) const -> Rational
Definition rational.h:80
T m_numerator
Definition rational.h:89
constexpr auto denominator() const -> T
Definition rational.h:26
Definition operations.h:11
Definition abs.h:10
constexpr auto lcm
Definition lcm.h:34
constexpr auto midpoint
Definition midpoint.h:36
Rational(T, U) -> Rational< meta::CommonType< T, U > >
constexpr auto gcd
Definition gcd.h:44
Definition zstring_parser.h:9