From 7441b35594bf3c181bdad624352ce7d23adb5125 Mon Sep 17 00:00:00 2001 From: fintarin Date: Tue, 19 Sep 2023 19:17:36 +0300 Subject: [PATCH] Fix PowExpression::powSimplify --- .../expressions/binary/PowExpression.cpp | 26 ++++++++++++------- .../expressions/binary/PowExpression.hpp | 2 -- .../expressions/ExpressionFunctionsTests.cpp | 6 ++--- tests/src/expressions/ExpressionTests.cpp | 23 ++++++++-------- 4 files changed, 31 insertions(+), 26 deletions(-) diff --git a/src/fintamath/expressions/binary/PowExpression.cpp b/src/fintamath/expressions/binary/PowExpression.cpp index d58893711..1a07d8b50 100644 --- a/src/fintamath/expressions/binary/PowExpression.cpp +++ b/src/fintamath/expressions/binary/PowExpression.cpp @@ -6,6 +6,7 @@ #include "fintamath/functions/arithmetic/Div.hpp" #include "fintamath/functions/arithmetic/Mul.hpp" #include "fintamath/functions/arithmetic/Neg.hpp" +#include "fintamath/functions/comparison/MoreEqv.hpp" #include "fintamath/functions/powers/Pow.hpp" #include "fintamath/functions/powers/Root.hpp" #include "fintamath/functions/powers/Sqrt.hpp" @@ -81,13 +82,6 @@ ArgumentPtr PowExpression::preciseSimplify() const { return IBinaryExpression::preciseSimplify(); } -PowExpression::SimplifyFunctionsVector PowExpression::getFunctionsForPreSimplify() const { - static const PowExpression::SimplifyFunctionsVector simplifyFunctions = { - &PowExpression::powSimplify, - }; - return simplifyFunctions; -} - PowExpression::SimplifyFunctionsVector PowExpression::getFunctionsForPostSimplify() const { static const PowExpression::SimplifyFunctionsVector simplifyFunctions = { &PowExpression::constSimplify, @@ -182,9 +176,21 @@ ArgumentPtr PowExpression::powSimplify(const IFunction & /*func*/, const Argumen ArgumentPtr res; if (auto lhsExpr = cast(lhs); lhsExpr && is(lhsExpr->getFunction())) { - ArgumentPtr lhsPow = lhsExpr->getChildren().front(); - ArgumentPtr rhsPow = mulExpr(lhsExpr->getChildren().back(), rhs); - res = powExpr(lhsPow, rhsPow); + auto lhsExprLhsChild = lhsExpr->getChildren().front(); + auto lhsExprRhsChild = lhsExpr->getChildren().back(); + + bool canMul = is(rhs) && is(lhsExprRhsChild); + + if (auto lhsExprLhsChildNum = cast(lhsExprLhsChild)) { + canMul = canMul || + *MoreEqv()(*lhsExprLhsChildNum, Integer(0)) == Boolean(true); + } + + if (canMul) { + ArgumentPtr newLhs = lhsExprLhsChild; + ArgumentPtr newRhs = mulExpr(lhsExprRhsChild, rhs); + res = powExpr(newLhs, newRhs); + } } return res; diff --git a/src/fintamath/expressions/binary/PowExpression.hpp b/src/fintamath/expressions/binary/PowExpression.hpp index 9f22aa6f4..1861217a6 100644 --- a/src/fintamath/expressions/binary/PowExpression.hpp +++ b/src/fintamath/expressions/binary/PowExpression.hpp @@ -20,8 +20,6 @@ class PowExpression : public IBinaryExpressionCRTP { protected: ArgumentPtr preciseSimplify() const override; - SimplifyFunctionsVector getFunctionsForPreSimplify() const override; - SimplifyFunctionsVector getFunctionsForPostSimplify() const override; private: diff --git a/tests/src/expressions/ExpressionFunctionsTests.cpp b/tests/src/expressions/ExpressionFunctionsTests.cpp index c30407ff5..8f2ffe3e7 100644 --- a/tests/src/expressions/ExpressionFunctionsTests.cpp +++ b/tests/src/expressions/ExpressionFunctionsTests.cpp @@ -102,14 +102,14 @@ TEST(ExpressionFunctionsTests, factorialTest) { TEST(ExpressionFunctionsTests, sqrtTest) { EXPECT_EQ(sqrt(Expression("4")).toString(), "2"); EXPECT_EQ(sqrt(Expression("5")).toString(), "sqrt(5)"); - EXPECT_EQ(sqrt(Expression("a^4")).toString(), "a^2"); - EXPECT_EQ(sqrt(Expression("a^2*b*b")).toString(), "a b"); + EXPECT_EQ(sqrt(Expression("a^4")).toString(), "sqrt(a^4)"); + EXPECT_EQ(sqrt(Expression("a^2*b*b")).toString(), "sqrt(a^2) sqrt(b^2)"); EXPECT_EQ(sqrt(Expression("a^2+b^2+2*a*b")).toString(), "sqrt(a^2 + 2 a b + b^2)"); } TEST(ExpressionFunctionsTests, powTest) { EXPECT_EQ(pow(Expression("a+b"), Expression("0")).toString(), "1"); - EXPECT_EQ(pow(Expression("a^4"), Expression("a")).toString(), "a^(4 a)"); + EXPECT_EQ(pow(Expression("a^4"), Expression("a")).toString(), "(a^4)^a"); EXPECT_EQ(pow(Expression("a^4"), Expression("2")).toString(), "a^8"); EXPECT_EQ(pow(Expression("a*b"), Expression("a+3")).toString(), "a^(a + 3) b^(a + 3)"); EXPECT_EQ(pow(Expression("a+2"), Expression("2")).toString(), "a^2 + 4 a + 4"); diff --git a/tests/src/expressions/ExpressionTests.cpp b/tests/src/expressions/ExpressionTests.cpp index 1bfc56150..5c441f985 100644 --- a/tests/src/expressions/ExpressionTests.cpp +++ b/tests/src/expressions/ExpressionTests.cpp @@ -185,7 +185,9 @@ TEST(ExpressionTests, stringConstructorTest) { EXPECT_EQ(Expression("2*sqrt((1-cos(2*(Pi/3)))/2)*cos(Pi/3)").toString(), "sqrt(3)/2"); EXPECT_EQ(Expression("-sin(2)").toString(), "-sin(2)"); EXPECT_EQ(Expression("2^(3/2)").toString(), "2 sqrt(2)"); + EXPECT_EQ(Expression("sqrt((-1)^2)").toString(), "1"); EXPECT_EQ(Expression("sqrt(sqrt5)").toString(), "root(5, 4)"); + EXPECT_EQ(Expression("sqrt(sqrt(-5))").toString(), "sqrt(I) root(5, 4)"); EXPECT_EQ(Expression("sqrt4!").toString(), "2"); EXPECT_EQ(Expression("(sqrt4)!").toString(), "2"); EXPECT_EQ(Expression("sqrt4*2!").toString(), "4"); @@ -255,9 +257,9 @@ TEST(ExpressionTests, stringConstructorTest) { EXPECT_EQ(Expression("x/y/z").toString(), "x/(y z)"); EXPECT_EQ(Expression("x/(y/z)").toString(), "(x z)/y"); EXPECT_EQ(Expression("(x/y)/z").toString(), "x/(y z)"); - EXPECT_EQ(Expression("x^y^z").toString(), "x^(y z)"); + EXPECT_EQ(Expression("x^y^z").toString(), "(x^y)^z"); EXPECT_EQ(Expression("x^(y^z)").toString(), "x^(y^z)"); - EXPECT_EQ(Expression("(x^y)^z").toString(), "x^(y z)"); + EXPECT_EQ(Expression("(x^y)^z").toString(), "(x^y)^z"); EXPECT_EQ(Expression("(a+b)^2").toString(), "a^2 + 2 a b + b^2"); EXPECT_EQ(Expression("(a+b)^3").toString(), "a^3 + 3 a^2 b + 3 a b^2 + b^3"); EXPECT_EQ(Expression("1*(a+b)^3").toString(), "a^3 + 3 a^2 b + 3 a b^2 + b^3"); @@ -362,6 +364,7 @@ TEST(ExpressionTests, stringConstructorTest) { EXPECT_EQ(Expression("sqrt(x) + x").toString(), "x + sqrt(x)"); EXPECT_EQ(Expression("sqrt(x) - x").toString(), "-x + sqrt(x)"); + EXPECT_EQ(Expression("sqrt(x) * sqrt(x)").toString(), "x"); EXPECT_EQ(Expression("x/(sqrt(x) - x)").toString(), "-1 - sqrt(x)/(x - sqrt(x))"); EXPECT_EQ(Expression("x/(2 sqrt(x) - x)").toString(), "-1 - (2 sqrt(x))/(x - 2 sqrt(x))"); EXPECT_EQ(Expression("(x-1)/(sqrt(x) - x)").toString(), "-1 - 1/sqrt(x)"); @@ -401,15 +404,13 @@ TEST(ExpressionTests, stringConstructorTest) { EXPECT_EQ(Expression("log(E^3, E)").toString(), "1/3"); EXPECT_EQ(Expression("log(E^Pi, E)").toString(), "1/Pi"); - // TODO! implement this - // EXPECT_EQ(Expression("sqrt((-1)^2)").toString(), "abs(x)"); - // EXPECT_EQ(Expression("sqrt((-1)^2)").toString(), "abs(x)"); - // 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"); - // EXPECT_EQ(Expression("sqrt(x)^2").toString(), "x"); - // EXPECT_EQ(Expression("sqrt(x) * sqrt(x)").toString(), "x"); - // EXPECT_EQ(Expression("root(x^(-2), )").toString(), "abs(1/x)"); + EXPECT_EQ(Expression("sqrt(x^2)").toString(), "sqrt(x^2)"); + EXPECT_EQ(Expression("(x^10)^(1/10)").toString(), "root(x^10, 10)"); + EXPECT_EQ(Expression("(x^3)^(1/3)").toString(), "root(x^3, 3)"); + EXPECT_EQ(Expression("sqrt(x)^2").toString(), "sqrt(x)^2"); + EXPECT_EQ(Expression("root(x^(-2), -2)").toString(), "sqrt(x^2)"); + + // TODO: implement // EXPECT_EQ(Expression("abs(x)^3").toString(), "abs(x^3)"); // EXPECT_EQ(Expression("abs(x^3)").toString(), "abs(x^3)"); // EXPECT_EQ(Expression("abs(x)^I").toString(), "abs(x)^I");