@@ -118,30 +118,40 @@ export namespace zero::math {
118118
119119 [[nodiscard]] constexpr Rational (int numerator, int denominator) noexcept
120120 : _numerator(numerator), _denominator(denominator) {}
121+
121122 [[nodiscard]] constexpr Rational (Natural numerator, Natural denominator) noexcept
122123 : _numerator(static_cast <Natural>(numerator)), _denominator(static_cast <Natural>(denominator)) {}
124+
123125 [[nodiscard]] constexpr Rational (Integer numerator, Integer denominator) noexcept
124126 : _numerator(numerator), _denominator(denominator) {}
125127
126128 // / @return a {@link Integer} with the value of the numerator for this rational
127129 [[nodiscard]] inline constexpr Integer numerator () const noexcept { return _numerator; }
130+
128131 // / @return a {@link Integer} with the value of the denominator for this rational
129132 [[nodiscard]] inline constexpr Integer denominator () const noexcept { return _denominator; }
130133
134+ // TODO Add a method to reduce fractions
135+
131136 // Arithmetic operator overloads
132- [[nodiscard]] inline constexpr Rational operator +(Rational rhs) const ;
137+ [[nodiscard]] inline constexpr Rational operator +(const Rational &rhs) const ;
138+ [[nodiscard]] inline constexpr Rational operator -(const Rational &rhs) const ;
139+
133140 // TODO complete arithmetic overloads
134141 // Comparison operator overloads
135142 [[nodiscard]] inline constexpr bool operator ==(Rational rhs) const noexcept ;
143+
136144 // Printable
137- inline constexpr friend std::ostream& operator <<(std::ostream& os, const Rational& rhs) {
145+ inline friend std::ostream & operator <<(std::ostream& os, const Rational& rhs) {
138146 os << rhs._numerator ;
139- os << 0x2044 ;
147+ os << MathSymbol::DivisionSlash ;
140148 os << rhs._denominator ;
141149 return os;
142150 }
143- };
144151
152+ private:
153+ [[nodiscard]] inline constexpr Rational sum_or_subtract (const Rational &rhs, int sign) const ;
154+ };
145155
146156// class Real {
147157// double number; // TODO handle rationals and irrationals with std::variant?
@@ -210,56 +220,51 @@ using namespace zero::math;
210220 /* +++++++++++++++++ Rationals +++++++++++++++++*/
211221// Arithmetic
212222
213- // / Adds the current rational number to another rational number.
214- // / @param rhs The rational number to be added.
223+ // Addition operator
224+ [[nodiscard]] inline constexpr Rational Rational::operator +(const Rational& rhs) const {
225+ return this ->sum_or_subtract (rhs, 1 );
226+ }
227+
228+ // Subtraction operator
229+ [[nodiscard]] inline constexpr Rational Rational::operator -(const Rational& rhs) const {
230+ return this ->sum_or_subtract (rhs, -1 );
231+ }
232+
233+ // / Private helper function to perform the common logic for addition and subtraction
234+ // / @param rhs The rational number to be added or subtracted.
235+ // / \param sign
215236// / @return The sum of the two rational numbers.
216237// /
217238// / This method handles both like and unlike fractions. If the denominators of
218239// / the two fractions are equal, it directly adds the numerators. Otherwise, it
219240// / finds the least common multiple (LCM) of the denominators and scales the
220241// / numerators to have the LCM as the common denominator before adding.
221- [[nodiscard]] inline constexpr Rational Rational:: operator +( const Rational rhs) const {
222- if (_denominator == rhs. denominator ()) // Like fractions
223- return {
224- static_cast <int >(_numerator) + static_cast <int >(rhs.numerator ()),
242+ // TODO move to the future impl module
243+ [[nodiscard]] inline constexpr Rational Rational::sum_or_subtract ( const Rational& rhs, int sign) const {
244+ if (_denominator == rhs. denominator ()) { // Like fractions
245+ return { static_cast <int >(_numerator) + sign * static_cast <int >(rhs.numerator ()),
225246 static_cast <int >(_denominator)
226247 };
227- else { // Unlike fractions
248+ } else { // Unlike fractions
228249 const int lhs_numerator = static_cast <int >(_numerator);
229- const int rhs_numerator = static_cast <int >(rhs._numerator );
250+ const int rhs_numerator = sign * static_cast <int >(rhs._numerator );
230251 const int lhs_denominator = static_cast <int >(_denominator);
231252 const int rhs_denominator = static_cast <int >(rhs._denominator );
232253
233254 // Get their lcd by finding their lcm
234255 const auto lcd = zero::math::lcm (_denominator.number (), rhs.denominator ().number ());
235256
236257 // Scale numerators to have the common denominator (lcm)
237- const int numerator = (lhs_numerator * (lcd / lhs_denominator)) + (rhs_numerator * (lcd / rhs_denominator));
258+ const int numerator = (lhs_numerator * (lcd / lhs_denominator)) + (sign * rhs_numerator * (lcd / rhs_denominator));
238259
239260 return {numerator, lcd};
240261 }
241262}
242263
243264// Equality
244265
245- // TODO should we check that 4/2 is the same as 2/1 right? Or we should maintain the difference and explictly
266+ // TODO should we check that 4/2 is the same as 2/1 right? Or we should maintain the difference and explicitly
246267// say that 4/2 aren't the same Rational number as 2/1?
247268[[nodiscard]] inline constexpr bool Rational::operator ==(const Rational rhs) const noexcept {
248269 return _numerator == rhs.numerator () && _denominator == rhs.denominator ();
249270}
250-
251- /* +++++++++++++++++ oss operator overloads (oss) +++++++++++++++++*/
252- // inline constexpr std::ostream& Natural::operator<<(std::ostream& os) {
253- // os << _number;
254- // return os;
255- // }
256- // inline constexpr std::ostream& Integer::operator<<(std::ostream& os) {
257- // os << _number;
258- // return os;
259- // }
260- // inline constexpr std::ostream& Rational::operator<<(std::ostream& os) {
261- // os << _numerator;
262- // os << 0x2044;
263- // os << _denominator;
264- // return os;
265- // }
0 commit comments