From b03be111ee43272cde8072232a1028e3d6a8350b Mon Sep 17 00:00:00 2001 From: fintarin Date: Thu, 27 Jul 2023 12:57:21 +0300 Subject: [PATCH] Remove multimethods in IArithmetic --- include/fintamath/core/IArithmetic.hpp | 40 ----------------- .../fintamath/functions/arithmetic/Div.hpp | 5 +++ src/fintamath/config/ArithmeticConfig.cpp | 45 ------------------- src/fintamath/config/ExpressionConfig.cpp | 2 +- src/fintamath/functions/arithmetic/Div.cpp | 31 ++++++++++++- src/fintamath/functions/other/Percent.cpp | 5 ++- src/fintamath/functions/powers/Root.cpp | 2 +- tests/src/core/IArithmeticTests.cpp | 22 --------- tests/src/numbers/INumberTests.cpp | 2 +- 9 files changed, 41 insertions(+), 113 deletions(-) delete mode 100644 src/fintamath/config/ArithmeticConfig.cpp diff --git a/include/fintamath/core/IArithmetic.hpp b/include/fintamath/core/IArithmetic.hpp index caf97c8a2..3202e346b 100644 --- a/include/fintamath/core/IArithmetic.hpp +++ b/include/fintamath/core/IArithmetic.hpp @@ -14,30 +14,18 @@ namespace fintamath { class IArithmetic : public IMathObject { public: friend inline std::unique_ptr operator+(const IArithmetic &lhs, const IArithmetic &rhs) { - if (auto res = IArithmetic::getMultiAdd()(lhs, rhs)) { - return res; - } return lhs.addAbstract(rhs); } friend inline std::unique_ptr operator-(const IArithmetic &lhs, const IArithmetic &rhs) { - if (auto res = IArithmetic::getMultiSub()(lhs, rhs)) { - return res; - } return lhs.substractAbstract(rhs); } friend inline std::unique_ptr operator*(const IArithmetic &lhs, const IArithmetic &rhs) { - if (auto res = IArithmetic::getMultiMul()(lhs, rhs)) { - return res; - } return lhs.multiplyAbstract(rhs); } friend inline std::unique_ptr operator/(const IArithmetic &lhs, const IArithmetic &rhs) { - if (auto res = IArithmetic::getMultiDiv()(lhs, rhs)) { - return res; - } return lhs.divideAbstract(rhs); } @@ -49,26 +37,6 @@ class IArithmetic : public IMathObject { return rhs.negateAbstract(); } - template - static void addMultiAddFunction(const Func &func) { - getMultiAdd().add(func); - } - - template - static void addMultiSubFunction(const Func &func) { - getMultiSub().add(func); - } - - template - static void addMultiMulFunction(const Func &func) { - getMultiMul().add(func); - } - - template - static void addMultiDivFunction(const Func &func) { - getMultiDiv().add(func); - } - template >> static void registerType() { Parser::registerType(getParser()); @@ -101,14 +69,6 @@ class IArithmetic : public IMathObject { virtual std::unique_ptr unaryPlusAbstract() const = 0; private: - static MultiMethod(const IArithmetic &, const IArithmetic &)> &getMultiAdd(); - - static MultiMethod(const IArithmetic &, const IArithmetic &)> &getMultiSub(); - - static MultiMethod(const IArithmetic &, const IArithmetic &)> &getMultiMul(); - - static MultiMethod(const IArithmetic &, const IArithmetic &)> &getMultiDiv(); - static Parser::Vector, const std::string &> &getParser(); }; diff --git a/include/fintamath/functions/arithmetic/Div.hpp b/include/fintamath/functions/arithmetic/Div.hpp index e204ac7da..d03d36978 100644 --- a/include/fintamath/functions/arithmetic/Div.hpp +++ b/include/fintamath/functions/arithmetic/Div.hpp @@ -5,6 +5,8 @@ namespace fintamath { +class Integer; + class Div : public IOperatorCRTP { public: Div() : IOperatorCRTP(IOperator::Priority::Multiplication, false) { @@ -20,6 +22,9 @@ class Div : public IOperatorCRTP { protected: std::unique_ptr call(const ArgumentsRefVector &argsVect) const override; + +private: + static std::unique_ptr divSimpl(const Integer &lhs, const Integer &rhs); }; } diff --git a/src/fintamath/config/ArithmeticConfig.cpp b/src/fintamath/config/ArithmeticConfig.cpp deleted file mode 100644 index 329811aae..000000000 --- a/src/fintamath/config/ArithmeticConfig.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "fintamath/core/IArithmetic.hpp" - -#include "fintamath/core/MultiMethod.hpp" -#include "fintamath/numbers/Integer.hpp" -#include "fintamath/numbers/Rational.hpp" - -namespace fintamath { - -MultiMethod(const IArithmetic &, const IArithmetic &)> &IArithmetic::getMultiAdd() { - static MultiMethod(const IArithmetic &, const IArithmetic &)> multiAdd; - return multiAdd; -} - -MultiMethod(const IArithmetic &, const IArithmetic &)> &IArithmetic::getMultiSub() { - static MultiMethod(const IArithmetic &, const IArithmetic &)> multiSub; - return multiSub; -} - -MultiMethod(const IArithmetic &, const IArithmetic &)> &IArithmetic::getMultiMul() { - static MultiMethod(const IArithmetic &, const IArithmetic &)> multiMul; - return multiMul; -} - -MultiMethod(const IArithmetic &, const IArithmetic &)> &IArithmetic::getMultiDiv() { - static MultiMethod(const IArithmetic &, const IArithmetic &)> multiDiv; - return multiDiv; -} - -} - -using namespace fintamath; - -namespace { - -struct ArithmeticConfig { - ArithmeticConfig() { - IArithmetic::addMultiDivFunction([](const Integer &lhs, const Integer &rhs) { - return cast((Rational(lhs) / Rational(rhs)).toMinimalObject()); - }); - } -}; - -const ArithmeticConfig config; - -} diff --git a/src/fintamath/config/ExpressionConfig.cpp b/src/fintamath/config/ExpressionConfig.cpp index eeeabc0dd..6b6d3089d 100644 --- a/src/fintamath/config/ExpressionConfig.cpp +++ b/src/fintamath/config/ExpressionConfig.cpp @@ -305,7 +305,7 @@ struct ExpressionConfig { Expression::registerFunctionExpressionMaker([](const ArgumentsPtrVector &args) { if (const auto num = cast(args.back())) { - return makeExpr(Pow(), args.front(), Integer(1) / (*num)); + return makeExpr(Pow(), args.front(), Rational(1) / (*num)); } return makeExpr(Pow(), args.front(), makeExpr(Div(), std::make_shared(1), args.back())); diff --git a/src/fintamath/functions/arithmetic/Div.cpp b/src/fintamath/functions/arithmetic/Div.cpp index 069b2577d..f7797ca43 100644 --- a/src/fintamath/functions/arithmetic/Div.cpp +++ b/src/fintamath/functions/arithmetic/Div.cpp @@ -1,9 +1,38 @@ +#include "fintamath/numbers/INumber.hpp" + #include "fintamath/functions/arithmetic/Div.hpp" +#include "fintamath/numbers/Integer.hpp" +#include "fintamath/numbers/Rational.hpp" namespace fintamath { std::unique_ptr Div::call(const ArgumentsRefVector &argsVect) const { - return cast(argsVect.front().get()) / cast(argsVect.back().get()); + static const auto multiPow = [] { + static MultiMethod(const IArithmetic &, const IArithmetic &)> outMultiPow; + + outMultiPow.add([](const Integer &lhs, const Integer &rhs) { + return divSimpl(lhs, rhs); + }); + + return outMultiPow; + }(); + + const auto &lhs = cast(argsVect.front().get()); + const auto &rhs = cast(argsVect.back().get()); + + if (auto res = multiPow(lhs, rhs)) { + return res; + } + + return lhs / rhs; +} + +std::unique_ptr Div::divSimpl(const Integer &lhs, const Integer &rhs) { + if (lhs % rhs != 0) { + return Rational(lhs, rhs).toMinimalObject(); + } + + return (lhs / rhs).toMinimalObject(); } } diff --git a/src/fintamath/functions/other/Percent.cpp b/src/fintamath/functions/other/Percent.cpp index 8b421b30a..5ce635241 100644 --- a/src/fintamath/functions/other/Percent.cpp +++ b/src/fintamath/functions/other/Percent.cpp @@ -5,10 +5,11 @@ namespace fintamath { -const Integer PERCENT_VALUE = 100; +const Rational PERCENT_VALUE = 100; std::unique_ptr Percent::call(const ArgumentsRefVector &argsVect) const { - return (cast(argsVect.front().get()) / PERCENT_VALUE)->toMinimalObject(); + const auto &rhs = cast(argsVect.front().get()); + return (rhs / PERCENT_VALUE)->toMinimalObject(); } } diff --git a/src/fintamath/functions/powers/Root.cpp b/src/fintamath/functions/powers/Root.cpp index 9c49f2eca..1f62b0aed 100644 --- a/src/fintamath/functions/powers/Root.cpp +++ b/src/fintamath/functions/powers/Root.cpp @@ -222,7 +222,7 @@ std::unique_ptr Root::rootSimpl(const Rational &lhs, const Integer } std::unique_ptr Root::rootSimpl(const Real &lhs, const Integer &rhs) { - return Pow()(lhs, 1 / Rational(rhs)); + return Pow()(lhs, Rational(1, rhs)); } } diff --git a/tests/src/core/IArithmeticTests.cpp b/tests/src/core/IArithmeticTests.cpp index d20a5a762..b3e2b40e0 100644 --- a/tests/src/core/IArithmeticTests.cpp +++ b/tests/src/core/IArithmeticTests.cpp @@ -198,28 +198,6 @@ TEST(IArithmeticTests, negateTest) { EXPECT_EQ((-Integer(1)).toString(), "-1"); } -TEST(IArithmeticTests, multimethodsTest) { - IArithmetic::addMultiAddFunction([](const TestArithmetic &lhs, const Integer &rhs) { - return cast(std::make_unique(0)); - }); - EXPECT_EQ(*(TestArithmetic() + Integer(1)), Integer(0)); - - IArithmetic::addMultiSubFunction([](const TestArithmetic &lhs, const Integer &rhs) { - return cast(std::make_unique(0)); - }); - EXPECT_EQ(*(TestArithmetic() - Integer(1)), Integer(0)); - - IArithmetic::addMultiMulFunction([](const TestArithmetic &lhs, const Integer &rhs) { - return cast(std::make_unique(0)); - }); - EXPECT_EQ(*(TestArithmetic() * Integer(1)), Integer(0)); - - IArithmetic::addMultiDivFunction([](const TestArithmetic &lhs, const Integer &rhs) { - return cast(std::make_unique(0)); - }); - EXPECT_EQ(*(TestArithmetic() / Integer(1)), Integer(0)); -} - TEST(IArithmeticTests, getTypeIdTest) { EXPECT_EQ(IArithmetic::getTypeIdStatic(), MathObjectTypeId(MathObjectType::IArithmetic)); } diff --git a/tests/src/numbers/INumberTests.cpp b/tests/src/numbers/INumberTests.cpp index 0b7843e1b..ed52d63cf 100644 --- a/tests/src/numbers/INumberTests.cpp +++ b/tests/src/numbers/INumberTests.cpp @@ -61,7 +61,7 @@ TEST(INumberTests, divTest) { std::unique_ptr m3 = std::make_unique(2); std::unique_ptr m4 = std::make_unique(1, 2); - EXPECT_EQ((*m1 / *m2)->toString(), "1/5"); + EXPECT_EQ((*m1 / *m2)->toString(), "0"); EXPECT_EQ((*m1 / *m1)->toString(), "1"); EXPECT_EQ((*m3 / *m3)->toString(), "1");