Skip to content

Commit

Permalink
feat: enumerated type for represent via a compile time constant a nam…
Browse files Browse the repository at this point in the history
…ed arithmetic operation
  • Loading branch information
TheRustifyer committed Sep 7, 2024
1 parent 9d5ecc6 commit a23a009
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 35 deletions.
12 changes: 10 additions & 2 deletions zero/ifc/math/general.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,17 @@ export module math:general;
import std;
import math.symbols;

/// Forward declarations of the 'Numbers types', so they can be shared across different
/// module partitions of 'math'
export namespace zero::math {
/// Compile time constants for represent an arithmetic operation via literal constants
enum class ArithmeticOperation {
Add,
Subtract,
Multiply,
Divide
};

/// Forward declarations of the 'Numbers types', so they can be shared across different
/// module partitions of 'math'
class Natural;
class Integer;
class Rational;
Expand Down
63 changes: 45 additions & 18 deletions zero/ifc/math/numbers/detail.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import std;
import math.ops;
import math.symbols;

import :general;
import :numbers.naturals;
import :numbers.integers;
import :numbers.rationals;
Expand Down Expand Up @@ -44,32 +45,58 @@ constexpr auto arithmetic_op(const L &lhs, const R &rhs, Op op) noexcept {

// Specialized addition and subtraction for Rational types
template <typename L, typename R>
constexpr auto rational_add_or_subtract(const L &lhs, const R &rhs, int sign) noexcept {
if constexpr (std::is_same_v<L, Rational> && std::is_same_v<R, Rational>) {
return sum_or_subtract(lhs, rhs, sign);
} else if constexpr (std::is_same_v<L, Rational>) {
return sum_or_subtract(lhs, Rational(rhs), sign);
} else if constexpr (std::is_same_v<R, Rational>) {
return sum_or_subtract(Rational(lhs), rhs, sign);
}
constexpr auto rational_add(const L &lhs, const R &rhs) noexcept {
const auto op = ArithmeticOperation::Add;
if constexpr (std::is_same_v<L, Rational> && std::is_same_v<R, Rational>)
return sum_or_subtract(lhs, rhs, op);
else if constexpr (std::is_same_v<L, Rational>)
return sum_or_subtract(lhs, Rational(rhs), op);
else if constexpr (std::is_same_v<R, Rational>)
return sum_or_subtract(Rational(lhs), rhs, op);
}

template <typename L, typename R>
constexpr auto rational_subtract(const L &lhs, const R &rhs) noexcept {
const auto op = ArithmeticOperation::Subtract;
if constexpr (std::is_same_v<L, Rational> && std::is_same_v<R, Rational>)
return sum_or_subtract(lhs, rhs, op);
else if constexpr (std::is_same_v<L, Rational>)
return sum_or_subtract(lhs, Rational(rhs), op);
else if constexpr (std::is_same_v<R, Rational>)
return sum_or_subtract(Rational(lhs), rhs, op);
}

template <typename L, typename R>
constexpr auto rational_mult(const L &lhs, const R &rhs) noexcept {
if constexpr (std::is_same_v<std::decay_t<decltype(lhs)>, Rational> &&
std::is_same_v<std::decay_t<decltype(rhs)>, Rational>) {
return Rational(lhs.numerator() * rhs.numerator(),
lhs.denominator() * rhs.denominator());
} else if constexpr (std::is_same_v<std::decay_t<decltype(lhs)>, Rational>) {
return Rational(lhs.numerator() * normalize(rhs), lhs.denominator());
} else if constexpr (std::is_same_v<std::decay_t<decltype(rhs)>, Rational>) {
return Rational(normalize(lhs) * rhs.numerator(), rhs.denominator());
}
if constexpr (std::is_same_v<std::decay_t<decltype(lhs)>, Rational> &&
std::is_same_v<std::decay_t<decltype(rhs)>, Rational>)
return Rational(lhs.numerator() * rhs.numerator(),
lhs.denominator() * rhs.denominator());
else if constexpr (std::is_same_v<std::decay_t<decltype(lhs)>, Rational>)
return Rational(lhs.numerator() * normalize(rhs), lhs.denominator());
else if constexpr (std::is_same_v<std::decay_t<decltype(rhs)>, Rational>)
return Rational(normalize(lhs) * rhs.numerator(), rhs.denominator());
}

// Equality check for Rational types
template <typename L, typename R>
constexpr auto rational_equality(const L &lhs, const R &rhs) noexcept {
if constexpr (std::is_same_v<std::decay_t<decltype(lhs)>, Rational> &&
std::is_same_v<std::decay_t<decltype(rhs)>, Rational>)
return lhs.numerator() == rhs.numerator() &&
lhs.denominator() == rhs.denominator();
else if constexpr (std::is_same_v<std::decay_t<decltype(lhs)>, Rational>)
return lhs == Rational(rhs);
else if constexpr (std::is_same_v<std::decay_t<decltype(rhs)>, Rational>)
return Rational(lhs) == rhs;
}

// Helper function to sum or subtract two Rationals
[[nodiscard]] constexpr Rational
sum_or_subtract(const Rational &lhs, const Rational &rhs, int sign) noexcept {
sum_or_subtract(const Rational &lhs, const Rational &rhs,
const ArithmeticOperation op) noexcept {
const int sign = op == ArithmeticOperation::Add ? 1 : -1;

const int lhs_numerator = lhs.numerator().number();
const int rhs_numerator = sign * rhs.numerator().number();
const int lhs_denominator = lhs.denominator().number();
Expand Down
17 changes: 4 additions & 13 deletions zero/ifc/math/numbers/numbers.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ template <Numerical L, Numerical R>
constexpr auto operator+(const L &lhs, const R &rhs) noexcept {
auto op = [](const auto &a, const auto &b) {
if constexpr (EitherRational<L, R>) {
return rational_add_or_subtract(a, b, 1);
return rational_add(a, b);
} else {
return a + b;
}
Expand All @@ -32,8 +32,7 @@ template <Numerical L, Numerical R>
constexpr auto operator-(const L &lhs, const R &rhs) noexcept {
auto op = [](const auto &a, const auto &b) {
if constexpr (EitherRational<L, R>) {
return rational_add_or_subtract(a, b, -1); // TODO: split it in rational sub and rational add, with
// the sign hidden on the impl details
return rational_subtract(a, b);
} else {
return a - b;
}
Expand All @@ -47,7 +46,7 @@ constexpr auto operator*(const L &lhs, const R &rhs) noexcept {
if constexpr (EitherRational<L, R>) {
return rational_mult(a, b);
} else {
return normalize(a) * normalize(b);
return a * b;
}
};
return arithmetic_op(lhs, rhs, op);
Expand All @@ -59,15 +58,7 @@ constexpr auto operator*(const L &lhs, const R &rhs) noexcept {
template <Numerical L, Numerical R>
constexpr bool operator==(const L &lhs, const R &rhs) noexcept {
auto op = [](const auto &a, const auto &b) {
if constexpr (std::is_same_v<std::decay_t<decltype(a)>, Rational> &&
std::is_same_v<std::decay_t<decltype(b)>, Rational>) {
// Equality check for Rational types
return a.numerator() == b.numerator() && // TODO: hide on the impl details module, by using the concept for check for them
a.denominator() == b.denominator();
} else if constexpr (std::is_same_v<std::decay_t<decltype(a)>, Rational>) {
return a == Rational(b);
} else if constexpr (std::is_same_v<std::decay_t<decltype(b)>, Rational>) {
return Rational(a) == b;
if constexpr (EitherRational<L, R>) {
} else {
return a == b;
}
Expand Down
4 changes: 2 additions & 2 deletions zork_config/zork_clang.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ cpp_compiler = "clang"
driver_path = "clang++" # This binary is soft linked and included in our local path
cpp_standard = "23"
std_lib = "LIBCPP"
# std_lib_installed_dir = "/usr/local/share/libc++/v1"
std_lib_installed_dir = "C:/msys64/clang64/share/libc++/v1"
std_lib_installed_dir = "/usr/local/share/libc++/v1"
# std_lib_installed_dir = "C:/msys64/clang64/share/libc++/v1"
extra_args = [
'-Werror', '-Wall', '-Wpedantic', '-pedantic', '-Wextra', '-Wconversion', '-Wfloat-conversion', '-Wsign-conversion',
'-Wshadow', '-Wnon-virtual-dtor', '-Wold-style-cast', '-Wcast-align', '-Wunused', '-Woverloaded-virtual',
Expand Down

0 comments on commit a23a009

Please sign in to comment.