From 1f0141ba0c876f85f79424c9de9eb8dd21d58ea0 Mon Sep 17 00:00:00 2001 From: fintarin Date: Wed, 12 Jul 2023 17:15:32 +0300 Subject: [PATCH] Implement Pow(Div, Expr) --- .../expressions/binary/PowExpression.cpp | 28 +++++++++++++++++-- .../expressions/binary/PowExpression.hpp | 2 ++ tests/src/expressions/ExpressionTests.cpp | 7 ++++- tests/src/functions/powers/RootTests.cpp | 2 +- 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/fintamath/expressions/binary/PowExpression.cpp b/src/fintamath/expressions/binary/PowExpression.cpp index 62ee029cf..dd2841001 100644 --- a/src/fintamath/expressions/binary/PowExpression.cpp +++ b/src/fintamath/expressions/binary/PowExpression.cpp @@ -20,9 +20,9 @@ PowExpression::PowExpression(const ArgumentPtr &inLhsChild, const ArgumentPtr &i } std::string PowExpression::toString() const { - if (auto val = cast(rhsChild)) { - const Integer &numerator = val->numerator(); - const Integer &denominator = val->denominator(); + if (auto rhsChildRat = cast(rhsChild)) { + const Integer &numerator = rhsChildRat->numerator(); + const Integer &denominator = rhsChildRat->denominator(); if (numerator == 1) { if (denominator == 2) { @@ -33,6 +33,12 @@ std::string PowExpression::toString() const { } } + if (auto rhsChildExpr = cast(rhsChild); rhsChildExpr && is
(rhsChildExpr->getFunction())) { + if (*rhsChildExpr->getChildren().front() == Integer(1)) { + return functionToString(Root(), {lhsChild, rhsChildExpr->getChildren().back()}); + } + } + return IBinaryExpression::toString(); } @@ -219,6 +225,10 @@ ArgumentPtr PowExpression::polynomSimplify(const IFunction & /*func*/, const Arg return res; } + if (auto res = divSimplify(lhs, rhs)) { + return res; + } + return {}; } @@ -238,6 +248,18 @@ ArgumentPtr PowExpression::mulSimplify(const ArgumentPtr &lhs, const ArgumentPtr return res; } +ArgumentPtr PowExpression::divSimplify(const ArgumentPtr &lhs, const ArgumentPtr &rhs) { + ArgumentPtr res; + + if (auto divExpr = cast(lhs); divExpr && is
(divExpr->getFunction())) { + ArgumentPtr numerator = makeExpr(Pow(), divExpr->getChildren().front(), rhs); + ArgumentPtr denominator = makeExpr(Pow(), divExpr->getChildren().back(), rhs); + res = makeExpr(Div(), numerator, denominator); + } + + return res; +} + ArgumentPtr PowExpression::sumSimplify(const ArgumentPtr &lhs, const ArgumentPtr &rhs) { if (const auto rhsInt = cast(rhs)) { if (auto sumExpr = sumPolynomSimplify(lhs, *rhsInt)) { diff --git a/src/fintamath/expressions/binary/PowExpression.hpp b/src/fintamath/expressions/binary/PowExpression.hpp index 4cd075a83..58a835809 100644 --- a/src/fintamath/expressions/binary/PowExpression.hpp +++ b/src/fintamath/expressions/binary/PowExpression.hpp @@ -43,6 +43,8 @@ class PowExpression : public IBinaryExpressionCRTP { static ArgumentPtr mulSimplify(const ArgumentPtr &lhs, const ArgumentPtr &rhs); + static ArgumentPtr divSimplify(const ArgumentPtr &lhs, const ArgumentPtr &rhs); + static ArgumentPtr sumSimplify(const ArgumentPtr &lhs, const ArgumentPtr &rhs); }; diff --git a/tests/src/expressions/ExpressionTests.cpp b/tests/src/expressions/ExpressionTests.cpp index a9b345481..53f47c1e0 100644 --- a/tests/src/expressions/ExpressionTests.cpp +++ b/tests/src/expressions/ExpressionTests.cpp @@ -351,8 +351,13 @@ TEST(ExpressionTests, stringConstructorTest) { EXPECT_EQ(Expression("(a+b)*(a+b)*(1/(a+b))").toString(), "a + b"); EXPECT_EQ(Expression("(x^2+2x+1)/(x+1)").toString(), "x + 1"); + EXPECT_EQ(Expression("(x/y)^2").toString(), "x^2/y^2"); + EXPECT_EQ(Expression("(x/y)^(1/2)").toString(), "sqrt(x)/sqrt(y)"); + EXPECT_EQ(Expression("(x/y)^(1/3)").toString(), "root(x, 3)/root(y, 3)"); + EXPECT_EQ(Expression("(x/y)^x").toString(), "x^x/y^x"); + EXPECT_EQ(Expression("(x/y)^(1/x)").toString(), "root(x, x)/root(y, x)"); + // TODO! implement this - // EXPECT_EQ(Expression("(x/y)^2").toString(), "(x^2)/(y^2)"); // EXPECT_EQ(Expression("sqrt(x^2)").toString(), "abs(x)"); // EXPECT_EQ(Expression("(x^10)^(1/10))").toString(), "abs(x)"); // EXPECT_EQ(Expression("(x^3)^(1/3)").toString(), "x"); diff --git a/tests/src/functions/powers/RootTests.cpp b/tests/src/functions/powers/RootTests.cpp index 367678137..dd97bbc37 100644 --- a/tests/src/functions/powers/RootTests.cpp +++ b/tests/src/functions/powers/RootTests.cpp @@ -90,7 +90,7 @@ TEST(RootTests, callTest) { EXPECT_EQ(f(Variable("a"), Integer(2))->toString(), "sqrt(a)"); EXPECT_EQ(f(Variable("a"), Integer(3))->toString(), "root(a, 3)"); EXPECT_EQ(f(Variable("a"), Integer(123))->toString(), "root(a, 123)"); - EXPECT_EQ(f(Integer(2), Variable("a"))->toString(), "2^(1/a)"); + EXPECT_EQ(f(Integer(2), Variable("a"))->toString(), "root(2, a)"); EXPECT_THROW(f(Integer(-10), Integer(2)), UndefinedException); EXPECT_THROW(f(Rational(-9289, 10), Rational(2, 3)), UndefinedException);