Skip to content

Commit

Permalink
code(numbers): Created the 'Number' concept to determine whenever a t…
Browse files Browse the repository at this point in the history
…ype satisfies the criteria to be a Number

code(numbers): implemented the basic operations for Rationals
code(numbers): Implemented the implementation of the equality operators for Naturals, Integers and Rationals
code(numbers): implemented some operator overloads for mix arithmetic operations between types
  • Loading branch information
TheRustifyer committed Nov 13, 2023
1 parent 9f4923a commit 569e987
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 15 deletions.
64 changes: 49 additions & 15 deletions zero/ifc/math/numbers.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
export module math.numbers;

import std;
import math.ops;
import math.symbols;

export {
export namespace zero::math {
// Forward declarations
class Natural;
class Integer;
Expand All @@ -14,8 +15,6 @@ export {
class Real;
class Complex;

// TODO adding the set symbols for every type

/// Concept to act as an interface for the abstract concept of 'number' in mathematics.
/// In particular, this interface represents a kind of number that belongs to a concrete set of numbers,
/// for example, the naturals, the integers, the reals, the complex numbers...
Expand All @@ -28,8 +27,8 @@ export {
std::is_same_v<T, Real> ||
std::is_same_v<T, Complex>
) && requires {
T::symbol; /* Check if 'T' has a static member named 'symbol' */
{ T::symbol } -> std::same_as<const MathSymbol&>; // Check if 'T::symbol' has the type MathSymbol
T::symbol; /* Check if 'T' has a static member named 'symbol' */
{ T::symbol } -> std::same_as<const MathSymbol&>; // Check if 'T::symbol' has the type MathSymbol
};

/// A positive integer number
Expand Down Expand Up @@ -69,7 +68,12 @@ export {
[[nodiscard]] inline constexpr Integer operator+(Integer rhs) const noexcept;
[[nodiscard]] inline constexpr Integer operator-(Integer rhs) const noexcept;
[[nodiscard]] inline constexpr Integer operator*(Integer rhs) const noexcept;
[[nodiscard]] inline constexpr Rational operator*(Rational rhs) const noexcept;
[[nodiscard]] inline constexpr Rational operator/(Integer rhs) const noexcept;
[[nodiscard]] inline constexpr bool operator==(Integer rhs) const noexcept;

// Explicit conversion operators
[[nodiscard]] inline explicit operator int() const { return _number; }
};

/// @brief A type that represents rational numbers of the form: ℚ = {a, b ∈ ℤ, b ≠ 0}
Expand Down Expand Up @@ -107,18 +111,11 @@ export {
/// @return a {@link Integer} with the value of the denominator for this rational
[[nodiscard]] inline constexpr Integer denominator() const noexcept { return _denominator; }

// [[nodiscard]] inline constexpr Rational operator+(const Rational rhs) const {
// if constexpr (_denominator == rhs.denominator()) // TODO impl the eq of integers as constexpr for this to work
// return Rational(_number + rhs.number()); // Like fractions
// else { // Unlike fractions
// const auto lcm = zero::math::lcm(_denominator, rhs.denominator());
//
// return Rational(_number + rhs.number());
// }
// }
// Arithmetic operator overloads
[[nodiscard]] inline constexpr Rational operator+(Rational rhs) const;
};

//

// class Real {
// double number; // TODO handle rationals and irrationals with std::variant?
// };
Expand All @@ -131,6 +128,7 @@ export {
}

// TODO move this ones to an internal module partition?? or to a module implementation better?
using namespace zero::math;

/*++++++++ Operator overloads implementations ++++++++++*/
/*+++++++++++++++++ Naturals +++++++++++++++++*/
Expand Down Expand Up @@ -159,6 +157,42 @@ export {
[[nodiscard]] inline constexpr Integer Integer::operator*(const Integer rhs) const noexcept {
return Integer(_number * rhs.number());
}
[[nodiscard]] inline constexpr Rational Integer::operator*(const Rational rhs) const noexcept {
return {_number * rhs.numerator().number(), rhs.denominator().number()};
}
[[nodiscard]] inline constexpr Rational Integer::operator/(const Integer rhs) const noexcept {
return {static_cast<signed int>(_number), static_cast<signed int>(rhs.number())};
}
[[nodiscard]] inline constexpr bool Integer::operator==(const Integer rhs) const noexcept {
return _number == rhs.number();
}

/*+++++++++++++++++ Rationals +++++++++++++++++*/
/// Adds the current rational number to another rational number.
/// @param rhs The rational number to be added.
/// @return The sum of the two rational numbers.
///
/// This method handles both like and unlike fractions. If the denominators of
/// the two fractions are equal, it directly adds the numerators. Otherwise, it
/// finds the least common multiple (LCM) of the denominators and scales the
/// numerators to have the LCM as the common denominator before adding.
[[nodiscard]] inline constexpr Rational Rational::operator+(const Rational rhs) const {
if (_denominator == rhs.denominator())
return {
static_cast<int>(_numerator) + static_cast<int>(rhs.numerator()),
static_cast<int>(_denominator)
}; // Like fractions
else {
const int lhs_numerator = static_cast<int>(_numerator);
const int rhs_numerator = static_cast<int>(rhs._numerator);
const int lhs_denominator = static_cast<int>(_denominator);
const int rhs_denominator = static_cast<int>(rhs._denominator);

const auto lcd = zero::math::lcm(_denominator.number(), rhs.denominator().number());

// Scale numerators to have the common denominator (lcm)
const int numerator = (lhs_numerator * (lcd / lhs_denominator)) + (rhs_numerator * (lcd / rhs_denominator));

return {numerator, lcd};
}
}
2 changes: 2 additions & 0 deletions zero/tests/math/numbers_tests.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "numbers_tests.h"

using namespace zero::math;

TestSuite numbers_suite {"Numbers TS"};

/// Compile time tests for numbers
Expand Down

0 comments on commit 569e987

Please sign in to comment.