diff --git a/include/fintamath/core/MathObjectType.hpp b/include/fintamath/core/MathObjectType.hpp index 7b297e62d..ef611bd95 100644 --- a/include/fintamath/core/MathObjectType.hpp +++ b/include/fintamath/core/MathObjectType.hpp @@ -119,21 +119,28 @@ struct MathObjectType final { Integral, Frac, FracMixed, - PowFunction, Floor, Ceil, + Add, + Mul, + Pow, + And, + Or, IOperator = 12000, - - Add, + AddOper, + UnaryPlus, Sub, - Mul, - Div, Neg, - UnaryPlus, + MulOper, + Div, + Mod, + PowOper, Factorial, Percent, - Pow, + Deg, + Index, + Comma, Eqv, Neqv, Less, @@ -141,15 +148,11 @@ struct MathObjectType final { LessEqv, MoreEqv, Not, - And, - Or, + AndOper, + OrOper, Impl, Equiv, Nequiv, - Index, - Deg, - Comma, - Mod, None = std::numeric_limits::max(), }; diff --git a/include/fintamath/expressions/Expression.hpp b/include/fintamath/expressions/Expression.hpp index 976a3e56f..087cc58ae 100644 --- a/include/fintamath/expressions/Expression.hpp +++ b/include/fintamath/expressions/Expression.hpp @@ -92,7 +92,7 @@ class Expression final : public IExpressionCRTP { getTermParser().registerType(std::move(constructor)); } - template + template static void registerFunctionExpressionMaker(ExpressionMaker maker); static constexpr MathObjectType getTypeStatic() { @@ -195,7 +195,7 @@ Expression operator/(const Expression &lhs, const Variable &rhs); Expression operator/(const Variable &lhs, const Expression &rhs); -template +template void Expression::registerFunctionExpressionMaker(ExpressionMaker maker) { ExpressionParser::Constructor constructor = [maker = std::move(maker)](ArgumentPtrVector &&args) { static const size_t argSize = Function{}.getArgumentTypes().size(); @@ -204,11 +204,6 @@ void Expression::registerFunctionExpressionMaker(ExpressionMaker maker) { if constexpr (Function::isVariadicStatic()) { res = maker(std::move(args)); } - else if constexpr (isPolynomial) { - if (argSize <= args.size()) { - res = maker(std::move(args)); - } - } else { if (argSize == args.size()) { res = maker(std::move(args)); diff --git a/include/fintamath/expressions/ExpressionUtils.hpp b/include/fintamath/expressions/ExpressionUtils.hpp index 277b34de9..12aa676ab 100644 --- a/include/fintamath/expressions/ExpressionUtils.hpp +++ b/include/fintamath/expressions/ExpressionUtils.hpp @@ -76,6 +76,8 @@ std::pair splitRational(const ArgumentPtr &arg); ArgumentPtr negate(const ArgumentPtr &arg); +ArgumentPtr invert(const ArgumentPtr &arg); + ArgumentPtr makePolynom(const IFunction &func, ArgumentPtrVector &&args); ArgumentPtr makePolynom(const IFunction &func, const ArgumentPtrVector &args); diff --git a/include/fintamath/expressions/IExpression.hpp b/include/fintamath/expressions/IExpression.hpp index 3b80d521e..fd3debc0e 100644 --- a/include/fintamath/expressions/IExpression.hpp +++ b/include/fintamath/expressions/IExpression.hpp @@ -50,6 +50,12 @@ class IExpression : public IArithmetic { } protected: + virtual bool isTermOrderInversed() const; + + virtual bool isComparableOrderInversed() const; + + virtual std::strong_ordering compare(const ArgumentPtr &lhs, const ArgumentPtr &rhs) const; + virtual ArgumentPtr simplify() const; virtual ArgumentPtr preSimplify() const; diff --git a/include/fintamath/expressions/interfaces/IPolynomExpression.hpp b/include/fintamath/expressions/interfaces/IPolynomExpression.hpp index 4c6bb09b5..bc7e5fb2e 100644 --- a/include/fintamath/expressions/interfaces/IPolynomExpression.hpp +++ b/include/fintamath/expressions/interfaces/IPolynomExpression.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include @@ -43,16 +42,10 @@ class IPolynomExpression : public IExpression { virtual std::string childToString(const IOperator &oper, const ArgumentPtr &inChild, const ArgumentPtr &prevChild) const; - virtual std::strong_ordering compare(const ArgumentPtr &lhs, const ArgumentPtr &rhs) const; - ArgumentPtr preSimplify() const override; ArgumentPtr postSimplify() const override; - virtual bool isTermOrderInversed() const; - - virtual bool isComparableOrderInversed() const; - private: void simplifyRec(bool isPostSimplify); diff --git a/include/fintamath/functions/IFunctionCRTP.hpp b/include/fintamath/functions/IFunctionCRTP.hpp index bad238aef..21478792d 100644 --- a/include/fintamath/functions/IFunctionCRTP.hpp +++ b/include/fintamath/functions/IFunctionCRTP.hpp @@ -24,7 +24,7 @@ class IFunctionCRTP_ : public IFunction { bool doArgsMatch(const ArgumentRefVector &argVect) const override { if constexpr (Derived::isVariadicStatic()) { - return doAnyArgsMatch(argVect); + return doVariadicArgsMatch(argVect); } else { if (argVect.size() != argTypes.size()) { @@ -75,8 +75,8 @@ class IFunctionCRTP_ : public IFunction { private: template - bool doArgsMatch(const ArgumentRefVector &argVect) const { - if (!is(argVect[i]) || detail::isExpression(argVect[i])) { + static bool doArgsMatch(const ArgumentRefVector &argVect) { + if (!doArgMatch(argVect[i])) { return false; } @@ -84,18 +84,23 @@ class IFunctionCRTP_ : public IFunction { } template - bool doArgsMatch(const ArgumentRefVector & /*unused*/) const { + static bool doArgsMatch(const ArgumentRefVector &) { return true; } - bool doAnyArgsMatch(const ArgumentRefVector &argVect) const { - using AnyArgsType = typename std::tuple_element_t<0, std::tuple>; + static bool doVariadicArgsMatch(const ArgumentRefVector &argVect) { + using ExpectedArg = typename std::tuple_element_t<0, std::tuple>; return stdr::all_of(argVect, [](const auto &arg) { - return is(arg); + return doArgMatch(arg); }); } + template + static bool doArgMatch(const ArgumentRef &arg) { + return is(arg) && !detail::isExpression(arg); + } + private: inline static const ArgumentTypeVector argTypes = {Args::getTypeStatic()...}; diff --git a/include/fintamath/functions/arithmetic/Add.hpp b/include/fintamath/functions/arithmetic/Add.hpp index c440491d6..b2e43ab61 100644 --- a/include/fintamath/functions/arithmetic/Add.hpp +++ b/include/fintamath/functions/arithmetic/Add.hpp @@ -8,24 +8,20 @@ #include "fintamath/core/MathObjectType.hpp" #include "fintamath/functions/FunctionArguments.hpp" #include "fintamath/functions/FunctionUtils.hpp" -#include "fintamath/functions/IOperator.hpp" +#include "fintamath/functions/IFunction.hpp" namespace fintamath { -class Add final : public IOperatorCRTP { +class Add final : public IFunctionCRTP { public: std::string toString() const override { - return "+"; + return "add"; } - static constexpr bool isAssociativeStatic() { + static constexpr bool isVariadicStatic() { return true; } - static constexpr Priority getPriorityStatic() { - return Priority::Addition; - } - static constexpr MathObjectType getTypeStatic() { return {MathObjectType::Add, "Add"}; } diff --git a/include/fintamath/functions/arithmetic/AddOper.hpp b/include/fintamath/functions/arithmetic/AddOper.hpp new file mode 100644 index 000000000..ab2abfcb8 --- /dev/null +++ b/include/fintamath/functions/arithmetic/AddOper.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include +#include + +#include "fintamath/core/IArithmetic.hpp" +#include "fintamath/core/IMathObject.hpp" +#include "fintamath/core/MathObjectType.hpp" +#include "fintamath/functions/FunctionArguments.hpp" +#include "fintamath/functions/IOperator.hpp" + +namespace fintamath { + +class AddOper final : public IOperatorCRTP { +public: + std::string toString() const override { + return "+"; + } + + static constexpr bool isAssociativeStatic() { + return true; + } + + static constexpr Priority getPriorityStatic() { + return Priority::Addition; + } + + static constexpr MathObjectType getTypeStatic() { + return {MathObjectType::AddOper, "AddOper"}; + } + +protected: + std::unique_ptr call(const ArgumentRefVector &argVect) const override; +}; + +} diff --git a/include/fintamath/functions/arithmetic/Mul.hpp b/include/fintamath/functions/arithmetic/Mul.hpp index 49a8c84ac..f4d199892 100644 --- a/include/fintamath/functions/arithmetic/Mul.hpp +++ b/include/fintamath/functions/arithmetic/Mul.hpp @@ -8,24 +8,20 @@ #include "fintamath/core/MathObjectType.hpp" #include "fintamath/functions/FunctionArguments.hpp" #include "fintamath/functions/FunctionUtils.hpp" -#include "fintamath/functions/IOperator.hpp" +#include "fintamath/functions/IFunction.hpp" namespace fintamath { -class Mul final : public IOperatorCRTP { +class Mul final : public IFunctionCRTP { public: std::string toString() const override { - return "*"; + return "mul"; } - static constexpr bool isAssociativeStatic() { + static constexpr bool isVariadicStatic() { return true; } - static constexpr Priority getPriorityStatic() { - return Priority::Multiplication; - } - static constexpr MathObjectType getTypeStatic() { return {MathObjectType::Mul, "Mul"}; } diff --git a/include/fintamath/functions/arithmetic/MulOper.hpp b/include/fintamath/functions/arithmetic/MulOper.hpp new file mode 100644 index 000000000..35e5f738b --- /dev/null +++ b/include/fintamath/functions/arithmetic/MulOper.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include +#include + +#include "fintamath/core/IArithmetic.hpp" +#include "fintamath/core/IMathObject.hpp" +#include "fintamath/core/MathObjectType.hpp" +#include "fintamath/functions/FunctionArguments.hpp" +#include "fintamath/functions/IOperator.hpp" + +namespace fintamath { + +class MulOper final : public IOperatorCRTP { +public: + std::string toString() const override { + return "*"; + } + + static constexpr bool isAssociativeStatic() { + return true; + } + + static constexpr Priority getPriorityStatic() { + return Priority::Multiplication; + } + + static constexpr MathObjectType getTypeStatic() { + return {MathObjectType::MulOper, "MulOper"}; + } + +protected: + std::unique_ptr call(const ArgumentRefVector &argVect) const override; +}; + +} diff --git a/include/fintamath/functions/logic/And.hpp b/include/fintamath/functions/logic/And.hpp index fd15849c6..093dbd87b 100644 --- a/include/fintamath/functions/logic/And.hpp +++ b/include/fintamath/functions/logic/And.hpp @@ -7,25 +7,22 @@ #include "fintamath/core/MathObjectType.hpp" #include "fintamath/functions/FunctionArguments.hpp" #include "fintamath/functions/FunctionUtils.hpp" +#include "fintamath/functions/IFunction.hpp" #include "fintamath/functions/IOperator.hpp" #include "fintamath/literals/Boolean.hpp" namespace fintamath { -class And final : public IOperatorCRTP { +class And final : public IFunctionCRTP { public: std::string toString() const override { - return "&"; + return "and"; } - static constexpr bool isAssociativeStatic() { + static constexpr bool isVariadicStatic() { return true; } - static constexpr Priority getPriorityStatic() { - return Priority::Conjunction; - } - static constexpr MathObjectType getTypeStatic() { return {MathObjectType::And, "And"}; } diff --git a/include/fintamath/functions/logic/AndOper.hpp b/include/fintamath/functions/logic/AndOper.hpp new file mode 100644 index 000000000..05e028e40 --- /dev/null +++ b/include/fintamath/functions/logic/AndOper.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include +#include + +#include "fintamath/core/IMathObject.hpp" +#include "fintamath/core/MathObjectType.hpp" +#include "fintamath/functions/FunctionArguments.hpp" +#include "fintamath/functions/IOperator.hpp" +#include "fintamath/literals/Boolean.hpp" + +namespace fintamath { + +class AndOper final : public IOperatorCRTP { +public: + std::string toString() const override { + return "&"; + } + + static constexpr bool isAssociativeStatic() { + return true; + } + + static constexpr Priority getPriorityStatic() { + return Priority::Conjunction; + } + + static constexpr MathObjectType getTypeStatic() { + return {MathObjectType::AndOper, "AndOper"}; + } + +protected: + std::unique_ptr call(const ArgumentRefVector &argVect) const override; +}; + +} diff --git a/include/fintamath/functions/logic/Or.hpp b/include/fintamath/functions/logic/Or.hpp index 49c97f146..88cae2a89 100644 --- a/include/fintamath/functions/logic/Or.hpp +++ b/include/fintamath/functions/logic/Or.hpp @@ -7,25 +7,21 @@ #include "fintamath/core/MathObjectType.hpp" #include "fintamath/functions/FunctionArguments.hpp" #include "fintamath/functions/FunctionUtils.hpp" -#include "fintamath/functions/IOperator.hpp" +#include "fintamath/functions/IFunction.hpp" #include "fintamath/literals/Boolean.hpp" namespace fintamath { -class Or final : public IOperatorCRTP { +class Or final : public IFunctionCRTP { public: std::string toString() const override { - return "|"; + return "or"; } - static constexpr bool isAssociativeStatic() { + static constexpr bool isVariadicStatic() { return true; } - static constexpr Priority getPriorityStatic() { - return Priority::Disjunction; - } - static constexpr MathObjectType getTypeStatic() { return {MathObjectType::Or, "Or"}; } diff --git a/include/fintamath/functions/logic/OrOper.hpp b/include/fintamath/functions/logic/OrOper.hpp new file mode 100644 index 000000000..cf702830b --- /dev/null +++ b/include/fintamath/functions/logic/OrOper.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include +#include + +#include "fintamath/core/IMathObject.hpp" +#include "fintamath/core/MathObjectType.hpp" +#include "fintamath/functions/FunctionArguments.hpp" +#include "fintamath/functions/FunctionUtils.hpp" +#include "fintamath/functions/IFunction.hpp" +#include "fintamath/functions/IOperator.hpp" +#include "fintamath/literals/Boolean.hpp" + +namespace fintamath { + +class OrOper final : public IOperatorCRTP { +public: + std::string toString() const override { + return "|"; + } + + static constexpr bool isAssociativeStatic() { + return true; + } + + static constexpr Priority getPriorityStatic() { + return Priority::Disjunction; + } + + static constexpr MathObjectType getTypeStatic() { + return {MathObjectType::OrOper, "OrOper"}; + } + +protected: + std::unique_ptr call(const ArgumentRefVector &argVect) const override; +}; + +} diff --git a/include/fintamath/functions/powers/Pow.hpp b/include/fintamath/functions/powers/Pow.hpp index e36058302..206a3b5cf 100644 --- a/include/fintamath/functions/powers/Pow.hpp +++ b/include/fintamath/functions/powers/Pow.hpp @@ -17,14 +17,10 @@ class Rational; class Real; class Complex; -class Pow final : public IOperatorCRTP { +class Pow final : public IFunctionCRTP { public: std::string toString() const override { - return "^"; - } - - static constexpr Priority getPriorityStatic() { - return Priority::Exponentiation; + return "pow"; } static constexpr MathObjectType getTypeStatic() { diff --git a/include/fintamath/functions/powers/PowFunction.hpp b/include/fintamath/functions/powers/PowOper.hpp similarity index 59% rename from include/fintamath/functions/powers/PowFunction.hpp rename to include/fintamath/functions/powers/PowOper.hpp index d255a54fe..921326063 100644 --- a/include/fintamath/functions/powers/PowFunction.hpp +++ b/include/fintamath/functions/powers/PowOper.hpp @@ -7,22 +7,27 @@ #include "fintamath/core/IMathObject.hpp" #include "fintamath/core/MathObjectType.hpp" #include "fintamath/functions/FunctionArguments.hpp" -#include "fintamath/functions/IFunction.hpp" +#include "fintamath/functions/IOperator.hpp" +#include "fintamath/numbers/INumber.hpp" namespace fintamath { -class PowFunction final : public IFunctionCRTP { +class PowOper final : public IOperatorCRTP { public: std::string toString() const override { - return "pow"; + return "^"; + } + + static constexpr Priority getPriorityStatic() { + return Priority::Exponentiation; } static constexpr MathObjectType getTypeStatic() { - return {MathObjectType::PowFunction, "PowFunction"}; + return {MathObjectType::PowOper, "PowOper"}; } protected: std::unique_ptr call(const ArgumentRefVector &argVect) const override; }; -} +} \ No newline at end of file diff --git a/src/fintamath/config/ExpressionConfig.cpp b/src/fintamath/config/ExpressionConfig.cpp index 623ddc51d..44ea3cec9 100644 --- a/src/fintamath/config/ExpressionConfig.cpp +++ b/src/fintamath/config/ExpressionConfig.cpp @@ -29,10 +29,12 @@ #include "fintamath/functions/IFunction.hpp" #include "fintamath/functions/arithmetic/Abs.hpp" #include "fintamath/functions/arithmetic/Add.hpp" +#include "fintamath/functions/arithmetic/AddOper.hpp" #include "fintamath/functions/arithmetic/Div.hpp" #include "fintamath/functions/arithmetic/Frac.hpp" #include "fintamath/functions/arithmetic/FracMixed.hpp" #include "fintamath/functions/arithmetic/Mul.hpp" +#include "fintamath/functions/arithmetic/MulOper.hpp" #include "fintamath/functions/arithmetic/Neg.hpp" #include "fintamath/functions/arithmetic/Sign.hpp" #include "fintamath/functions/arithmetic/Sub.hpp" @@ -64,11 +66,13 @@ #include "fintamath/functions/logarithms/Ln.hpp" #include "fintamath/functions/logarithms/Log.hpp" #include "fintamath/functions/logic/And.hpp" +#include "fintamath/functions/logic/AndOper.hpp" #include "fintamath/functions/logic/Equiv.hpp" #include "fintamath/functions/logic/Impl.hpp" #include "fintamath/functions/logic/Nequiv.hpp" #include "fintamath/functions/logic/Not.hpp" #include "fintamath/functions/logic/Or.hpp" +#include "fintamath/functions/logic/OrOper.hpp" #include "fintamath/functions/ntheory/Ceil.hpp" #include "fintamath/functions/ntheory/Floor.hpp" #include "fintamath/functions/other/Deg.hpp" @@ -76,7 +80,7 @@ #include "fintamath/functions/other/Percent.hpp" #include "fintamath/functions/powers/Exp.hpp" #include "fintamath/functions/powers/Pow.hpp" -#include "fintamath/functions/powers/PowFunction.hpp" +#include "fintamath/functions/powers/PowOper.hpp" #include "fintamath/functions/powers/Root.hpp" #include "fintamath/functions/powers/Sqr.hpp" #include "fintamath/functions/powers/Sqrt.hpp" @@ -134,23 +138,31 @@ void registerTermParsers() { } void registerFunctionExpressionMakers() { - Expression::registerFunctionExpressionMaker([](ArgumentPtrVector &&args) { + Expression::registerFunctionExpressionMaker([](ArgumentPtrVector &&args) { return AddExpr(std::move(args)).clone(); }); + Expression::registerFunctionExpressionMaker([](ArgumentPtrVector &&args) { + return addExpr(std::move(args)); + }); + Expression::registerFunctionExpressionMaker([](ArgumentPtrVector args) { ArgumentPtr lhs = std::move(args.front()); ArgumentPtr rhs = std::move(args.back()); ArgumentPtr negRhs = negExpr(std::move(rhs)); - return AddExpr({std::move(lhs), std::move(negRhs)}).clone(); + return addExpr(std::move(lhs), std::move(negRhs)); }); - Expression::registerFunctionExpressionMaker([](ArgumentPtrVector &&args) { + Expression::registerFunctionExpressionMaker([](ArgumentPtrVector &&args) { return MulExpr(std::move(args)).clone(); }); + Expression::registerFunctionExpressionMaker([](ArgumentPtrVector &&args) { + return mulExpr(std::move(args)); + }); + Expression::registerFunctionExpressionMaker
([](ArgumentPtrVector args) { return DivExpr(std::move(args.front()), std::move(args.back())).clone(); }); @@ -167,19 +179,27 @@ void registerFunctionExpressionMakers() { return addExpr(std::move(integ), divExpr(std::move(numer), std::move(denom))); }); - Expression::registerFunctionExpressionMaker([](ArgumentPtrVector &&args) { + Expression::registerFunctionExpressionMaker([](ArgumentPtrVector &&args) { return AndExpr(std::move(args)).clone(); }); - Expression::registerFunctionExpressionMaker([](ArgumentPtrVector &&args) { + Expression::registerFunctionExpressionMaker([](ArgumentPtrVector &&args) { + return andExpr(std::move(args)); + }); + + Expression::registerFunctionExpressionMaker([](ArgumentPtrVector &&args) { return OrExpr(std::move(args)).clone(); }); + Expression::registerFunctionExpressionMaker([](ArgumentPtrVector &&args) { + return orExpr(std::move(args)); + }); + Expression::registerFunctionExpressionMaker([](ArgumentPtrVector args) { return PowExpr(std::move(args.front()), std::move(args.back())).clone(); }); - Expression::registerFunctionExpressionMaker([](ArgumentPtrVector &&args) { + Expression::registerFunctionExpressionMaker([](ArgumentPtrVector &&args) { return powExpr(std::move(args)); }); diff --git a/src/fintamath/config/ParserConfig.cpp b/src/fintamath/config/ParserConfig.cpp index f37e33f3f..752588bcd 100644 --- a/src/fintamath/config/ParserConfig.cpp +++ b/src/fintamath/config/ParserConfig.cpp @@ -11,10 +11,12 @@ #include "fintamath/functions/IOperator.hpp" #include "fintamath/functions/arithmetic/Abs.hpp" #include "fintamath/functions/arithmetic/Add.hpp" +#include "fintamath/functions/arithmetic/AddOper.hpp" #include "fintamath/functions/arithmetic/Div.hpp" #include "fintamath/functions/arithmetic/Frac.hpp" #include "fintamath/functions/arithmetic/FracMixed.hpp" #include "fintamath/functions/arithmetic/Mul.hpp" +#include "fintamath/functions/arithmetic/MulOper.hpp" #include "fintamath/functions/arithmetic/Neg.hpp" #include "fintamath/functions/arithmetic/Sign.hpp" #include "fintamath/functions/arithmetic/Sub.hpp" @@ -46,11 +48,13 @@ #include "fintamath/functions/logarithms/Ln.hpp" #include "fintamath/functions/logarithms/Log.hpp" #include "fintamath/functions/logic/And.hpp" +#include "fintamath/functions/logic/AndOper.hpp" #include "fintamath/functions/logic/Equiv.hpp" #include "fintamath/functions/logic/Impl.hpp" #include "fintamath/functions/logic/Nequiv.hpp" #include "fintamath/functions/logic/Not.hpp" #include "fintamath/functions/logic/Or.hpp" +#include "fintamath/functions/logic/OrOper.hpp" #include "fintamath/functions/ntheory/Ceil.hpp" #include "fintamath/functions/ntheory/Floor.hpp" #include "fintamath/functions/ntheory/Mod.hpp" @@ -61,7 +65,7 @@ #include "fintamath/functions/other/Percent.hpp" #include "fintamath/functions/powers/Exp.hpp" #include "fintamath/functions/powers/Pow.hpp" -#include "fintamath/functions/powers/PowFunction.hpp" +#include "fintamath/functions/powers/PowOper.hpp" #include "fintamath/functions/powers/Root.hpp" #include "fintamath/functions/powers/Sqr.hpp" #include "fintamath/functions/powers/Sqrt.hpp" @@ -126,6 +130,9 @@ ParserConfig::ParserConfig() { IConstant::registerType(); IConstant::registerType(); + IFunction::registerType(); + IFunction::registerType(); + IFunction::registerType(); IFunction::registerType(); IFunction::registerType(); IFunction::registerType(); @@ -166,19 +173,24 @@ ParserConfig::ParserConfig() { IFunction::registerType(); IFunction::registerType(); IFunction::registerType(); - IFunction::registerType(); IFunction::registerType(); IFunction::registerType(); + IFunction::registerType(); + IFunction::registerType(); - IOperator::registerType(); + IOperator::registerType(); + IOperator::registerType(); IOperator::registerType(); - IOperator::registerType(); - IOperator::registerType
(); IOperator::registerType(); - IOperator::registerType(); + IOperator::registerType(); + IOperator::registerType
(); + IOperator::registerType(); + IOperator::registerType(); IOperator::registerType(); IOperator::registerType(); - IOperator::registerType(); + IOperator::registerType(); + IOperator::registerType(); + IOperator::registerType(); IOperator::registerType(); IOperator::registerType(); IOperator::registerType(); @@ -186,15 +198,11 @@ ParserConfig::ParserConfig() { IOperator::registerType(); IOperator::registerType(); IOperator::registerType(); - IOperator::registerType(); - IOperator::registerType(); + IOperator::registerType(); + IOperator::registerType(); IOperator::registerType(); IOperator::registerType(); IOperator::registerType(); - IOperator::registerType(); - IOperator::registerType(); - IOperator::registerType(); - IOperator::registerType(); IExpression::registerType(); } diff --git a/src/fintamath/expressions/Expression.cpp b/src/fintamath/expressions/Expression.cpp index 534ee631e..b06b6b8d5 100644 --- a/src/fintamath/expressions/Expression.cpp +++ b/src/fintamath/expressions/Expression.cpp @@ -28,6 +28,7 @@ #include "fintamath/functions/arithmetic/Add.hpp" #include "fintamath/functions/arithmetic/Div.hpp" #include "fintamath/functions/arithmetic/Mul.hpp" +#include "fintamath/functions/arithmetic/MulOper.hpp" #include "fintamath/functions/arithmetic/Neg.hpp" #include "fintamath/functions/arithmetic/Sub.hpp" #include "fintamath/functions/other/Comma.hpp" @@ -295,7 +296,7 @@ void Expression::moveFunctionsToOperands(OperandStack &operands, std::stack makeExpr(const IFunction &func, ArgumentPtrVector args) { stdr::transform(args, args.begin(), &Expression::compress); + + if (func.isVariadic() && args.size() == 1) { + return std::move(args.front())->clone(); + } + Expression::validateFunctionArgs(func, args); if (auto expr = Expression::getExpressionParser().parse(func.toString(), std::move(args))) { diff --git a/src/fintamath/expressions/ExpressionComparator.cpp b/src/fintamath/expressions/ExpressionComparator.cpp index ba0ffd0f5..b24663b0b 100644 --- a/src/fintamath/expressions/ExpressionComparator.cpp +++ b/src/fintamath/expressions/ExpressionComparator.cpp @@ -17,11 +17,12 @@ #include "fintamath/functions/FunctionUtils.hpp" #include "fintamath/functions/IFunction.hpp" #include "fintamath/functions/arithmetic/Mul.hpp" -#include "fintamath/functions/logic/Not.hpp" #include "fintamath/functions/powers/Pow.hpp" #include "fintamath/literals/ILiteral.hpp" #include "fintamath/literals/Variable.hpp" +#include + namespace fintamath::detail { using Ordering = std::strong_ordering; @@ -36,28 +37,24 @@ using ExpressionTreePathStack = std::stack>; struct ChildrenComparatorResult final { Ordering postfix = Ordering::equal; - Ordering prefixFirst = Ordering::equal; - Ordering prefixLast = Ordering::equal; - Ordering unary = Ordering::equal; + Ordering prefix = Ordering::equal; Ordering literals = Ordering::equal; Ordering size = Ordering::equal; }; -Ordering compareNonExpressions(const ArgumentPtr &lhs, const ArgumentPtr &rhs, const ComparatorOptions &options); - -Ordering comparePolynoms(const PolynomPtr &lhs, const PolynomPtr &rhs, const ComparatorOptions &options); +Ordering compareNonExpressions(const ArgumentPtr &lhs, const ArgumentPtr &rhs, const ComparatorOptions options); -Ordering compareExpressions(const ExpressionPtr &lhs, const ExpressionPtr &rhs, const ComparatorOptions &options); +Ordering comparePolynoms(const PolynomPtr &lhs, const PolynomPtr &rhs, const ComparatorOptions options); -Ordering comparePolynomAndNonPolynom(const PolynomPtr &lhs, const ArgumentPtr &rhs, const ComparatorOptions &options); +Ordering compareExpressions(const ExpressionPtr &lhs, const ExpressionPtr &rhs, const ComparatorOptions options); -Ordering compareExpressionAndNonExpression(const ExpressionPtr &lhs, const ArgumentPtr &rhs, const ComparatorOptions &options); +Ordering comparePolynomAndNonPolynom(const PolynomPtr &lhs, const ArgumentPtr &rhs, const ComparatorOptions options); -Ordering compareFunctions(const FunctionPtr &lhs, const FunctionPtr &rhs, const ComparatorOptions &options); +Ordering compareExpressionAndNonExpression(const ExpressionPtr &lhs, const ArgumentPtr &rhs, const ComparatorOptions options); -ChildrenComparatorResult compareChildren(const ArgumentPtrVector &lhsChildren, const ArgumentPtrVector &rhsChildren, const ComparatorOptions &options); +Ordering compareFunctions(const FunctionPtr &lhs, const FunctionPtr &rhs); -bool unwrapUnaryExpression(ArgumentPtr &arg); +ChildrenComparatorResult compareChildren(const ArgumentPtrVector &lhsChildren, const ArgumentPtrVector &rhsChildren, const ComparatorOptions options); bool unwrapEmptyExpression(ArgumentPtr &arg); @@ -108,7 +105,7 @@ std::shared_ptr popNextTerm(ExpressionTreePathStack &stack) { } template -Ordering compareTerms(const ArgumentPtr &lhs, const ArgumentPtr &rhs, const ComparatorOptions &options) { +Ordering compareTerms(const ArgumentPtr &lhs, const ArgumentPtr &rhs, const ComparatorOptions options) { ExpressionTreePathStack lhsPath; ExpressionTreePathStack rhsPath; @@ -188,23 +185,34 @@ Ordering compare(ArgumentPtr lhs, ArgumentPtr rhs, const ComparatorOptions optio return compareExpressions(lhsExpr, rhsExpr, options); } -Ordering compareNonExpressions(const ArgumentPtr &lhs, const ArgumentPtr &rhs, const ComparatorOptions &options) { - if (is(lhs) && !is(rhs)) { - return !options.termOrderInversed ? Ordering::greater : Ordering::less; - } - if (!is(lhs) && is(rhs)) { - return options.termOrderInversed ? Ordering::greater : Ordering::less; +Ordering compareNonExpressions(const ArgumentPtr &lhs, const ArgumentPtr &rhs, const ComparatorOptions options) { + Ordering ordering = Ordering::equal; + + if (!lhs && !rhs) { + return ordering; } - if (is(lhs) && !is(rhs)) { - return !options.termOrderInversed ? Ordering::greater : Ordering::less; + if (lhs && !rhs) { + ordering = Ordering::greater; } - if (!is(lhs) && is(rhs)) { - return options.termOrderInversed ? Ordering::greater : Ordering::less; + else if (!lhs && rhs) { + ordering = Ordering::less; + } + else if (is(lhs) && !is(rhs)) { + ordering = Ordering::greater; + } + else if (!is(lhs) && is(rhs)) { + ordering = Ordering::less; + } + else if (is(lhs) && !is(rhs)) { + ordering = Ordering::greater; + } + else if (!is(lhs) && is(rhs)) { + ordering = Ordering::less; } - if (*lhs == *rhs) { - return Ordering::equal; + if (ordering != Ordering::equal || *lhs == *rhs) { + return options.termOrderInversed ? reverse(ordering) : ordering; } if (const auto lhsComp = cast(lhs)) { @@ -220,7 +228,11 @@ Ordering compareNonExpressions(const ArgumentPtr &lhs, const ArgumentPtr &rhs, c return lhs->toString() < rhs->toString() ? Ordering::greater : Ordering::less; } -Ordering comparePolynoms(const PolynomPtr &lhs, const PolynomPtr &rhs, const ComparatorOptions &options) { +Ordering comparePolynoms(const PolynomPtr &lhs, const PolynomPtr &rhs, const ComparatorOptions options) { + if (*lhs->getFunction() != *rhs->getFunction()) { + return compareFunctions(lhs->getFunction(), rhs->getFunction()); + } + const ChildrenComparatorResult childrenComp = compareChildren(lhs->getChildren(), rhs->getChildren(), options); if (childrenComp.postfix != Ordering::equal) { @@ -229,22 +241,16 @@ Ordering comparePolynoms(const PolynomPtr &lhs, const PolynomPtr &rhs, const Com if (childrenComp.size != Ordering::equal) { return childrenComp.size; } - if (childrenComp.unary != Ordering::equal) { - return childrenComp.unary; - } - if (childrenComp.prefixFirst != Ordering::equal) { - return childrenComp.prefixFirst; + if (childrenComp.prefix != Ordering::equal) { + return childrenComp.prefix; } - return compareFunctions(lhs->getFunction(), rhs->getFunction(), options); + return Ordering::equal; } -Ordering compareExpressions(const ExpressionPtr &lhs, const ExpressionPtr &rhs, const ComparatorOptions &options) { - const auto lhsOper = cast(lhs->getFunction()); - const auto rhsOper = cast(rhs->getFunction()); - - if ((lhsOper != nullptr) != (rhsOper != nullptr)) { - return compareFunctions(lhs->getFunction(), rhs->getFunction(), options); +Ordering compareExpressions(const ExpressionPtr &lhs, const ExpressionPtr &rhs, const ComparatorOptions options) { + if (*lhs->getFunction() != *rhs->getFunction()) { + return compareFunctions(lhs->getFunction(), rhs->getFunction()); } ComparatorOptions childCompOptions = options; @@ -260,32 +266,24 @@ Ordering compareExpressions(const ExpressionPtr &lhs, const ExpressionPtr &rhs, if (childrenComp.postfix != Ordering::equal) { return childrenComp.postfix; } - - if (is(lhs->getFunction()) && is(rhs->getFunction())) { - if (childrenComp.prefixLast != Ordering::equal) { - return childrenComp.prefixLast; - } - } - else { - if (childrenComp.prefixFirst != Ordering::equal) { - return childrenComp.prefixFirst; - } + if (childrenComp.prefix != Ordering::equal) { + return childrenComp.prefix; } - return compareFunctions(lhs->getFunction(), rhs->getFunction(), options); + return Ordering::equal; } -Ordering comparePolynomAndNonPolynom(const PolynomPtr &lhs, const ArgumentPtr &rhs, const ComparatorOptions &options) { +Ordering comparePolynomAndNonPolynom(const PolynomPtr &lhs, const ArgumentPtr &rhs, const ComparatorOptions options) { const ChildrenComparatorResult childrenComp = compareChildren(lhs->getChildren(), {rhs}, options); if (childrenComp.postfix != Ordering::equal) { return childrenComp.postfix; } - return childrenComp.prefixFirst; + return childrenComp.prefix; } -Ordering compareExpressionAndNonExpression(const ExpressionPtr &lhs, const ArgumentPtr &rhs, const ComparatorOptions &options) { +Ordering compareExpressionAndNonExpression(const ExpressionPtr &lhs, const ArgumentPtr &rhs, const ComparatorOptions options) { if (!is(rhs)) { return !options.termOrderInversed ? Ordering::greater : Ordering::less; } @@ -294,22 +292,10 @@ Ordering compareExpressionAndNonExpression(const ExpressionPtr &lhs, const Argum return res; } - if (!is(lhs->getFunction())) { - return !options.termOrderInversed ? Ordering::greater : Ordering::less; - } - if (const auto res = compareTerms(lhs, rhs, options); res != Ordering::equal) { return res; } - if (is(lhs->getFunction())) { - if (const Ordering res = compare(lhs->getChildren().front(), rhs); res != Ordering::equal) { - return res; - } - - return Ordering::less; - } - if (is(lhs->getFunction()) || is(lhs->getFunction())) { const ArgumentPtr rhsExpr = makeExpr(*lhs->getFunction(), rhs, Integer(1).clone()); const Ordering res = compare(lhs, rhsExpr); @@ -319,14 +305,7 @@ Ordering compareExpressionAndNonExpression(const ExpressionPtr &lhs, const Argum return !options.termOrderInversed ? Ordering::greater : Ordering::less; } -Ordering compareFunctions(const FunctionPtr &lhs, const FunctionPtr &rhs, const ComparatorOptions &options) { - if (is(lhs) && !is(rhs)) { - return options.termOrderInversed ? Ordering::greater : Ordering::less; - } - if (!is(lhs) && is(rhs)) { - return !options.termOrderInversed ? Ordering::greater : Ordering::less; - } - +Ordering compareFunctions(const FunctionPtr &lhs, const FunctionPtr &rhs) { if (*lhs == *rhs) { return Ordering::equal; } @@ -338,7 +317,7 @@ Ordering compareFunctions(const FunctionPtr &lhs, const FunctionPtr &rhs, const return lhs->toString() < rhs->toString() ? Ordering::greater : Ordering::less; } -ChildrenComparatorResult compareChildren(const ArgumentPtrVector &lhsChildren, const ArgumentPtrVector &rhsChildren, const ComparatorOptions &options) { +ChildrenComparatorResult compareChildren(const ArgumentPtrVector &lhsChildren, const ArgumentPtrVector &rhsChildren, const ComparatorOptions options) { ChildrenComparatorResult result = {}; if (lhsChildren.size() != rhsChildren.size()) { @@ -351,50 +330,29 @@ ChildrenComparatorResult compareChildren(const ArgumentPtrVector &lhsChildren, c std::min(lhsChildren.size(), rhsChildren.size())); for (const auto i : stdv::iota(0U, prefixSize)) { - const Ordering childrenComp = compare(lhsChildren[i], rhsChildren[i], options); - - if (childrenComp != Ordering::equal) { - result.prefixLast = childrenComp; - } - - if (result.prefixFirst == Ordering::equal) { - result.prefixFirst = childrenComp; + if (result.prefix == Ordering::equal) { + result.prefix = compare(lhsChildren[i], rhsChildren[i], options); } if (result.literals == Ordering::equal) { result.literals = compareTerms(lhsChildren[i], rhsChildren[i], {}); } - if (result.literals != Ordering::equal && result.prefixLast != Ordering::equal) { + if (result.prefix != Ordering::equal && result.literals != Ordering::equal) { break; } } for (size_t i = lhsPostfixStart, j = rhsPostfixStart; i < lhsChildren.size() && j < rhsChildren.size(); i++, j++) { - ArgumentPtr compLhs = lhsChildren[i]; - ArgumentPtr compRhs = rhsChildren[j]; - - const bool isLhsUnary = unwrapUnaryExpression(compLhs); - const bool isRhsUnary = unwrapUnaryExpression(compRhs); - - if (isLhsUnary && isRhsUnary) { - compLhs = lhsChildren[i]; - compRhs = rhsChildren[j]; + if (result.postfix == Ordering::equal) { + result.postfix = compare(lhsChildren[i], rhsChildren[j], options); } if (result.literals == Ordering::equal) { - result.literals = compareTerms(compLhs, compRhs, options); + result.literals = compareTerms(lhsChildren[i], rhsChildren[j], options); } - if (result.unary == Ordering::equal && isLhsUnary != isRhsUnary) { - result.unary = !isLhsUnary ? Ordering::greater : Ordering::less; - } - - if (result.postfix == Ordering::equal) { - result.postfix = compare(compLhs, compRhs, options); - } - - if (result.postfix != Ordering::equal) { + if (result.postfix != Ordering::equal && result.literals != Ordering::equal) { break; } } @@ -411,18 +369,6 @@ ChildrenComparatorResult compareChildren(const ArgumentPtrVector &lhsChildren, c return result; } -bool unwrapUnaryExpression(ArgumentPtr &arg) { - if (const auto expr = cast(arg); - expr && - expr->getFunction()->getArgumentTypes().size() == 1) { - - arg = expr->getChildren().front(); - return true; - } - - return false; -} - bool unwrapEmptyExpression(ArgumentPtr &arg) { if (const auto expr = cast(arg); expr && diff --git a/src/fintamath/expressions/ExpressionUtils.cpp b/src/fintamath/expressions/ExpressionUtils.cpp index ffe214ba4..6013facee 100644 --- a/src/fintamath/expressions/ExpressionUtils.cpp +++ b/src/fintamath/expressions/ExpressionUtils.cpp @@ -17,8 +17,10 @@ #include "fintamath/functions/IFunction.hpp" #include "fintamath/functions/IOperator.hpp" #include "fintamath/functions/arithmetic/Add.hpp" +#include "fintamath/functions/arithmetic/AddOper.hpp" #include "fintamath/functions/arithmetic/Div.hpp" #include "fintamath/functions/arithmetic/Mul.hpp" +#include "fintamath/functions/arithmetic/MulOper.hpp" #include "fintamath/functions/arithmetic/Neg.hpp" #include "fintamath/functions/powers/Pow.hpp" #include "fintamath/literals/Variable.hpp" @@ -254,6 +256,22 @@ ArgumentPtr negate(const ArgumentPtr &arg) { return mulExpr(Integer(-1).clone(), arg); } +ArgumentPtr invert(const ArgumentPtr &arg) { + if (const auto num = cast(arg)) { + return Integer(1) / (*num); + } + + if (const auto expr = cast(arg); expr && is
(expr->getFunction())) { + if (*expr->getChildren().front() == Integer(1)) { + return expr->getChildren().back(); + } + + return divExpr(expr->getChildren().back(), expr->getChildren().front()); + } + + return divExpr(Integer(1).clone(), arg); +} + ArgumentPtr makePolynom(const IFunction &func, ArgumentPtrVector &&args) { if (args.empty()) { return {}; @@ -329,14 +347,14 @@ std::string operatorChildToString(const IOperator &oper, const ArgumentPtr &chil } else if (const auto childComplex = cast(child)) { if (childComplex->real() != Integer(0)) { - childOper = std::make_shared(); + childOper = std::make_shared(); } else if (childComplex->imag() != Integer(1)) { if (childComplex->imag() == Integer(-1)) { childOper = std::make_shared(); } else { - childOper = std::make_shared(); + childOper = std::make_shared(); } } } @@ -348,7 +366,7 @@ std::string operatorChildToString(const IOperator &oper, const ArgumentPtr &chil } else if (is(child)) { if (childStr.find(Mul{}.toString()) != std::string::npos) { - childOper = std::make_shared(); + childOper = std::make_shared(); } } diff --git a/src/fintamath/expressions/FunctionExpression.cpp b/src/fintamath/expressions/FunctionExpression.cpp index 3cd53e225..861a46200 100644 --- a/src/fintamath/expressions/FunctionExpression.cpp +++ b/src/fintamath/expressions/FunctionExpression.cpp @@ -47,21 +47,25 @@ const ArgumentPtrVector &FunctionExpression::getChildren() const { } ArgumentPtr FunctionExpression::preSimplify() const { - auto simpl = cast(clone()); - - for (auto &child : simpl->children) { - preSimplifyChild(child); - } - - return simpl; + return simplifyRec(false); } ArgumentPtr FunctionExpression::postSimplify() const { + return simplifyRec(true); +} + +ArgumentPtr FunctionExpression::simplifyRec(bool isPostSimplify) const { auto simpl = cast(clone()); ArgumentRefVector args; for (auto &child : simpl->children) { - postSimplifyChild(child); + if (isPostSimplify) { + postSimplifyChild(child); + } + else { + preSimplifyChild(child); + } + args.emplace_back(*child); } @@ -79,4 +83,5 @@ void FunctionExpression::setChildren(const ArgumentPtrVector &childVect) { children = childVect; } + } diff --git a/src/fintamath/expressions/FunctionExpression.hpp b/src/fintamath/expressions/FunctionExpression.hpp index 54c5ffe7e..2f68c4f87 100644 --- a/src/fintamath/expressions/FunctionExpression.hpp +++ b/src/fintamath/expressions/FunctionExpression.hpp @@ -31,6 +31,9 @@ class FunctionExpression final : public IExpressionCRTP { ArgumentPtr postSimplify() const override; +private: + ArgumentPtr simplifyRec(bool isPostSimplify) const; + private: std::shared_ptr func; diff --git a/src/fintamath/expressions/IExpression.cpp b/src/fintamath/expressions/IExpression.cpp index b8bceaf3a..aa1b96e89 100644 --- a/src/fintamath/expressions/IExpression.cpp +++ b/src/fintamath/expressions/IExpression.cpp @@ -8,6 +8,7 @@ #include #include "fintamath/core/Converter.hpp" +#include "fintamath/expressions/ExpressionComparator.hpp" #include "fintamath/core/CoreUtils.hpp" #include "fintamath/core/IMathObject.hpp" #include "fintamath/core/MultiMethod.hpp" @@ -86,6 +87,22 @@ const std::shared_ptr &IExpression::getOutputFunction() const { return getFunction(); } +bool IExpression::isTermOrderInversed() const { + return false; +} + +bool IExpression::isComparableOrderInversed() const { + return false; +} + +std::strong_ordering IExpression::compare(const ArgumentPtr &lhs, const ArgumentPtr &rhs) const { + const ComparatorOptions options = { + .termOrderInversed = isTermOrderInversed(), + .comparableOrderInversed = isComparableOrderInversed(), + }; + return fintamath::compare(lhs, rhs, options); +} + ArgumentPtr IExpression::simplify() const { ArgumentPtr simpl = cast(clone()); preSimplifyChild(simpl); @@ -165,8 +182,8 @@ std::unique_ptr IExpression::convertToApproximated(const INumber &num) outMultiApproximate.add([](const Complex &inRhs) { return Complex( - *convert(inRhs.real()), - *convert(inRhs.imag())) + *convert(inRhs.real()), + *convert(inRhs.imag())) .clone(); }); @@ -338,7 +355,7 @@ ArgumentPtr IExpression::approximateSimplify() const { if (!containsVar && areNumberChilrenPrecise) { if (auto res = callFunction(*approxSimplExpr->getFunction(), convertToApproximatedNumbers(approxSimplExpr->getChildren())); - is(res)) { + is(res)) { return res; } @@ -364,4 +381,4 @@ IExpression::ExpressionParser &IExpression::getParser() { return parser; } -} +} \ No newline at end of file diff --git a/src/fintamath/expressions/binary/DivExpr.cpp b/src/fintamath/expressions/binary/DivExpr.cpp index 20cf88dda..5d8c35878 100644 --- a/src/fintamath/expressions/binary/DivExpr.cpp +++ b/src/fintamath/expressions/binary/DivExpr.cpp @@ -402,7 +402,7 @@ std::pair DivExpr::mulSumSimplify(const ArgumentPtr &l simplifyChild(remainderAdd); if (const ArgumentPtr remainderAddFirstChild = getPolynomChildren(Add{}, remainderAdd).front(); - compare(lhs, remainderAddFirstChild) != std::strong_ordering::greater) { + fintamath::compare(lhs, remainderAddFirstChild) != std::strong_ordering::greater) { return {}; } diff --git a/src/fintamath/expressions/binary/PowExpr.cpp b/src/fintamath/expressions/binary/PowExpr.cpp index 32a2d7e99..419fbca1b 100644 --- a/src/fintamath/expressions/binary/PowExpr.cpp +++ b/src/fintamath/expressions/binary/PowExpr.cpp @@ -21,6 +21,7 @@ #include "fintamath/functions/arithmetic/Neg.hpp" #include "fintamath/functions/comparison/MoreEqv.hpp" #include "fintamath/functions/powers/Pow.hpp" +#include "fintamath/functions/powers/PowOper.hpp" #include "fintamath/functions/powers/Root.hpp" #include "fintamath/functions/powers/Sqrt.hpp" #include "fintamath/literals/Boolean.hpp" @@ -43,32 +44,8 @@ PowExpr::PowExpr(ArgumentPtr inLhsChild, ArgumentPtr inRhsChild) : IBinaryExpressionCRTP(Pow{}, std::move(inLhsChild), std::move(inRhsChild)) { } -std::string PowExpr::toString() const { - if (const auto rhsChildRat = cast(rhsChild)) { - const Integer &numerator = rhsChildRat->numerator(); - const Integer &denominator = rhsChildRat->denominator(); - - if (numerator == 1) { - if (denominator == 2) { - return functionToString(Sqrt{}, {lhsChild}); - } - - return functionToString(Root{}, {lhsChild, denominator.clone()}); - } - } - - if (const auto rhsChildExpr = cast(rhsChild); - rhsChildExpr && is
(rhsChildExpr->getFunction())) { - - if (*rhsChildExpr->getChildren().front() == Integer(1)) { - return functionToString(Root{}, {lhsChild, rhsChildExpr->getChildren().back()}); - } - } - - return IBinaryExpression::toString(); -} - const std::shared_ptr &PowExpr::getOutputFunction() const { + static const std::shared_ptr pow = std::make_shared(); static const std::shared_ptr sqrt = std::make_shared(); static const std::shared_ptr root = std::make_shared(); @@ -93,7 +70,25 @@ const std::shared_ptr &PowExpr::getOutputFunction() const { return root; } - return IBinaryExpression::getFunction(); + return pow; +} + +std::string PowExpr::toString() const { + const auto outFunc = getOutputFunction(); + + if (is(outFunc)) { + return functionToString(Sqrt{}, {lhsChild}); + } + + if (is(outFunc)) { + return functionToString(Root{}, {lhsChild, invert(rhsChild)}); + } + + return IBinaryExpression::toString(); +} + +bool PowExpr::isTermOrderInversed() const { + return true; } ArgumentPtr PowExpr::approximateSimplify() const { diff --git a/src/fintamath/expressions/binary/PowExpr.hpp b/src/fintamath/expressions/binary/PowExpr.hpp index 922782cb5..908d01684 100644 --- a/src/fintamath/expressions/binary/PowExpr.hpp +++ b/src/fintamath/expressions/binary/PowExpr.hpp @@ -16,15 +16,17 @@ class PowExpr final : public IBinaryExpressionCRTP { public: explicit PowExpr(ArgumentPtr inLhsChild, ArgumentPtr inRhsChild); - std::string toString() const override; - const std::shared_ptr &getOutputFunction() const override; + std::string toString() const override; + static constexpr MathObjectType getTypeStatic() { return {MathObjectType::PowExpr, "PowExpr"}; } protected: + bool isTermOrderInversed() const; + ArgumentPtr approximateSimplify() const override; ArgumentPtr setPrecision(unsigned precision, const Integer &maxInt) const override; diff --git a/src/fintamath/expressions/interfaces/IBinaryExpression.cpp b/src/fintamath/expressions/interfaces/IBinaryExpression.cpp index 5aa3be82a..a437570c8 100644 --- a/src/fintamath/expressions/interfaces/IBinaryExpression.cpp +++ b/src/fintamath/expressions/interfaces/IBinaryExpression.cpp @@ -21,11 +21,14 @@ IBinaryExpression::IBinaryExpression(const IFunction &inFunc, ArgumentPtr lhs, A } std::string IBinaryExpression::toString() const { - if (const auto oper = cast(func)) { - return binaryOperatorToString(*oper, lhsChild, rhsChild); + const auto &outFunc = getOutputFunction(); + const auto outOper = cast(outFunc); + + if (!outOper) { + return functionToString(*outFunc, {lhsChild, rhsChild}); } - return functionToString(*func, {lhsChild, rhsChild}); + return binaryOperatorToString(*outOper, lhsChild, rhsChild); } const std::shared_ptr &IBinaryExpression::getFunction() const { diff --git a/src/fintamath/expressions/interfaces/IPolynomExpression.cpp b/src/fintamath/expressions/interfaces/IPolynomExpression.cpp index 6f7306998..0f9fbc76f 100644 --- a/src/fintamath/expressions/interfaces/IPolynomExpression.cpp +++ b/src/fintamath/expressions/interfaces/IPolynomExpression.cpp @@ -18,6 +18,7 @@ #include "fintamath/functions/IFunction.hpp" #include "fintamath/functions/IOperator.hpp" #include "fintamath/functions/arithmetic/Mul.hpp" +#include "fintamath/functions/arithmetic/MulOper.hpp" namespace fintamath { @@ -37,20 +38,20 @@ const ArgumentPtrVector &IPolynomExpression::getChildren() const { } std::string IPolynomExpression::toString() const { - const auto oper = cast(func); - if (!oper) { - return functionToString(*func, children); - } + const auto &outFunc = getOutputFunction(); + const auto outOper = cast(outFunc); - std::string result; + if (!outOper) { + return functionToString(*outFunc, children); + } - result += childToString(*oper, children.front(), {}); + std::string result = childToString(*outOper, children.front(), {}); for (const auto i : stdv::iota(1U, children.size())) { - const std::string childStr = childToString(*oper, children[i], children[i - 1]); + const std::string childStr = childToString(*outOper, children[i], children[i - 1]); if (childStr.size() > 2 && childStr[0] == ' ' && std::isdigit(childStr[1]) && std::isdigit(result.back())) { - result += Mul{}.toString() + childStr.substr(1); + result += MulOper{}.toString() + childStr.substr(1); } else { result += childStr; @@ -195,23 +196,8 @@ IPolynomExpression::SimplifyFunctionVector IPolynomExpression::getFunctionsForPo std::string IPolynomExpression::childToString(const IOperator &oper, const ArgumentPtr &inChild, const ArgumentPtr &prevChild) const { const std::string childStr = operatorChildToString(oper, inChild); - return prevChild ? (putInSpaces(func->toString()) + childStr) : childStr; -} - -std::strong_ordering IPolynomExpression::compare(const ArgumentPtr &lhs, const ArgumentPtr &rhs) const { - const ComparatorOptions options = { - .termOrderInversed = isTermOrderInversed(), - .comparableOrderInversed = isComparableOrderInversed(), - }; - return fintamath::compare(lhs, rhs, options); -} - -bool IPolynomExpression::isTermOrderInversed() const { - return false; -} - -bool IPolynomExpression::isComparableOrderInversed() const { - return false; + const std::string operStr = prevChild ? putInSpaces(oper.toString()) : ""; + return operStr + childStr; } void IPolynomExpression::setChildren(const ArgumentPtrVector &childVect) { diff --git a/src/fintamath/expressions/interfaces/IUnaryExpression.cpp b/src/fintamath/expressions/interfaces/IUnaryExpression.cpp index ffbf50912..cbd844905 100644 --- a/src/fintamath/expressions/interfaces/IUnaryExpression.cpp +++ b/src/fintamath/expressions/interfaces/IUnaryExpression.cpp @@ -20,15 +20,18 @@ IUnaryExpression::IUnaryExpression(const IFunction &inFunc, ArgumentPtr rhs) } std::string IUnaryExpression::toString() const { - if (const auto oper = cast(func)) { - if (oper->getPriority() == IOperator::Priority::PostfixUnary) { - return detail::postfixUnaryOperatorToString(*oper, child); - } + const auto &outFunc = getOutputFunction(); + const auto outOper = cast(outFunc); + + if (!outOper) { + return functionToString(*outFunc, {child}); + } - return detail::prefixUnaryOperatorToString(*oper, child); + if (outOper->getPriority() == IOperator::Priority::PostfixUnary) { + return postfixUnaryOperatorToString(*outOper, child); } - return detail::functionToString(*func, {child}); + return prefixUnaryOperatorToString(*outOper, child); } const std::shared_ptr &IUnaryExpression::getFunction() const { diff --git a/src/fintamath/expressions/polynomial/AddExpr.cpp b/src/fintamath/expressions/polynomial/AddExpr.cpp index 82630599d..946d8fa50 100644 --- a/src/fintamath/expressions/polynomial/AddExpr.cpp +++ b/src/fintamath/expressions/polynomial/AddExpr.cpp @@ -16,6 +16,7 @@ #include "fintamath/functions/IFunction.hpp" #include "fintamath/functions/IOperator.hpp" #include "fintamath/functions/arithmetic/Add.hpp" +#include "fintamath/functions/arithmetic/AddOper.hpp" #include "fintamath/functions/arithmetic/Div.hpp" #include "fintamath/functions/arithmetic/Mul.hpp" #include "fintamath/functions/arithmetic/Neg.hpp" @@ -39,6 +40,11 @@ AddExpr::AddExpr(ArgumentPtrVector inChildren) : IPolynomExpressionCRTP(Add{}, std::move(inChildren)) { } +const std::shared_ptr &AddExpr::getOutputFunction() const { + static const std::shared_ptr oper = std::make_shared(); + return oper; +} + std::string AddExpr::childToString(const IOperator &oper, const ArgumentPtr &inChild, const ArgumentPtr &prevChild) const { std::string result = operatorChildToString(oper, inChild); bool isChildNegated = false; @@ -53,7 +59,7 @@ std::string AddExpr::childToString(const IOperator &oper, const ArgumentPtr &inC std::string funcStr; if (isChildNegated) { - funcStr = Sub{}.toString(); + funcStr = Neg{}.toString(); } else if (prevChild) { funcStr = oper.toString(); diff --git a/src/fintamath/expressions/polynomial/AddExpr.hpp b/src/fintamath/expressions/polynomial/AddExpr.hpp index 1e1403633..552a323ba 100644 --- a/src/fintamath/expressions/polynomial/AddExpr.hpp +++ b/src/fintamath/expressions/polynomial/AddExpr.hpp @@ -18,6 +18,8 @@ class AddExpr final : public IPolynomExpressionCRTP { public: explicit AddExpr(ArgumentPtrVector inChildren); + const std::shared_ptr &getOutputFunction() const override; + static constexpr MathObjectType getTypeStatic() { return {MathObjectType::AddExpr, "AddExpr"}; } @@ -29,15 +31,6 @@ class AddExpr final : public IPolynomExpressionCRTP { std::string childToString(const IOperator &oper, const ArgumentPtr &inChild, const ArgumentPtr &prevChild) const override; - /** - * @brief - * - * @param lhs - * @param rhs - * @return -1 if we should swap the arguments - * @return 1 if we should not swap the arguments - * @return 0 if this comparator fails - */ std::strong_ordering compare(const ArgumentPtr &lhs, const ArgumentPtr &rhs) const override; private: diff --git a/src/fintamath/expressions/polynomial/AndExpr.cpp b/src/fintamath/expressions/polynomial/AndExpr.cpp index 4f707493b..44ef3c802 100644 --- a/src/fintamath/expressions/polynomial/AndExpr.cpp +++ b/src/fintamath/expressions/polynomial/AndExpr.cpp @@ -8,6 +8,7 @@ #include "fintamath/functions/FunctionArguments.hpp" #include "fintamath/functions/IFunction.hpp" #include "fintamath/functions/logic/And.hpp" +#include "fintamath/functions/logic/AndOper.hpp" #include "fintamath/functions/logic/Not.hpp" #include "fintamath/functions/logic/Or.hpp" #include "fintamath/literals/Boolean.hpp" @@ -18,6 +19,11 @@ AndExpr::AndExpr(ArgumentPtrVector inChildren) : IPolynomExpressionCRTP(And{}, std::move(inChildren)) { } +const std::shared_ptr &AndExpr::getOutputFunction() const { + static const std::shared_ptr oper = std::make_shared(); + return oper; +} + AndExpr::SimplifyFunctionVector AndExpr::getFunctionsForPreSimplify() const { static const SimplifyFunctionVector simplifyFunctions = { &AndExpr::boolSimplify, @@ -62,10 +68,10 @@ ArgumentPtr AndExpr::equalSimplify(const IFunction & /*func*/, const ArgumentPtr } ArgumentPtr AndExpr::notSimplify(const IFunction & /*func*/, const ArgumentPtr &lhs, const ArgumentPtr &rhs) { - if (const auto rhsExpr = cast(rhs); - rhsExpr && - is(rhsExpr->getFunction()) && - *rhsExpr->getChildren().front() == *lhs) { + if (const auto lhsExpr = cast(lhs); + lhsExpr && + is(lhsExpr->getFunction()) && + *lhsExpr->getChildren().front() == *rhs) { return Boolean(false).clone(); } diff --git a/src/fintamath/expressions/polynomial/AndExpr.hpp b/src/fintamath/expressions/polynomial/AndExpr.hpp index e60e8e1ea..08105b9d4 100644 --- a/src/fintamath/expressions/polynomial/AndExpr.hpp +++ b/src/fintamath/expressions/polynomial/AndExpr.hpp @@ -11,6 +11,8 @@ class AndExpr final : public IPolynomExpressionCRTP { public: explicit AndExpr(ArgumentPtrVector inChildren); + const std::shared_ptr &getOutputFunction() const override; + static constexpr MathObjectType getTypeStatic() { return {MathObjectType::AndExpr, "AndExpr"}; } diff --git a/src/fintamath/expressions/polynomial/MulExpr.cpp b/src/fintamath/expressions/polynomial/MulExpr.cpp index 4d96753d6..229682d79 100644 --- a/src/fintamath/expressions/polynomial/MulExpr.cpp +++ b/src/fintamath/expressions/polynomial/MulExpr.cpp @@ -14,6 +14,7 @@ #include "fintamath/functions/arithmetic/Add.hpp" #include "fintamath/functions/arithmetic/Div.hpp" #include "fintamath/functions/arithmetic/Mul.hpp" +#include "fintamath/functions/arithmetic/MulOper.hpp" #include "fintamath/functions/arithmetic/Neg.hpp" #include "fintamath/functions/arithmetic/Sign.hpp" #include "fintamath/functions/logarithms/Log.hpp" @@ -35,6 +36,11 @@ MulExpr::MulExpr(ArgumentPtrVector inChildren) : IPolynomExpressionCRTP(Mul{}, std::move(inChildren)) { } +const std::shared_ptr &MulExpr::getOutputFunction() const { + static const std::shared_ptr oper = std::make_shared(); + return oper; +} + std::string MulExpr::toString() const { auto [childNumerator, childDenominator] = splitRational(children.front()); diff --git a/src/fintamath/expressions/polynomial/MulExpr.hpp b/src/fintamath/expressions/polynomial/MulExpr.hpp index 76c269f1d..50d1a2627 100644 --- a/src/fintamath/expressions/polynomial/MulExpr.hpp +++ b/src/fintamath/expressions/polynomial/MulExpr.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include "fintamath/core/MathObjectType.hpp" @@ -14,6 +15,8 @@ class MulExpr final : public IPolynomExpressionCRTP { std::string toString() const override; + const std::shared_ptr &getOutputFunction() const override; + static constexpr MathObjectType getTypeStatic() { return {MathObjectType::MulExpr, "MulExpr"}; } diff --git a/src/fintamath/expressions/polynomial/OrExpr.cpp b/src/fintamath/expressions/polynomial/OrExpr.cpp index bf3ff4b2b..dbe4c11d8 100644 --- a/src/fintamath/expressions/polynomial/OrExpr.cpp +++ b/src/fintamath/expressions/polynomial/OrExpr.cpp @@ -14,6 +14,7 @@ #include "fintamath/functions/logic/And.hpp" #include "fintamath/functions/logic/Not.hpp" #include "fintamath/functions/logic/Or.hpp" +#include "fintamath/functions/logic/OrOper.hpp" #include "fintamath/literals/Boolean.hpp" namespace fintamath { @@ -21,54 +22,24 @@ namespace fintamath { using namespace detail; OrExpr::OrExpr(ArgumentPtrVector inChildren) - : IPolynomExpressionCRTP(Or{}, std::move(inChildren)) { + : IPolynomExpressionCRTP(Or{}, std::move(inChildren)) { +} + +const std::shared_ptr &OrExpr::getOutputFunction() const { + static const std::shared_ptr oper = std::make_shared(); + return oper; } std::string OrExpr::childToString(const IOperator &oper, const ArgumentPtr &inChild, const ArgumentPtr &prevChild) const { std::string result = operatorChildToString(oper, inChild); if (const auto &childExpr = cast(inChild); - childExpr && is(childExpr->getFunction())) { + childExpr && is(childExpr->getFunction())) { result = putInBrackets(result); } - return prevChild ? (putInSpaces(func->toString()) + result) : result; -} - -ArgumentPtr OrExpr::postSimplify() const { - ArgumentPtr simplObj = IPolynomExpression::postSimplify(); - auto simpl = cast(simplObj); - - if (!simpl) { - return simplObj; - } - - ArgumentPtrVector simplChildren = simpl->children; - const size_t simplChildrenSizeInitial = simplChildren.size(); - - // TODO: use more efficient algorithm - for (size_t i = 0; i + 1 < simplChildren.size(); i++) { - for (size_t j = i + 1; j < simplChildren.size(); j++) { - if (auto res = absorptionSimplify(simplChildren[i], simplChildren[j])) { - simplChildren[i] = std::move(res); - simplChildren.erase(simplChildren.begin() + static_cast(j)); - j--; - } - } - } - - if (simplChildren.size() != simplChildrenSizeInitial) { - if (simplChildren.size() > 1) { - ArgumentPtr res = orExpr(std::move(simplChildren)); - postSimplifyChild(res); - return res; - } - - return simplChildren.front(); - } - - return simpl; + return (prevChild ? putInSpaces(getOutputFunction()->toString()) : "") + result; } OrExpr::SimplifyFunctionVector OrExpr::getFunctionsForPreSimplify() const { @@ -86,6 +57,7 @@ OrExpr::SimplifyFunctionVector OrExpr::getFunctionsForPostSimplify() const { &OrExpr::notSimplify, &OrExpr::boolSimplify, &OrExpr::equalSimplify, + &OrExpr::absorptionSimplify, }; return simplifyFunctions; } @@ -116,10 +88,10 @@ ArgumentPtr OrExpr::equalSimplify(const IFunction & /*func*/, const ArgumentPtr } ArgumentPtr OrExpr::notSimplify(const IFunction & /*func*/, const ArgumentPtr &lhs, const ArgumentPtr &rhs) { - if (const auto rhsExpr = cast(rhs); - rhsExpr && - is(rhsExpr->getFunction()) && - *rhsExpr->getChildren().front() == *lhs) { + if (const auto lhsExpr = cast(lhs); + lhsExpr && + is(lhsExpr->getFunction()) && + *lhsExpr->getChildren().front() == *rhs) { return Boolean(true).clone(); } @@ -152,8 +124,8 @@ ArgumentPtr OrExpr::andSimplify(const IFunction & /*func*/, const ArgumentPtr &l bool isLhsSubChildNot = false; if (const auto lhsSubChildNotExpr = cast(lhsSubChild); - lhsSubChildNotExpr && - is(lhsSubChildNotExpr->getFunction())) { + lhsSubChildNotExpr && + is(lhsSubChildNotExpr->getFunction())) { isLhsSubChildNot = true; lhsSubChild = lhsSubChildNotExpr->getChildren().front(); @@ -162,8 +134,8 @@ ArgumentPtr OrExpr::andSimplify(const IFunction & /*func*/, const ArgumentPtr &l bool isRhsSubChildNot = false; if (const auto rhsSubChildNotExpr = cast(rhsSubChild); - rhsSubChildNotExpr && - is(rhsSubChildNotExpr->getFunction())) { + rhsSubChildNotExpr && + is(rhsSubChildNotExpr->getFunction())) { isRhsSubChildNot = true; rhsSubChild = rhsSubChildNotExpr->getChildren().front(); @@ -197,7 +169,7 @@ ArgumentPtr OrExpr::andSimplify(const IFunction & /*func*/, const ArgumentPtr &l return resultChildren.front(); } -ArgumentPtr OrExpr::absorptionSimplify(const ArgumentPtr &lhs, const ArgumentPtr &rhs) { +ArgumentPtr OrExpr::absorptionSimplify(const IFunction & /*func*/, const ArgumentPtr &lhs, const ArgumentPtr &rhs) { const auto lhsExpr = cast(lhs); const auto rhsExpr = cast(rhs); @@ -252,4 +224,4 @@ ArgumentPtr OrExpr::absorptionSimplify(const ArgumentPtr &lhs, const ArgumentPtr return {}; } -} +} \ No newline at end of file diff --git a/src/fintamath/expressions/polynomial/OrExpr.hpp b/src/fintamath/expressions/polynomial/OrExpr.hpp index 15b0c06a0..178c6b45a 100644 --- a/src/fintamath/expressions/polynomial/OrExpr.hpp +++ b/src/fintamath/expressions/polynomial/OrExpr.hpp @@ -13,6 +13,8 @@ class OrExpr final : public IPolynomExpressionCRTP { public: explicit OrExpr(ArgumentPtrVector inChildren); + const std::shared_ptr &getOutputFunction() const override; + static constexpr MathObjectType getTypeStatic() { return {MathObjectType::OrExpr, "OrExpr"}; } @@ -20,8 +22,6 @@ class OrExpr final : public IPolynomExpressionCRTP { protected: std::string childToString(const IOperator &oper, const ArgumentPtr &inChild, const ArgumentPtr &prevChild) const override; - ArgumentPtr postSimplify() const override; - SimplifyFunctionVector getFunctionsForPreSimplify() const override; SimplifyFunctionVector getFunctionsForPostSimplify() const override; @@ -37,7 +37,7 @@ class OrExpr final : public IPolynomExpressionCRTP { static ArgumentPtr andSimplify(const IFunction &func, const ArgumentPtr &lhs, const ArgumentPtr &rhs); - static ArgumentPtr absorptionSimplify(const ArgumentPtr &lhs, const ArgumentPtr &rhs); + static ArgumentPtr absorptionSimplify(const IFunction &func, const ArgumentPtr &lhs, const ArgumentPtr &rhs); }; } \ No newline at end of file diff --git a/src/fintamath/functions/arithmetic/AddOper.cpp b/src/fintamath/functions/arithmetic/AddOper.cpp new file mode 100644 index 000000000..92e639c88 --- /dev/null +++ b/src/fintamath/functions/arithmetic/AddOper.cpp @@ -0,0 +1,15 @@ +#include "fintamath/functions/arithmetic/AddOper.hpp" + +#include + +#include "fintamath/core/IMathObject.hpp" +#include "fintamath/functions/FunctionArguments.hpp" +#include "fintamath/functions/arithmetic/Add.hpp" + +namespace fintamath { + +std::unique_ptr AddOper::call(const ArgumentRefVector &argVect) const { + return Add{}(argVect); +} + +} diff --git a/src/fintamath/functions/arithmetic/MulOper.cpp b/src/fintamath/functions/arithmetic/MulOper.cpp new file mode 100644 index 000000000..251e9e449 --- /dev/null +++ b/src/fintamath/functions/arithmetic/MulOper.cpp @@ -0,0 +1,15 @@ +#include "fintamath/functions/arithmetic/MulOper.hpp" + +#include + +#include "fintamath/core/IMathObject.hpp" +#include "fintamath/functions/FunctionArguments.hpp" +#include "fintamath/functions/arithmetic/Mul.hpp" + +namespace fintamath { + +std::unique_ptr MulOper::call(const ArgumentRefVector &argVect) const { + return Mul{}(argVect); +} + +} diff --git a/src/fintamath/functions/logic/AndOper.cpp b/src/fintamath/functions/logic/AndOper.cpp new file mode 100644 index 000000000..a3672043d --- /dev/null +++ b/src/fintamath/functions/logic/AndOper.cpp @@ -0,0 +1,15 @@ +#include "fintamath/functions/logic/AndOper.hpp" + +#include + +#include "fintamath/core/IMathObject.hpp" +#include "fintamath/functions/FunctionArguments.hpp" +#include "fintamath/functions/logic/And.hpp" + +namespace fintamath { + +std::unique_ptr AndOper::call(const ArgumentRefVector &argVect) const { + return And{}(argVect); +} + +} diff --git a/src/fintamath/functions/logic/OrOper.cpp b/src/fintamath/functions/logic/OrOper.cpp new file mode 100644 index 000000000..df3f81766 --- /dev/null +++ b/src/fintamath/functions/logic/OrOper.cpp @@ -0,0 +1,15 @@ +#include "fintamath/functions/logic/OrOper.hpp" + +#include + +#include "fintamath/core/IMathObject.hpp" +#include "fintamath/functions/FunctionArguments.hpp" +#include "fintamath/functions/logic/Or.hpp" + +namespace fintamath { + +std::unique_ptr OrOper::call(const ArgumentRefVector &argVect) const { + return Or{}(argVect); +} + +} diff --git a/src/fintamath/functions/powers/PowFunction.cpp b/src/fintamath/functions/powers/PowOper.cpp similarity index 60% rename from src/fintamath/functions/powers/PowFunction.cpp rename to src/fintamath/functions/powers/PowOper.cpp index 2cb0dd7dc..89cab9859 100644 --- a/src/fintamath/functions/powers/PowFunction.cpp +++ b/src/fintamath/functions/powers/PowOper.cpp @@ -1,4 +1,4 @@ -#include "fintamath/functions/powers/PowFunction.hpp" +#include "fintamath/functions/powers/PowOper.hpp" #include @@ -8,7 +8,7 @@ namespace fintamath { -std::unique_ptr PowFunction::call(const ArgumentRefVector &argVect) const { +std::unique_ptr PowOper::call(const ArgumentRefVector &argVect) const { return Pow{}(argVect); } diff --git a/tests/src/FintamathTests.cpp b/tests/src/FintamathTests.cpp index b6b462387..f0af90612 100644 --- a/tests/src/FintamathTests.cpp +++ b/tests/src/FintamathTests.cpp @@ -67,7 +67,7 @@ TEST(FintamathTests, fintamathTest) { EXPECT_EQ(expr.toString(), "-0.039790759931157709524"); expr = Expression("~a & b | ~c -> a <-> b !<-> c"); - EXPECT_EQ(expr.toString(), "(a & b & ~c) | (~a & ~b & ~c) | (~a & c) | (~b & c)"); + EXPECT_EQ(expr.toString(), "(~a & ~b & ~c) | (~a & c) | (a & b & ~c) | (~b & c)"); //-------------------------------------------------------------------------------------// diff --git a/tests/src/core/ParseTests.cpp b/tests/src/core/ParseTests.cpp index b6effad91..2ce706c59 100644 --- a/tests/src/core/ParseTests.cpp +++ b/tests/src/core/ParseTests.cpp @@ -7,10 +7,12 @@ #include "fintamath/functions/IOperator.hpp" #include "fintamath/functions/arithmetic/Abs.hpp" #include "fintamath/functions/arithmetic/Add.hpp" +#include "fintamath/functions/arithmetic/AddOper.hpp" #include "fintamath/functions/arithmetic/Div.hpp" #include "fintamath/functions/arithmetic/Frac.hpp" #include "fintamath/functions/arithmetic/FracMixed.hpp" #include "fintamath/functions/arithmetic/Mul.hpp" +#include "fintamath/functions/arithmetic/MulOper.hpp" #include "fintamath/functions/arithmetic/Neg.hpp" #include "fintamath/functions/arithmetic/Sign.hpp" #include "fintamath/functions/arithmetic/Sub.hpp" @@ -40,11 +42,13 @@ #include "fintamath/functions/logarithms/Ln.hpp" #include "fintamath/functions/logarithms/Log.hpp" #include "fintamath/functions/logic/And.hpp" +#include "fintamath/functions/logic/AndOper.hpp" #include "fintamath/functions/logic/Equiv.hpp" #include "fintamath/functions/logic/Impl.hpp" #include "fintamath/functions/logic/Nequiv.hpp" #include "fintamath/functions/logic/Not.hpp" #include "fintamath/functions/logic/Or.hpp" +#include "fintamath/functions/logic/OrOper.hpp" #include "fintamath/functions/ntheory/Ceil.hpp" #include "fintamath/functions/ntheory/Floor.hpp" #include "fintamath/functions/other/Deg.hpp" @@ -53,7 +57,7 @@ #include "fintamath/functions/other/Percent.hpp" #include "fintamath/functions/powers/Exp.hpp" #include "fintamath/functions/powers/Pow.hpp" -#include "fintamath/functions/powers/PowFunction.hpp" +#include "fintamath/functions/powers/PowOper.hpp" #include "fintamath/functions/powers/Root.hpp" #include "fintamath/functions/powers/Sqrt.hpp" #include "fintamath/functions/trigonometry/Acos.hpp" @@ -208,6 +212,9 @@ TEST(ParseTests, parseConstantTest) { } TEST(ParseTests, parseFunctionTest) { + EXPECT_TRUE(is(IFunction::parse("add"))); + EXPECT_TRUE(is(IFunction::parse("mul"))); + EXPECT_TRUE(is(IFunction::parse("pow"))); EXPECT_TRUE(is(IFunction::parse("sqrt"))); EXPECT_TRUE(is(IFunction::parse("root"))); EXPECT_TRUE(is(IFunction::parse("exp"))); @@ -245,26 +252,27 @@ TEST(ParseTests, parseFunctionTest) { EXPECT_TRUE(is(IFunction::parse("integral"))); EXPECT_TRUE(is(IFunction::parse("frac", 2))); EXPECT_TRUE(is(IFunction::parse("frac", 3))); - EXPECT_TRUE(is(IFunction::parse("pow"))); EXPECT_TRUE(is(IFunction::parse("floor"))); EXPECT_TRUE(is(IFunction::parse("ceil"))); + EXPECT_TRUE(is(IFunction::parse("and"))); + EXPECT_TRUE(is(IFunction::parse("or"))); EXPECT_EQ(IFunction::parse("asdgewfe"), nullptr); EXPECT_EQ(IFunction::parse("1224"), nullptr); } TEST(ParseTests, parseOperatorTest) { - EXPECT_TRUE(is(IOperator::parse("+", IOperator::Priority::Addition))); + EXPECT_TRUE(is(IOperator::parse("+", IOperator::Priority::Addition))); EXPECT_TRUE(is(IOperator::parse("+", IOperator::Priority::PrefixUnary))); - EXPECT_TRUE(is(IOperator::parse("+", 2))); + EXPECT_TRUE(is(IOperator::parse("+", 2))); EXPECT_TRUE(is(IOperator::parse("+", 1))); EXPECT_TRUE(is(IOperator::parse("-", IOperator::Priority::Addition))); EXPECT_TRUE(is(IOperator::parse("-", IOperator::Priority::PrefixUnary))); EXPECT_TRUE(is(IOperator::parse("-", 2))); EXPECT_TRUE(is(IOperator::parse("-", 1))); - EXPECT_TRUE(is(IOperator::parse("*"))); + EXPECT_TRUE(is(IOperator::parse("*"))); EXPECT_TRUE(is
(IOperator::parse("/"))); - EXPECT_TRUE(is(IOperator::parse("^"))); + EXPECT_TRUE(is(IOperator::parse("^"))); EXPECT_TRUE(is(IOperator::parse("%"))); EXPECT_TRUE(is(IOperator::parse("!"))); EXPECT_TRUE(is(IOperator::parse("="))); @@ -274,8 +282,8 @@ TEST(ParseTests, parseOperatorTest) { EXPECT_TRUE(is(IOperator::parse("<="))); EXPECT_TRUE(is(IOperator::parse(">="))); EXPECT_TRUE(is(IOperator::parse("~"))); - EXPECT_TRUE(is(IOperator::parse("&"))); - EXPECT_TRUE(is(IOperator::parse("|"))); + EXPECT_TRUE(is(IOperator::parse("&"))); + EXPECT_TRUE(is(IOperator::parse("|"))); EXPECT_TRUE(is(IOperator::parse("->"))); EXPECT_TRUE(is(IOperator::parse("<->"))); EXPECT_TRUE(is(IOperator::parse("!<->"))); diff --git a/tests/src/expressions/ExpressionComparatorTests.cpp b/tests/src/expressions/ExpressionComparatorTests.cpp index a018920c1..1837436c4 100644 --- a/tests/src/expressions/ExpressionComparatorTests.cpp +++ b/tests/src/expressions/ExpressionComparatorTests.cpp @@ -1,20 +1,32 @@ #include -#include "fintamath/expressions/Expression.hpp" #include "fintamath/expressions/ExpressionComparator.hpp" +#include "fintamath/expressions/Expression.hpp" +#include "fintamath/expressions/ExpressionParser.hpp" + using namespace fintamath; using namespace detail; TEST(ExpressionComparatorTests, comparatorTest) { - EXPECT_EQ(compare(Variable("a").clone(), Expression("a").clone()), std::strong_ordering::equal); - EXPECT_EQ(compare(Expression("a").clone(), Expression("a").clone()), std::strong_ordering::equal); - EXPECT_EQ(compare(Integer(2).clone(), Expression("2 a").clone()), std::strong_ordering::less); + EXPECT_EQ(compare({}, {}), std::strong_ordering::equal); + EXPECT_EQ(compare({}, Integer(2).clone()), std::strong_ordering::less); + EXPECT_EQ(compare(Integer(2).clone(), {}), std::strong_ordering::greater); + + EXPECT_EQ(compare(Integer(2).clone(), Integer(2).clone()), std::strong_ordering::equal); + EXPECT_EQ(compare(Integer(2).clone(), Expression(2).clone()), std::strong_ordering::equal); EXPECT_EQ(compare(Integer(2).clone(), Expression("2 a").clone()), std::strong_ordering::less); + + EXPECT_EQ(compare(Variable("a").clone(), Variable("a").clone()), std::strong_ordering::equal); + EXPECT_EQ(compare(Variable("a").clone(), Expression("a").clone()), std::strong_ordering::equal); EXPECT_EQ(compare(Variable("a").clone(), Expression("a b").clone()), std::strong_ordering::less); EXPECT_EQ(compare(Variable("a").clone(), Expression("a + b").clone()), std::strong_ordering::less); + + EXPECT_EQ(compare(Expression("a").clone(), Expression("a").clone()), std::strong_ordering::equal); EXPECT_EQ(compare(Expression("a^b").clone(), Expression("a b c").clone()), std::strong_ordering::greater); - EXPECT_EQ(compare(Expression("x^x ln(x)").clone(), Expression("x^x").clone()), std::strong_ordering::greater); + EXPECT_EQ(compare(Expression("x^x").clone(), Expression("x^y").clone()), std::strong_ordering::greater); - // TODO: add more tests -} + EXPECT_EQ(compare(parseExpr("sqrt(11)"), parseExpr("root(2022369065670411386760301914510907000742418, 4)")), std::strong_ordering::greater); + EXPECT_EQ(compare(parseExpr("x^x ln(x)"), parseExpr("x^x")), std::strong_ordering::greater); + EXPECT_EQ(compare(parseExpr("~a & c"), parseExpr("a & b & ~c")), std::strong_ordering::greater); +} \ No newline at end of file diff --git a/tests/src/expressions/interfaces/IBinaryExpressionTests.cpp b/tests/src/expressions/interfaces/IBinaryExpressionTests.cpp index 4b07788bd..56e6f722e 100644 --- a/tests/src/expressions/interfaces/IBinaryExpressionTests.cpp +++ b/tests/src/expressions/interfaces/IBinaryExpressionTests.cpp @@ -2,11 +2,11 @@ #include "fintamath/expressions/interfaces/IBinaryExpression.hpp" -#include "fintamath/functions/arithmetic/Add.hpp" +#include "fintamath/functions/arithmetic/AddOper.hpp" using namespace fintamath; -const Add f; +const AddOper f; namespace { diff --git a/tests/src/expressions/interfaces/IPolynomExpressionTests.cpp b/tests/src/expressions/interfaces/IPolynomExpressionTests.cpp index 0185cef2f..6512d3824 100644 --- a/tests/src/expressions/interfaces/IPolynomExpressionTests.cpp +++ b/tests/src/expressions/interfaces/IPolynomExpressionTests.cpp @@ -26,10 +26,10 @@ class TestPolynomExpression final : public IPolynomExpressionCRTPtoString(), "a * 2"); + EXPECT_EQ(expr.toMinimalObject()->toString(), "mul(a, 2)"); } TEST(IPolynomExpressionTests, getTypeTest) { EXPECT_EQ(IPolynomExpression::getTypeStatic(), MathObjectType(MathObjectType::IPolynomExpression, "IPolynomExpression")); -} +} \ No newline at end of file diff --git a/tests/src/functions/IOperatorTests.cpp b/tests/src/functions/IOperatorTests.cpp index 202cce0ae..e25bce79a 100644 --- a/tests/src/functions/IOperatorTests.cpp +++ b/tests/src/functions/IOperatorTests.cpp @@ -3,25 +3,26 @@ #include "fintamath/functions/IOperator.hpp" #include "fintamath/functions/arithmetic/Add.hpp" +#include "fintamath/functions/arithmetic/AddOper.hpp" #include "fintamath/functions/arithmetic/Neg.hpp" -#include "fintamath/functions/logic/Or.hpp" +#include "fintamath/functions/logic/OrOper.hpp" #include "fintamath/functions/other/Factorial.hpp" -#include "fintamath/functions/powers/Pow.hpp" +#include "fintamath/functions/powers/PowOper.hpp" using namespace fintamath; TEST(IOperatorTests, getPriorityTest) { - EXPECT_EQ(Add().getPriority(), IOperator::Priority::Addition); + EXPECT_EQ(AddOper().getPriority(), IOperator::Priority::Addition); EXPECT_EQ(Neg().getPriority(), IOperator::Priority::PrefixUnary); EXPECT_EQ(Factorial().getPriority(), IOperator::Priority::PostfixUnary); - EXPECT_EQ(Or().getPriority(), IOperator::Priority::Disjunction); + EXPECT_EQ(OrOper().getPriority(), IOperator::Priority::Disjunction); } TEST(IOperatorTests, isAssociativeTest) { - EXPECT_TRUE(Add().isAssociative()); + EXPECT_TRUE(AddOper().isAssociative()); EXPECT_FALSE(Neg().isAssociative()); - EXPECT_TRUE(Or().isAssociative()); - EXPECT_FALSE(Pow().isAssociative()); + EXPECT_TRUE(OrOper().isAssociative()); + EXPECT_FALSE(PowOper().isAssociative()); } TEST(IOperatorTests, getTypeTest) { diff --git a/tests/src/functions/arithmetic/AddOperTests.cpp b/tests/src/functions/arithmetic/AddOperTests.cpp new file mode 100644 index 000000000..a9e5839c3 --- /dev/null +++ b/tests/src/functions/arithmetic/AddOperTests.cpp @@ -0,0 +1,65 @@ +#include +#include + +#include "fintamath/functions/arithmetic/AddOper.hpp" + +#include "fintamath/exceptions/InvalidInputException.hpp" +#include "fintamath/literals/Variable.hpp" +#include "fintamath/numbers/Rational.hpp" + +using namespace fintamath; + +using F = AddOper; +const F f; + +TEST(AddOperTests, toStringTest) { + EXPECT_EQ(f.toString(), "+"); +} + +TEST(AddOperTests, getArgumentTypesTest) { + EXPECT_THAT(f.getArgumentTypes(), testing::ElementsAre(IArithmetic::getTypeStatic(), IArithmetic::getTypeStatic())); +} + +TEST(AddOperTests, getReturnTypeTest) { + EXPECT_EQ(f.getReturnType(), IArithmetic::getTypeStatic()); +} + +TEST(AddOperTests, isVariadicTest) { + EXPECT_FALSE(F::isVariadicStatic()); + EXPECT_FALSE(f.isVariadic()); +} + +TEST(AddOperTests, isEvaluatableTest) { + EXPECT_TRUE(F::isEvaluatableStatic()); + EXPECT_TRUE(f.isEvaluatable()); +} + +TEST(AddOperTests, getPriorityTest) { + EXPECT_EQ(F::getPriorityStatic(), IOperator::Priority::Addition); + EXPECT_EQ(f.getPriority(), IOperator::Priority::Addition); +} + +TEST(AddOperTests, isAssociativeTest) { + EXPECT_TRUE(F::isAssociativeStatic()); + EXPECT_TRUE(f.isAssociative()); +} + +TEST(AddOperTests, callTest) { + EXPECT_EQ(f(Integer(3), Integer(5))->toString(), "8"); + EXPECT_EQ(f(Integer(3), Rational(5, 2))->toString(), "11/2"); + EXPECT_EQ(f(Rational(5, 2), Integer(3))->toString(), "11/2"); + EXPECT_EQ(f(Rational(5, 2), Rational(5, 2))->toString(), "5"); + EXPECT_EQ(f(Rational(5, 2), Rational(5, 3))->toString(), "25/6"); + + EXPECT_EQ(f(Integer(3), Variable("a"))->toString(), "a + 3"); + + EXPECT_THROW(f(Integer(1)), InvalidInputFunctionException); + EXPECT_THROW(f(Rational(2, 3)), InvalidInputFunctionException); + EXPECT_THROW(f(), InvalidInputFunctionException); + EXPECT_THROW(f(Integer(1), Integer(1), Integer(1)), InvalidInputFunctionException); +} + +TEST(AddOperTests, getTypeTest) { + EXPECT_EQ(F::getTypeStatic(), MathObjectType(MathObjectType::AddOper, "AddOper")); + EXPECT_EQ(f.getType(), MathObjectType(MathObjectType::AddOper, "AddOper")); +} diff --git a/tests/src/functions/arithmetic/AddTests.cpp b/tests/src/functions/arithmetic/AddTests.cpp index 2fe9654ea..a90d5527a 100644 --- a/tests/src/functions/arithmetic/AddTests.cpp +++ b/tests/src/functions/arithmetic/AddTests.cpp @@ -13,7 +13,7 @@ using F = Add; const F f; TEST(AddTests, toStringTest) { - EXPECT_EQ(f.toString(), "+"); + EXPECT_EQ(f.toString(), "add"); } TEST(AddTests, getArgumentTypesTest) { @@ -34,16 +34,6 @@ TEST(AddTests, isEvaluatableTest) { EXPECT_TRUE(f.isEvaluatable()); } -TEST(AddTests, getPriorityTest) { - EXPECT_EQ(F::getPriorityStatic(), IOperator::Priority::Addition); - EXPECT_EQ(f.getPriority(), IOperator::Priority::Addition); -} - -TEST(AddTests, isAssociativeTest) { - EXPECT_TRUE(F::isAssociativeStatic()); - EXPECT_TRUE(f.isAssociative()); -} - TEST(AddTests, callTest) { EXPECT_EQ(f(Integer(3), Integer(5))->toString(), "8"); EXPECT_EQ(f(Integer(3), Rational(5, 2))->toString(), "11/2"); diff --git a/tests/src/functions/arithmetic/MulOperTests.cpp b/tests/src/functions/arithmetic/MulOperTests.cpp new file mode 100644 index 000000000..4e1f91175 --- /dev/null +++ b/tests/src/functions/arithmetic/MulOperTests.cpp @@ -0,0 +1,63 @@ +#include +#include + +#include "fintamath/functions/arithmetic/MulOper.hpp" + +#include "fintamath/literals/Variable.hpp" +#include "fintamath/numbers/Rational.hpp" + +using namespace fintamath; + +using F = MulOper; +const F f; + +TEST(MulOperTests, toStringTest) { + EXPECT_EQ(f.toString(), "*"); +} + +TEST(MulOperTests, getArgumentTypesTest) { + EXPECT_THAT(f.getArgumentTypes(), testing::ElementsAre(IArithmetic::getTypeStatic(), IArithmetic::getTypeStatic())); +} + +TEST(MulOperTests, getReturnTypeTest) { + EXPECT_EQ(f.getReturnType(), IArithmetic::getTypeStatic()); +} + +TEST(MulOperTests, isVariadicTest) { + EXPECT_FALSE(F::isVariadicStatic()); + EXPECT_FALSE(f.isVariadic()); +} + +TEST(MulOperTests, isEvaluatableTest) { + EXPECT_TRUE(F::isEvaluatableStatic()); + EXPECT_TRUE(f.isEvaluatable()); +} + +TEST(MulOperTests, getPriorityTest) { + EXPECT_EQ(F::getPriorityStatic(), IOperator::Priority::Multiplication); + EXPECT_EQ(f.getPriority(), IOperator::Priority::Multiplication); +} + +TEST(MulOperTests, isAssociativeTest) { + EXPECT_TRUE(F::isAssociativeStatic()); + EXPECT_TRUE(f.isAssociative()); +} + +TEST(MulOperTests, callTest) { + EXPECT_EQ(f(Integer(3), Integer(5))->toString(), "15"); + EXPECT_EQ(f(Integer(3), Rational(5, 2))->toString(), "15/2"); + EXPECT_EQ(f(Rational(5, 2), Integer(3))->toString(), "15/2"); + EXPECT_EQ(f(Rational(5, 2), Rational(5, 3))->toString(), "25/6"); + + EXPECT_EQ(f(Integer(3), Variable("a"))->toString(), "3 a"); + + EXPECT_THROW(f(Integer(1)), InvalidInputFunctionException); + EXPECT_THROW(f(Rational(2, 3)), InvalidInputFunctionException); + EXPECT_THROW(f(), InvalidInputFunctionException); + EXPECT_THROW(f(Integer(1), Integer(1), Integer(1)), InvalidInputFunctionException); +} + +TEST(MulOperTests, getTypeTest) { + EXPECT_EQ(F::getTypeStatic(), MathObjectType(MathObjectType::MulOper, "MulOper")); + EXPECT_EQ(f.getType(), MathObjectType(MathObjectType::MulOper, "MulOper")); +} diff --git a/tests/src/functions/arithmetic/MulTests.cpp b/tests/src/functions/arithmetic/MulTests.cpp index 6975d50f2..20f10dff6 100644 --- a/tests/src/functions/arithmetic/MulTests.cpp +++ b/tests/src/functions/arithmetic/MulTests.cpp @@ -12,7 +12,7 @@ using F = Mul; const F f; TEST(MulTests, toStringTest) { - EXPECT_EQ(f.toString(), "*"); + EXPECT_EQ(f.toString(), "mul"); } TEST(MulTests, getArgumentTypesTest) { @@ -33,16 +33,6 @@ TEST(MulTests, isEvaluatableTest) { EXPECT_TRUE(f.isEvaluatable()); } -TEST(MulTests, getPriorityTest) { - EXPECT_EQ(F::getPriorityStatic(), IOperator::Priority::Multiplication); - EXPECT_EQ(f.getPriority(), IOperator::Priority::Multiplication); -} - -TEST(MulTests, isAssociativeTest) { - EXPECT_TRUE(F::isAssociativeStatic()); - EXPECT_TRUE(f.isAssociative()); -} - TEST(MulTests, callTest) { EXPECT_EQ(f(Integer(3), Integer(5))->toString(), "15"); EXPECT_EQ(f(Integer(3), Rational(5, 2))->toString(), "15/2"); diff --git a/tests/src/functions/logic/AndOperTests.cpp b/tests/src/functions/logic/AndOperTests.cpp new file mode 100644 index 000000000..3c439cc0a --- /dev/null +++ b/tests/src/functions/logic/AndOperTests.cpp @@ -0,0 +1,62 @@ +#include +#include + +#include "fintamath/functions/logic/AndOper.hpp" + +#include "fintamath/literals/Boolean.hpp" +#include "fintamath/literals/Variable.hpp" + +using namespace fintamath; + +using F = AndOper; +const F f; + +TEST(AndOperTests, toStringTest) { + EXPECT_EQ(f.toString(), "&"); +} + +TEST(AndOperTests, getArgumentTypesTest) { + EXPECT_THAT(f.getArgumentTypes(), testing::ElementsAre(Boolean::getTypeStatic(), Boolean::getTypeStatic())); +} + +TEST(AndOperTests, getReturnTypeTest) { + EXPECT_EQ(f.getReturnType(), Boolean::getTypeStatic()); +} + +TEST(AndOperTests, isVariadicTest) { + EXPECT_FALSE(F::isVariadicStatic()); + EXPECT_FALSE(f.isVariadic()); +} + +TEST(AndOperTests, isEvaluatableTest) { + EXPECT_TRUE(F::isEvaluatableStatic()); + EXPECT_TRUE(f.isEvaluatable()); +} + +TEST(AndOperTests, getPriorityTest) { + EXPECT_EQ(F::getPriorityStatic(), IOperator::Priority::Conjunction); + EXPECT_EQ(f.getPriority(), IOperator::Priority::Conjunction); +} + +TEST(AndOperTests, isAssociativeTest) { + EXPECT_TRUE(F::isAssociativeStatic()); + EXPECT_TRUE(f.isAssociative()); +} + +TEST(AndOperTests, callTest) { + EXPECT_EQ(f(Boolean(false), Boolean(false))->toString(), "False"); + EXPECT_EQ(f(Boolean(false), Boolean(true))->toString(), "False"); + EXPECT_EQ(f(Boolean(true), Boolean(false))->toString(), "False"); + EXPECT_EQ(f(Boolean(true), Boolean(true))->toString(), "True"); + + EXPECT_EQ(f(Variable("a"), Variable("b"))->toString(), "a & b"); + + EXPECT_THROW(f(), InvalidInputFunctionException); + EXPECT_THROW(f(Boolean(true)), InvalidInputFunctionException); + EXPECT_THROW(f(Boolean(true), Boolean(true), Boolean(true)), InvalidInputFunctionException); +} + +TEST(AndOperTests, getTypeTest) { + EXPECT_EQ(F::getTypeStatic(), MathObjectType(MathObjectType::And, "And")); + EXPECT_EQ(f.getType(), MathObjectType(MathObjectType::And, "And")); +} diff --git a/tests/src/functions/logic/AndTests.cpp b/tests/src/functions/logic/AndTests.cpp index 523327cb8..00b76531c 100644 --- a/tests/src/functions/logic/AndTests.cpp +++ b/tests/src/functions/logic/AndTests.cpp @@ -12,7 +12,7 @@ using F = And; const F f; TEST(AndTests, toStringTest) { - EXPECT_EQ(f.toString(), "&"); + EXPECT_EQ(f.toString(), "and"); } TEST(AndTests, getArgumentTypesTest) { @@ -33,16 +33,6 @@ TEST(AndTests, isEvaluatableTest) { EXPECT_TRUE(f.isEvaluatable()); } -TEST(AndTests, getPriorityTest) { - EXPECT_EQ(F::getPriorityStatic(), IOperator::Priority::Conjunction); - EXPECT_EQ(f.getPriority(), IOperator::Priority::Conjunction); -} - -TEST(AndTests, isAssociativeTest) { - EXPECT_TRUE(F::isAssociativeStatic()); - EXPECT_TRUE(f.isAssociative()); -} - TEST(AndTests, callTest) { EXPECT_EQ(f(Boolean(false), Boolean(false))->toString(), "False"); EXPECT_EQ(f(Boolean(false), Boolean(true))->toString(), "False"); diff --git a/tests/src/functions/logic/OrOperTests.cpp b/tests/src/functions/logic/OrOperTests.cpp new file mode 100644 index 000000000..6daf584de --- /dev/null +++ b/tests/src/functions/logic/OrOperTests.cpp @@ -0,0 +1,62 @@ +#include +#include + +#include "fintamath/functions/logic/OrOper.hpp" + +#include "fintamath/literals/Boolean.hpp" +#include "fintamath/literals/Variable.hpp" + +using namespace fintamath; + +using F = OrOper; +const F f; + +TEST(OrOperTests, toStringTest) { + EXPECT_EQ(f.toString(), "|"); +} + +TEST(OrOperTests, getArgumentTypesTest) { + EXPECT_THAT(f.getArgumentTypes(), testing::ElementsAre(Boolean::getTypeStatic(), Boolean::getTypeStatic())); +} + +TEST(OrOperTests, getReturnTypeTest) { + EXPECT_EQ(f.getReturnType(), Boolean::getTypeStatic()); +} + +TEST(OrOperTests, isVariadicTest) { + EXPECT_FALSE(F::isVariadicStatic()); + EXPECT_FALSE(f.isVariadic()); +} + +TEST(OrOperTests, isEvaluatableTest) { + EXPECT_TRUE(F::isEvaluatableStatic()); + EXPECT_TRUE(f.isEvaluatable()); +} + +TEST(OrOperTests, getPriorityTest) { + EXPECT_EQ(F::getPriorityStatic(), IOperator::Priority::Disjunction); + EXPECT_EQ(f.getPriority(), IOperator::Priority::Disjunction); +} + +TEST(OrOperTests, isAssociativeTest) { + EXPECT_TRUE(F::isAssociativeStatic()); + EXPECT_TRUE(f.isAssociative()); +} + +TEST(OrOperTests, callTest) { + EXPECT_EQ(f(Boolean(false), Boolean(false))->toString(), "False"); + EXPECT_EQ(f(Boolean(false), Boolean(true))->toString(), "True"); + EXPECT_EQ(f(Boolean(true), Boolean(false))->toString(), "True"); + EXPECT_EQ(f(Boolean(true), Boolean(true))->toString(), "True"); + + EXPECT_EQ(f(Variable("a"), Variable("b"))->toString(), "a | b"); + + EXPECT_THROW(f(), InvalidInputFunctionException); + EXPECT_THROW(f(Boolean(true)), InvalidInputFunctionException); + EXPECT_THROW(f(Boolean(true), Boolean(true), Boolean(true)), InvalidInputFunctionException); +} + +TEST(OrOperTests, getTypeTest) { + EXPECT_EQ(F::getTypeStatic(), MathObjectType(MathObjectType::Or, "Or")); + EXPECT_EQ(f.getType(), MathObjectType(MathObjectType::Or, "Or")); +} diff --git a/tests/src/functions/logic/OrTests.cpp b/tests/src/functions/logic/OrTests.cpp index 647fe84dd..430a075cd 100644 --- a/tests/src/functions/logic/OrTests.cpp +++ b/tests/src/functions/logic/OrTests.cpp @@ -12,7 +12,7 @@ using F = Or; const F f; TEST(OrTests, toStringTest) { - EXPECT_EQ(f.toString(), "|"); + EXPECT_EQ(f.toString(), "or"); } TEST(OrTests, getArgumentTypesTest) { @@ -33,16 +33,6 @@ TEST(OrTests, isEvaluatableTest) { EXPECT_TRUE(f.isEvaluatable()); } -TEST(OrTests, getPriorityTest) { - EXPECT_EQ(F::getPriorityStatic(), IOperator::Priority::Disjunction); - EXPECT_EQ(f.getPriority(), IOperator::Priority::Disjunction); -} - -TEST(OrTests, isAssociativeTest) { - EXPECT_TRUE(F::isAssociativeStatic()); - EXPECT_TRUE(f.isAssociative()); -} - TEST(OrTests, callTest) { EXPECT_EQ(f(Boolean(false), Boolean(false))->toString(), "False"); EXPECT_EQ(f(Boolean(false), Boolean(true))->toString(), "True"); diff --git a/tests/src/functions/powers/PowFunctionTests.cpp b/tests/src/functions/powers/PowOperTests.cpp similarity index 51% rename from tests/src/functions/powers/PowFunctionTests.cpp rename to tests/src/functions/powers/PowOperTests.cpp index ecec32aaf..bd48eafd8 100644 --- a/tests/src/functions/powers/PowFunctionTests.cpp +++ b/tests/src/functions/powers/PowOperTests.cpp @@ -1,40 +1,51 @@ #include #include -#include "fintamath/functions/powers/PowFunction.hpp" +#include "fintamath/functions/powers/PowOper.hpp" #include "fintamath/literals/Variable.hpp" +#include "fintamath/numbers/Complex.hpp" #include "fintamath/numbers/Rational.hpp" #include "fintamath/numbers/Real.hpp" using namespace fintamath; -using F = PowFunction; +using F = PowOper; const F f; -TEST(PowFunctionTests, toStringTest) { - EXPECT_EQ(f.toString(), "pow"); +TEST(PowOperTests, toStringTest) { + EXPECT_EQ(f.toString(), "^"); } -TEST(PowFunctionTests, getArgumentTypesTest) { +TEST(PowOperTests, getArgumentTypesTest) { EXPECT_THAT(f.getArgumentTypes(), testing::ElementsAre(IArithmetic::getTypeStatic(), IArithmetic::getTypeStatic())); } -TEST(PowFunctionTests, getReturnTypeTest) { +TEST(PowOperTests, getReturnTypeTest) { EXPECT_EQ(f.getReturnType(), IArithmetic::getTypeStatic()); } -TEST(PowFunctionTests, isVariadicTest) { +TEST(PowOperTests, isVariadicTest) { EXPECT_FALSE(F::isVariadicStatic()); EXPECT_FALSE(f.isVariadic()); } -TEST(PowFunctionTests, isEvaluatableTest) { +TEST(PowOperTests, isEvaluatableTest) { EXPECT_TRUE(F::isEvaluatableStatic()); EXPECT_TRUE(f.isEvaluatable()); } -TEST(PowFunctionTests, callTest) { +TEST(PowOperTests, getPriorityTest) { + EXPECT_EQ(F::getPriorityStatic(), IOperator::Priority::Exponentiation); + EXPECT_EQ(f.getPriority(), IOperator::Priority::Exponentiation); +} + +TEST(PowOperTests, isAssociativeTest) { + EXPECT_FALSE(F::isAssociativeStatic()); + EXPECT_FALSE(f.isAssociative()); +} + +TEST(PowOperTests, callTest) { EXPECT_EQ(f(Integer(3), Integer(2))->toString(), "9"); EXPECT_EQ(f(Rational(-10), Rational(-3))->toString(), "-1/1000"); @@ -42,13 +53,13 @@ TEST(PowFunctionTests, callTest) { EXPECT_EQ(f(Variable("a"), Rational(1, 2))->toString(), "sqrt(a)"); EXPECT_EQ(f(Variable("a"), Rational(3, 2))->toString(), "a^(3/2)"); - EXPECT_THROW(f(), InvalidInputFunctionException); - EXPECT_THROW(f(Integer(1)), InvalidInputFunctionException); - EXPECT_THROW(f(Rational(2, 3)), InvalidInputFunctionException); - EXPECT_THROW(f(Integer(1), Integer(1), Integer(1)), InvalidInputFunctionException); + EXPECT_THROW(f(), InvalidInputException); + EXPECT_THROW(f(Integer(1)), InvalidInputException); + EXPECT_THROW(f(Rational(2, 3)), InvalidInputException); + EXPECT_THROW(f(Integer(1), Integer(1), Integer(1)), InvalidInputException); } -TEST(PowFunctionTests, getTypeTest) { - EXPECT_EQ(F::getTypeStatic(), MathObjectType(MathObjectType::PowFunction, "PowFunction")); - EXPECT_EQ(f.getType(), MathObjectType(MathObjectType::PowFunction, "PowFunction")); +TEST(PowOperTests, getTypeTest) { + EXPECT_EQ(F::getTypeStatic(), MathObjectType(MathObjectType::PowOper, "PowOper")); + EXPECT_EQ(f.getType(), MathObjectType(MathObjectType::PowOper, "PowOper")); } diff --git a/tests/src/functions/powers/PowTests.cpp b/tests/src/functions/powers/PowTests.cpp index 5bf2b8653..a212e8751 100644 --- a/tests/src/functions/powers/PowTests.cpp +++ b/tests/src/functions/powers/PowTests.cpp @@ -14,7 +14,7 @@ using F = Pow; const F f; TEST(PowTests, toStringTest) { - EXPECT_EQ(f.toString(), "^"); + EXPECT_EQ(f.toString(), "pow"); } TEST(PowTests, getArgumentTypesTest) { @@ -35,16 +35,6 @@ TEST(PowTests, isEvaluatableTest) { EXPECT_TRUE(f.isEvaluatable()); } -TEST(PowTests, getPriorityTest) { - EXPECT_EQ(F::getPriorityStatic(), IOperator::Priority::Exponentiation); - EXPECT_EQ(f.getPriority(), IOperator::Priority::Exponentiation); -} - -TEST(PowTests, isAssociativeTest) { - EXPECT_FALSE(F::isAssociativeStatic()); - EXPECT_FALSE(f.isAssociative()); -} - TEST(PowTests, callTest) { EXPECT_EQ(f(Integer(3), Integer(0))->toString(), "1"); diff --git a/tests/src/overall/simplify/SimplifyDerivativeTests.cpp b/tests/src/overall/simplify/SimplifyDerivativeTests.cpp index 4e5617fe7..a4ccb9caa 100644 --- a/tests/src/overall/simplify/SimplifyDerivativeTests.cpp +++ b/tests/src/overall/simplify/SimplifyDerivativeTests.cpp @@ -60,15 +60,15 @@ TEST(SimplifyDerivativeTests, simplifyTest) { EXPECT_EQ(Expression("derivative(2 mod x, x)").toString(), "derivative(2 mod x, x)"); EXPECT_EQ(Expression("derivative(x ^ x, x)").toString(), - "x^x ln(x) + x^x"); + "ln(x) x^x + x^x"); EXPECT_EQ(Expression("derivative(x ^ y, x)").toString(), "x^(y - 1) y"); EXPECT_EQ(Expression("derivative(y ^ x, x)").toString(), - "y^x ln(y)"); + "ln(y) y^x"); EXPECT_EQ(Expression("derivative(x ^ 2, x)").toString(), "2 x"); EXPECT_EQ(Expression("derivative(2 ^ x, x)").toString(), - "2^x ln(2)"); + "2 ln(2) 2^(x - 1)"); EXPECT_EQ(Expression("derivative(x ^ (3/5), x)").toString(), "3/(5 x^(2/5))"); EXPECT_EQ(Expression("derivative((3/5) ^ x, x)").toString(), diff --git a/tests/src/overall/simplify/SimplifyLogicTests.cpp b/tests/src/overall/simplify/SimplifyLogicTests.cpp index 506dd5881..6a7104fa5 100644 --- a/tests/src/overall/simplify/SimplifyLogicTests.cpp +++ b/tests/src/overall/simplify/SimplifyLogicTests.cpp @@ -72,7 +72,7 @@ TEST(SimplifyLogicTests, simplifyTest) { EXPECT_EQ(Expression("~(x <= 1)").toString(), "x - 1 > 0"); EXPECT_EQ(Expression("~(x <= 1 | y >= 1)").toString(), - "x - 1 > 0 & y - 1 < 0"); + "y - 1 < 0 & x - 1 > 0"); EXPECT_EQ(Expression("~a").toString(), "~a"); @@ -92,9 +92,9 @@ TEST(SimplifyLogicTests, simplifyTest) { EXPECT_EQ(Expression("a -> b").toString(), "~a | b"); EXPECT_EQ(Expression("a <-> b").toString(), - "(a & b) | (~a & ~b)"); + "(~a & ~b) | (a & b)"); EXPECT_EQ(Expression("a !<-> b").toString(), - "(a & ~b) | (~a & b)"); + "(~a & b) | (a & ~b)"); EXPECT_EQ(Expression("a & a").toString(), "a"); @@ -177,7 +177,7 @@ TEST(SimplifyLogicTests, simplifyTest) { EXPECT_EQ(Expression("a<->a<->a<->a<->a<->a<->a").toString(), "a"); EXPECT_EQ(Expression("a&b->b&c").toString(), - "~a | (b & c) | ~b"); + "~a | ~b | (b & c)"); EXPECT_EQ(Expression("a&b&c").toString(), "a & b & c"); EXPECT_EQ(Expression("a&(b&c)").toString(), @@ -223,11 +223,11 @@ TEST(SimplifyLogicTests, simplifyTest) { EXPECT_EQ(Expression("(x | ~y | (x | ~y | z) & (y | z)) & (y | (x & ~y & z) | (y & z))").toString(), "(x & ~y & z) | (x & y) | (y & z)"); EXPECT_EQ(Expression("~a & b | ~c -> a <-> b !<-> c").toString(), - "(a & b & ~c) | (~a & ~b & ~c) | (~a & c) | (~b & c)"); + "(~a & ~b & ~c) | (~a & c) | (a & b & ~c) | (~b & c)"); EXPECT_EQ(Expression("~~~a & ~~b | ~~~c -> ~~a <-> ~~b !<-> ~~c").toString(), - "(a & b & ~c) | (~a & ~b & ~c) | (~a & c) | (~b & c)"); + "(~a & ~b & ~c) | (~a & c) | (a & b & ~c) | (~b & c)"); EXPECT_EQ(Expression("((a | b) & (a -> c)) <-> (~a -> b)").toString(), - "(a & c) | ~a | (b & c)"); + "~a | (a & c) | (b & c)"); EXPECT_EQ(Expression("x=1&a").toString(), "a & x - 1 = 0"); @@ -246,22 +246,22 @@ TEST(SimplifyLogicTests, simplifyLargeTest) { // EXPECT_EQ(Expression("a<->b<->c<->d<->e<->f").toString(), EXPECT_EQ(Expression("a<->b<->c<->d<->e").toString(), - "(a & b & c & d & e) | " - "(a & b & c & ~d & ~e) | " - "(a & b & ~c & d & ~e) | " - "(a & b & ~c & ~d & e) | " - "(a & ~b & c & d & ~e) | " - "(a & ~b & c & ~d & e) | " - "(a & ~b & ~c & d & e) | " - "(a & ~b & ~c & ~d & ~e) | " - "(~a & b & c & d & ~e) | " - "(~a & b & c & ~d & e) | " - "(~a & b & ~c & d & e) | " - "(~a & b & ~c & ~d & ~e) | " - "(~a & ~b & c & d & e) | " - "(~a & ~b & c & ~d & ~e) | " + "(~a & ~b & ~c & ~d & e) | " "(~a & ~b & ~c & d & ~e) | " - "(~a & ~b & ~c & ~d & e)"); + "(~a & ~b & c & ~d & ~e) | " + "(~a & ~b & c & d & e) | " + "(~a & b & ~c & ~d & ~e) | " + "(~a & b & ~c & d & e) | " + "(~a & b & c & ~d & e) | " + "(~a & b & c & d & ~e) | " + "(a & ~b & ~c & ~d & ~e) | " + "(a & ~b & ~c & d & e) | " + "(a & ~b & c & ~d & e) | " + "(a & ~b & c & d & ~e) | " + "(a & b & ~c & ~d & e) | " + "(a & b & ~c & d & ~e) | " + "(a & b & c & ~d & ~e) | " + "(a & b & c & d & e)"); EXPECT_EQ(Expression("a & b & c & d & e & f & g & h & i & j & k & l & m & n & o & p & q & r & s & t & u & v & w & x & y & z & x_1 & x_2 & x_3 | x_4").toString(), "(a & b & c & d & e & f & g & h & i & j & k & l & m & n & o & p & q & r & s & t & u & v & w & x & x_1 & x_2 & x_3 & y & z) | x_4"); diff --git a/tests/src/overall/simplify/SimplifyTests.cpp b/tests/src/overall/simplify/SimplifyTests.cpp index d25724fa6..e12d61c64 100644 --- a/tests/src/overall/simplify/SimplifyTests.cpp +++ b/tests/src/overall/simplify/SimplifyTests.cpp @@ -531,7 +531,7 @@ TEST(SimplifyTests, simplifyTest) { EXPECT_EQ(Expression("a - sqrt(2) x - sqrt(3) x - Pi^4 x + 1").toString(), "a + (-Pi^4 - sqrt(3) - sqrt(2)) x + 1"); EXPECT_EQ(Expression("x Pi^4 ln(5) + x E^2 sin(1) sinh(2)").toString(), - "(E^2 sinh(2) sin(1) + Pi^4 ln(5)) x"); + "(sin(1) sinh(2) E^2 + ln(5) Pi^4) x"); EXPECT_EQ(Expression("(a+b) (-sqrt2 + sqrt3 - sqrt5)").toString(), "(sqrt(3) - sqrt(5) - sqrt(2)) a + (sqrt(3) - sqrt(5) - sqrt(2)) b"); EXPECT_EQ(Expression("(sqrt(2) x + sqrt(3) x + Pi^4 x + 1) / (sqrt(2) + sqrt(3) + Pi^4)").toString(),