Skip to content

Commit

Permalink
Simplify trigonometry in AddExpression instead of PowExpression
Browse files Browse the repository at this point in the history
  • Loading branch information
fintarin committed Dec 1, 2023
1 parent 9b2fee7 commit f43182b
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 69 deletions.
34 changes: 0 additions & 34 deletions src/fintamath/expressions/binary/PowExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ PowExpression::SimplifyFunctionVector PowExpression::getFunctionsForPostSimplify
&PowExpression::constSimplify,
&PowExpression::polynomSimplify,
&PowExpression::powSimplify,
&PowExpression::trigDoubleAngleSimplify,
};
return simplifyFunctions;
}
Expand Down Expand Up @@ -331,39 +330,6 @@ ArgumentPtr PowExpression::constSimplify(const IFunction & /*func*/, const Argum
return {};
}

ArgumentPtr PowExpression::trigDoubleAngleSimplify(const IFunction & /*func*/, const ArgumentPtr &lhs, const ArgumentPtr &rhs) {
if (*rhs != Integer(2)) {
return {};
}

const auto lhsExpr = cast<IExpression>(lhs);
if (!lhsExpr) {
return {};
}

auto lhsChild = lhsExpr->getChildren().front();
if (containsInfinity(lhsChild)) {
return {};
}

ArgumentPtr doubleCos = cosExpr(
mulExpr(lhsChild, Integer(2).clone()));

if (is<Cos>(lhsExpr->getFunction())) {
return divExpr(
addExpr(doubleCos, Integer(1).clone()),
Integer(2).clone());
}

if (is<Sin>(lhsExpr->getFunction())) {
return divExpr(
addExpr(doubleCos, Integer(-1).clone()),
Integer(-2).clone());
}

return {};
}

ArgumentPtr PowExpression::polynomSimplify(const IFunction & /*func*/, const ArgumentPtr &lhs, const ArgumentPtr &rhs) {
if (auto res = mulSimplify(lhs, rhs)) {
return res;
Expand Down
2 changes: 0 additions & 2 deletions src/fintamath/expressions/binary/PowExpression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ class PowExpression : public IBinaryExpressionCRTP<PowExpression> {

static ArgumentPtr constSimplify(const IFunction &func, const ArgumentPtr &lhs, const ArgumentPtr &rhs);

static ArgumentPtr trigDoubleAngleSimplify(const IFunction &func, const ArgumentPtr &lhs, const ArgumentPtr &rhs);

static ArgumentPtr polynomSimplify(const IFunction &func, const ArgumentPtr &lhs, const ArgumentPtr &rhs);

static ArgumentPtr mulSimplify(const ArgumentPtr &lhs, const ArgumentPtr &rhs);
Expand Down
76 changes: 76 additions & 0 deletions src/fintamath/expressions/polynomial/AddExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
#include "fintamath/functions/arithmetic/Sub.hpp"
#include "fintamath/functions/logarithms/Log.hpp"
#include "fintamath/functions/powers/Pow.hpp"
#include "fintamath/functions/powers/Sqr.hpp"
#include "fintamath/functions/trigonometry/Cos.hpp"
#include "fintamath/functions/trigonometry/Sin.hpp"
#include "fintamath/literals/Variable.hpp"
#include "fintamath/literals/constants/ComplexInf.hpp"
#include "fintamath/literals/constants/IConstant.hpp"
Expand Down Expand Up @@ -91,6 +94,7 @@ AddExpression::SimplifyFunctionVector AddExpression::getFunctionsForPostSimplify
&AddExpression::mulSimplify,
&AddExpression::logSimplify,
&AddExpression::mulLogSimplify,
&AddExpression::trigSimplify,
};
return simplifyFunctions;
}
Expand Down Expand Up @@ -313,4 +317,76 @@ ArgumentPtr AddExpression::divSimplify(const IFunction & /*func*/, const Argumen
return res;
}

ArgumentPtr AddExpression::trigSimplify(const IFunction & /*func*/, const ArgumentPtr &lhs, const ArgumentPtr &rhs) {
auto [lhsMulRate, lhsMulValue] = splitMulExpr(lhs, false);
auto [rhsMulRate, rhsMulValue] = splitMulExpr(rhs, false);

auto [lhsPowRate, lhsPowValue] = splitPowExpr(lhsMulValue);
auto [rhsPowRate, rhsPowValue] = splitPowExpr(rhsMulValue);

auto lhsPowValueExpr = cast<IExpression>(lhsPowValue);
auto rhsPowValueExpr = cast<IExpression>(rhsPowValue);

if (!lhsPowValueExpr || *lhsPowRate != Integer(2)) {
return {};
}

if (containsInfinity(lhsPowValue) || containsInfinity(rhsPowValue)) {
return {};
}

auto lhsPowValueChild = lhsPowValueExpr->getChildren().front();

auto lhsMulRateNum = cast<INumber>(lhsMulRate);

if (rhsPowValueExpr && *rhsPowRate == Integer(2)) {
if (!is<Sin>(lhsPowValueExpr->getFunction()) || !is<Cos>(rhsPowValueExpr->getFunction())) {
return {};
}

auto rhsPowValueChild = rhsPowValueExpr->getChildren().front();

if (*lhsPowValueChild != *rhsPowValueChild) {
return {};
}

if (*lhsMulRate == *rhsMulRate) {
return lhsMulRate;
}

auto rhsMulRateNum = cast<INumber>(rhsMulRate);

if (lhsMulRateNum && rhsMulRateNum && *(*lhsMulRateNum + *rhsMulRateNum) == Integer(0)) {
ArgumentPtr res = cosExpr(
mulExpr(
lhsPowValueExpr->getChildren().front(),
Integer(2).clone()));

return mulExpr(rhsMulRateNum, res);
}

return {};
}

auto rhsNum = cast<INumber>(rhs);

if (lhsMulRateNum && rhsNum && *(*lhsMulRateNum + *rhsNum) == Integer(0)) {
ArgumentPtr res = lhsPowValueExpr->getChildren().front();

if (is<Sin>(lhsPowValueExpr->getFunction())) {
res = cosExpr(res);
}
else if (is<Cos>(lhsPowValueExpr->getFunction())) {
res = sinExpr(res);
}
else {
return {};
}

return mulExpr(rhsNum, sqrExpr(res));
}

return {};
}

}
2 changes: 2 additions & 0 deletions src/fintamath/expressions/polynomial/AddExpression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ class AddExpression : public IPolynomExpressionCRTP<AddExpression> {

static ArgumentPtr mulSimplify(const IFunction &func, const ArgumentPtr &lhs, const ArgumentPtr &rhs);

static ArgumentPtr trigSimplify(const IFunction &func, const ArgumentPtr &lhs, const ArgumentPtr &rhs);

static std::vector<size_t> findLogarithms(const ArgumentPtrVector &children);

static std::shared_ptr<const IExpression> mulToLogarithm(const ArgumentPtrVector &children, size_t i);
Expand Down
2 changes: 1 addition & 1 deletion tests/src/expressions/ExpressionFunctionsTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ TEST(ExpressionFunctionsTests, derivativeTest) {
EXPECT_EQ(derivative(Expression("a"), Expression("a")).toString(), "1");
EXPECT_EQ(derivative(Expression("(a+5)"), Expression("a")).toString(), "1");
EXPECT_EQ(derivative(Expression("sin(a^2)"), Expression("a")).toString(), "2 a cos(a^2)");
EXPECT_EQ(derivative(Expression("(ln(a)/tan(a))^(1/2)"), Expression("a")).toString(), "sqrt(ln(a))/(sqrt(cot(a)) cos(2 a) - sqrt(cot(a))) + sqrt(cot(a))/(2 sqrt(ln(a)) a)");
EXPECT_EQ(derivative(Expression("(ln(a)/tan(a))^(1/2)"), Expression("a")).toString(), "-(sqrt(ln(a)) csc(a)^2)/(2 sqrt(cot(a))) + sqrt(cot(a))/(2 sqrt(ln(a)) a)");
}

TEST(ExpressionFunctionsTests, notTest) {
Expand Down
101 changes: 69 additions & 32 deletions tests/src/expressions/ExpressionTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,9 @@ TEST(ExpressionTests, stringConstructorTest) {
EXPECT_EQ(Expression("acsch1.9").toString(), "acsch(19/10)");
EXPECT_EQ(Expression("((2))*sqrt2").toString(), "2 sqrt(2)");
EXPECT_EQ(Expression("sqrt2*((2))").toString(), "2 sqrt(2)");
EXPECT_EQ(Expression("sin(1)^2").toString(), "-cos(2)/2 + 1/2");
EXPECT_EQ(Expression("sin(-1)^2").toString(), "-cos(2)/2 + 1/2");
EXPECT_EQ(Expression("sin1^2").toString(), "-cos(2)/2 + 1/2");
EXPECT_EQ(Expression("sin(1)^2").toString(), "sin(1)^2");
EXPECT_EQ(Expression("sin(-1)^2").toString(), "sin(1)^2");
EXPECT_EQ(Expression("sin1^2").toString(), "sin(1)^2");
EXPECT_EQ(Expression("sin(10^30)").toString(), "sin(1000000000000000000000000000000)");
EXPECT_EQ(Expression("sin(1)^2 + cos(1)^2").toString(), "1");
EXPECT_EQ(Expression("3sin(1)^2 + 3cos(1)^2").toString(), "3");
Expand Down Expand Up @@ -544,9 +544,9 @@ TEST(ExpressionTests, stringConstructorTest) {
EXPECT_EQ(Expression("1/(sin(x)+1)").toString(), "1/(sin(x) + 1)");
EXPECT_EQ(Expression("(x+1)^3").toString(), "x^3 + 3 x^2 + 3 x + 1");
EXPECT_EQ(Expression("(x+1)^(-3)").toString(), "1/(x^3 + 3 x^2 + 3 x + 1)");
EXPECT_EQ(Expression("(sin(x)+1)^3").toString(), "sin(x)^3 + 3 sin(x) - (3 cos(2 x))/2 + 5/2");
EXPECT_EQ(Expression("(sin(x)+1)^(-3)").toString(), "2/(2 sin(x)^3 + 6 sin(x) - 3 cos(2 x) + 5)");
EXPECT_EQ(Expression("(sin(x)+1)^(-4)").toString(), "1/(sin(x)^4 + 4 sin(x)^3 + 4 sin(x) - 3 cos(2 x) + 4)");
EXPECT_EQ(Expression("(sin(x)+1)^3").toString(), "sin(x)^3 + 3 sin(x)^2 + 3 sin(x) + 1");
EXPECT_EQ(Expression("(sin(x)+1)^(-3)").toString(), "1/(sin(x)^3 + 3 sin(x)^2 + 3 sin(x) + 1)");
EXPECT_EQ(Expression("(sin(x)+1)^(-4)").toString(), "1/(sin(x)^4 + 4 sin(x)^3 + 6 sin(x)^2 + 4 sin(x) + 1)");
EXPECT_EQ(Expression("(x)sin(a)").toString(), "sin(a) x");
EXPECT_EQ(Expression("tan(4 a^3 b) + cot(4 a b^3) + b^4 + sin(a^4) + cos(6 a^2 b^2)").toString(),
"sin(a^4) + tan(4 a^3 b) + cos(6 a^2 b^2) + cot(4 a b^3) + b^4");
Expand Down Expand Up @@ -675,10 +675,10 @@ TEST(ExpressionTests, stringConstructorTest) {
EXPECT_EQ(Expression("derivative(sin(x^2), x)").toString(), "2 x cos(x^2)");
EXPECT_EQ(Expression("derivative(cos(x), x)").toString(), "-sin(x)");
EXPECT_EQ(Expression("derivative(cos(x^2), x)").toString(), "-2 x sin(x^2)");
EXPECT_EQ(Expression("derivative(tan(x), x)").toString(), "2/(cos(2 x) + 1)");
EXPECT_EQ(Expression("derivative(tan(x^2), x)").toString(), "(4 x)/(cos(2 x^2) + 1)");
EXPECT_EQ(Expression("derivative(cot(x), x)").toString(), "2/(cos(2 x) - 1)");
EXPECT_EQ(Expression("derivative(cot(x^2), x)").toString(), "(4 x)/(cos(2 x^2) - 1)");
EXPECT_EQ(Expression("derivative(tan(x), x)").toString(), "sec(x)^2");
EXPECT_EQ(Expression("derivative(tan(x^2), x)").toString(), "2 x sec(x^2)^2");
EXPECT_EQ(Expression("derivative(cot(x), x)").toString(), "-csc(x)^2");
EXPECT_EQ(Expression("derivative(cot(x^2), x)").toString(), "-2 x csc(x^2)^2");
EXPECT_EQ(Expression("derivative(sec(x), x)").toString(), "tan(x) sec(x)");
EXPECT_EQ(Expression("derivative(sec(x^2), x)").toString(), "2 x tan(x^2) sec(x^2)");
EXPECT_EQ(Expression("derivative(csc(x), x)").toString(), "-cot(x) csc(x)");
Expand Down Expand Up @@ -752,20 +752,20 @@ TEST(ExpressionTests, stringConstructorTest) {
EXPECT_EQ(Expression("derivative(sin(x)^2, x)").toString(), "sin(2 x)");
EXPECT_EQ(Expression("derivative(cos(x)^2, x)").toString(), "-sin(2 x)");
EXPECT_EQ(Expression("derivative(ln(cos(3x)), x)").toString(), "-3 tan(3 x)");
EXPECT_EQ(Expression("derivative(log(sin(x^5), tan(x^3)), x)").toString(), "((6 x^2)/(cos(2 x^3) + 1))/(tan(x^3) ln(sin(x^5))) - (5 x^4 cot(x^5) ln(tan(x^3)))/(ln(sin(x^5))^2)");
EXPECT_EQ(Expression("derivative(log(sin(x^5), tan(x^3)), x)").toString(), "(3 sec(x^3)^2 x^2)/(tan(x^3) ln(sin(x^5))) - (5 x^4 cot(x^5) ln(tan(x^3)))/(ln(sin(x^5))^2)");
EXPECT_EQ(Expression("derivative(acos(4x + 5)^5, x)").toString(), "-(20 acos(4 x + 5)^4)/sqrt(-16 x^2 - 40 x - 24)");
EXPECT_EQ(Expression("derivative(sin(sin(sin(x))), x)").toString(), "cos(sin(sin(x))) cos(sin(x)) cos(x)");
// EXPECT_EQ(Expression("derivative(cos(tan(cot(x))), x)").toString(), ""); // TODO: csc(x)^2 sec(cot(x))^2 sin(tan(cot(x)))
EXPECT_EQ(Expression("derivative(cos(tan(cot(x))), x)").toString(), "sec(cot(x))^2 csc(x)^2 sin(tan(cot(x)))");
EXPECT_EQ(Expression("derivative(a b cos(x), x)").toString(), "-a b sin(x)");
EXPECT_EQ(Expression("derivative(a x cos(x) ln(x) sign(x), x)").toString(), "(a x derivative(sign(x), x) cos(x) - a x sin(x) sign(x) + a cos(x) sign(x)) ln(x) + a cos(x) sign(x)");
EXPECT_EQ(Expression("derivative(a * c * cos(x)/(x^2 + 1), x)").toString(), "-(a c x^2 sin(x) + 2 a c x cos(x) + a c sin(x))/(x^4 + 2 x^2 + 1)");
EXPECT_EQ(Expression("derivative((2x^3)/tan(x), x)").toString(), "6 x^2 cot(x) + (4 x^3)/(cos(2 x) - 1)");
EXPECT_EQ(Expression("derivative((2x^3)/tan(x), x)").toString(), "-2 x^3 csc(x)^2 + 6 x^2 cot(x)");
EXPECT_EQ(Expression("derivative(acos(x)/(x^2 + 1), x)").toString(), "-(x^2 + 2 x sqrt(-x^2 + 1) acos(x) + 1)/(sqrt(-x^2 + 1) x^4 + 2 sqrt(-x^2 + 1) x^2 + sqrt(-x^2 + 1))");
EXPECT_EQ(Expression("derivative(sin(x)/sinh(x), x)").toString(), "-sin(x) coth(x) csch(x) + cos(x) csch(x)");
EXPECT_EQ(Expression("derivative(tan(x)/tanh(x), x)").toString(), "-csch(x)^2 tan(x) + (2 coth(x))/(cos(2 x) + 1)");
EXPECT_EQ(Expression("derivative(tan(x)/tanh(x), x)").toString(), "sec(x)^2 coth(x) - csch(x)^2 tan(x)");
EXPECT_EQ(Expression("derivative(derivative(derivative(sin(x^3), x), x), x)").toString(), "-27 x^6 cos(x^3) - 54 x^3 sin(x^3) + 6 cos(x^3)");
EXPECT_EQ(Expression("derivative(x^2, x) + derivative(y^2, y)").toString(), "2 x + 2 y");
EXPECT_EQ(Expression("derivative(sin(x^3), x) + derivative(cos(y^3), y) / derivative(tan(ln(y)), y)").toString(), "3 x^2 cos(x^3) - 3 y^3 sin(y^3) - (3 y^4 cos(4 ln(y)) sin(y^3) - 3 y^4 sin(y^3))/(4 y cos(2 ln(y)) + 4 y)");
EXPECT_EQ(Expression("derivative(sin(x^3), x) + derivative(cos(y^3), y) / derivative(tan(ln(y)), y)").toString(), "3 x^2 cos(x^3) - (3 y^3 sin(y^3))/(sec(ln(y))^2)");

// TODO: integral
EXPECT_EQ(Expression("integral(x, x)").toString(), "integral(x, x)");
Expand Down Expand Up @@ -970,20 +970,20 @@ TEST(ExpressionTests, stringConstructorTest) {
EXPECT_EQ(Expression("sin(x)/cos(x)").toString(), "tan(x)");
EXPECT_EQ(Expression("(-2sin(x))/cos(x)").toString(), "-2 tan(x)");
EXPECT_EQ(Expression("(2sin(x))/(3cos(x))").toString(), "(2 tan(x))/3");
EXPECT_EQ(Expression("sin(x)^2/cos(x)").toString(), "-(sec(x) cos(2 x))/2 + sec(x)/2");
EXPECT_EQ(Expression("sin(x)/cos(x)^2").toString(), "(2 sin(x))/(cos(2 x) + 1)");
EXPECT_EQ(Expression("sin(x)^2/cos(x)^2").toString(), "-1 + 2/(cos(2 x) + 1)");
EXPECT_EQ(Expression("(2sin(x))^2/cos(x)^2").toString(), "-4 + 8/(cos(2 x) + 1)");
EXPECT_EQ(Expression("(2sin(x))^2/(3cos(x))^2").toString(), "-4/9 + 8/(9 cos(2 x) + 9)");
EXPECT_EQ(Expression("sin(x)^2/cos(x)").toString(), "sin(x)^2 sec(x)");
EXPECT_EQ(Expression("sin(x)/cos(x)^2").toString(), "sec(x)^2 sin(x)");
EXPECT_EQ(Expression("sin(x)^2/cos(x)^2").toString(), "tan(x)^2");
EXPECT_EQ(Expression("(2sin(x))^2/cos(x)^2").toString(), "4 tan(x)^2");
EXPECT_EQ(Expression("(2sin(x))^2/(3cos(x))^2").toString(), "(4 tan(x)^2)/9");

EXPECT_EQ(Expression("cos(x)/sin(x)").toString(), "cot(x)");
EXPECT_EQ(Expression("(-2cos(x))/sin(x)").toString(), "-2 cot(x)");
EXPECT_EQ(Expression("(2cos(x))/(3sin(x))").toString(), "(2 cot(x))/3");
EXPECT_EQ(Expression("cos(x)^2/sin(x)").toString(), "(csc(x) cos(2 x))/2 + csc(x)/2");
EXPECT_EQ(Expression("cos(x)/sin(x)^2").toString(), "-(2 cos(x))/(cos(2 x) - 1)");
EXPECT_EQ(Expression("cos(x)^2/sin(x)^2").toString(), "-1 - 2/(cos(2 x) - 1)");
EXPECT_EQ(Expression("(2cos(x))^2/sin(x)^2").toString(), "-4 - 8/(cos(2 x) - 1)");
EXPECT_EQ(Expression("(2cos(x))^2/(3sin(x))^2").toString(), "-4/9 - 8/(9 cos(2 x) - 9)");
EXPECT_EQ(Expression("cos(x)^2/sin(x)").toString(), "cos(x)^2 csc(x)");
EXPECT_EQ(Expression("cos(x)/sin(x)^2").toString(), "csc(x)^2 cos(x)");
EXPECT_EQ(Expression("cos(x)^2/sin(x)^2").toString(), "cot(x)^2");
EXPECT_EQ(Expression("(2cos(x))^2/sin(x)^2").toString(), "4 cot(x)^2");
EXPECT_EQ(Expression("(2cos(x))^2/(3sin(x))^2").toString(), "(4 cot(x)^2)/9");

EXPECT_EQ(Expression("sec(x)/csc(x)").toString(), "tan(x)");
EXPECT_EQ(Expression("csc(x)/sec(x)").toString(), "cot(x)");
Expand All @@ -992,22 +992,59 @@ TEST(ExpressionTests, stringConstructorTest) {

EXPECT_EQ(Expression("sin(x)cos(x)").toString(), "sin(2 x)/2");
EXPECT_EQ(Expression("sin(x)cos(x)sign(x)").toString(), "(sign(x) sin(2 x))/2");
EXPECT_EQ(Expression("sin(x)^2").toString(), "-cos(2 x)/2 + 1/2");
EXPECT_EQ(Expression("cos(x)^2").toString(), "cos(2 x)/2 + 1/2");

EXPECT_EQ(Expression("sin(x)^2").toString(), "sin(x)^2");
EXPECT_EQ(Expression("cos(x)^2").toString(), "cos(x)^2");
EXPECT_EQ(Expression("1 - sin(x)^2").toString(), "cos(x)^2");
EXPECT_EQ(Expression("-1 + sin(x)^2").toString(), "-cos(x)^2");
EXPECT_EQ(Expression("2 - 2sin(x)^2").toString(), "2 cos(x)^2");
EXPECT_EQ(Expression("-2 + 2sin(x)^2").toString(), "-2 cos(x)^2");
EXPECT_EQ(Expression("1 - cos(x)^2").toString(), "sin(x)^2");
EXPECT_EQ(Expression("-1 + cos(x)^2").toString(), "-sin(x)^2");
EXPECT_EQ(Expression("2 - 2cos(x)^2").toString(), "2 sin(x)^2");
EXPECT_EQ(Expression("-2 + 2cos(x)^2").toString(), "-2 sin(x)^2");
EXPECT_EQ(Expression("1 - 2sin(x)^2").toString(), "-2 sin(x)^2 + 1"); // TODO: cos of double angle
EXPECT_EQ(Expression("1 - 2cos(x)^2").toString(), "-2 cos(x)^2 + 1"); // TODO: cos of double angle

EXPECT_EQ(Expression("sin(x)^2 + cos(x)^2").toString(), "1");
EXPECT_EQ(Expression("sin(x)^2 - cos(x)^2").toString(), "-cos(2 x)");
EXPECT_EQ(Expression("-sin(x)^2 + cos(x)^2").toString(), "cos(2 x)");
EXPECT_EQ(Expression("-sin(x)^2 - cos(x)^2").toString(), "-1");
EXPECT_EQ(Expression("2sin(x)^2 + 2cos(x)^2").toString(), "2");
EXPECT_EQ(Expression("sin(x)^2 + 2cos(x)^2").toString(), "cos(2 x)/2 + 3/2");
EXPECT_EQ(Expression("2sin(x)^2 + cos(x)^2").toString(), "-cos(2 x)/2 + 3/2");
EXPECT_EQ(Expression("2sin(x)^2 - 3cos(x)^2").toString(), "-(5 cos(2 x))/2 - 1/2");
EXPECT_EQ(Expression("-5sin(x)^2 + 10cos(x)^2").toString(), "(15 cos(2 x))/2 + 5/2");
EXPECT_EQ(Expression("-4sin(x)^2 - 6cos(x)^2").toString(), "-cos(2 x) - 5");
EXPECT_EQ(Expression("sin(x)^2 + 2cos(x)^2").toString(), "sin(x)^2 + 2 cos(x)^2");
EXPECT_EQ(Expression("2sin(x)^2 + cos(x)^2").toString(), "2 sin(x)^2 + cos(x)^2");
EXPECT_EQ(Expression("2sin(x)^2 - 3cos(x)^2").toString(), "2 sin(x)^2 - 3 cos(x)^2");
EXPECT_EQ(Expression("-5sin(x)^2 + 10cos(x)^2").toString(), "-5 sin(x)^2 + 10 cos(x)^2");
EXPECT_EQ(Expression("-4sin(x)^2 - 6cos(x)^2").toString(), "-4 sin(x)^2 - 6 cos(x)^2");
EXPECT_EQ(Expression("(2I + 2) sin(x)^2 + (2I + 2) cos(x)^2").toString(), "2 + 2 I");
EXPECT_EQ(Expression("(2I + 2) sin(x)^2 + (2I - 2) cos(x)^2").toString(), "(2 + 2 I) sin(x)^2 + (-2 + 2 I) cos(x)^2");
EXPECT_EQ(Expression("(2I + 2) sin(x)^2 + (-2I + 2) cos(x)^2").toString(), "(2 + 2 I) sin(x)^2 + (2 - 2 I) cos(x)^2");
EXPECT_EQ(Expression("(2I + 2) sin(x)^2 + (-2I - 2) cos(x)^2").toString(), "(-2 - 2 I) cos(2 x)");
EXPECT_EQ(Expression("(2I - 2) sin(x)^2 + (2I + 2) cos(x)^2").toString(), "(-2 + 2 I) sin(x)^2 + (2 + 2 I) cos(x)^2");
EXPECT_EQ(Expression("(2I - 2) sin(x)^2 + (2I - 2) cos(x)^2").toString(), "-2 + 2 I");
EXPECT_EQ(Expression("(2I - 2) sin(x)^2 + (-2I + 2) cos(x)^2").toString(), "(2 - 2 I) cos(2 x)");
EXPECT_EQ(Expression("(2I - 2) sin(x)^2 + (-2I - 2) cos(x)^2").toString(), "(-2 + 2 I) sin(x)^2 + (-2 - 2 I) cos(x)^2");
EXPECT_EQ(Expression("(-2I + 2) sin(x)^2 + (2I + 2) cos(x)^2").toString(), "(2 - 2 I) sin(x)^2 + (2 + 2 I) cos(x)^2");
EXPECT_EQ(Expression("(-2I + 2) sin(x)^2 + (2I - 2) cos(x)^2").toString(), "(-2 + 2 I) cos(2 x)");
EXPECT_EQ(Expression("(-2I + 2) sin(x)^2 + (-2I + 2) cos(x)^2").toString(), "2 - 2 I");
EXPECT_EQ(Expression("(-2I + 2) sin(x)^2 + (-2I - 2) cos(x)^2").toString(), "(2 - 2 I) sin(x)^2 + (-2 - 2 I) cos(x)^2");
EXPECT_EQ(Expression("(-2I - 2) sin(x)^2 + (2I + 2) cos(x)^2").toString(), "(2 + 2 I) cos(2 x)");
EXPECT_EQ(Expression("(-2I - 2) sin(x)^2 + (2I - 2) cos(x)^2").toString(), "(-2 - 2 I) sin(x)^2 + (-2 + 2 I) cos(x)^2");
EXPECT_EQ(Expression("(-2I - 2) sin(x)^2 + (-2I + 2) cos(x)^2").toString(), "(-2 - 2 I) sin(x)^2 + (2 - 2 I) cos(x)^2");
EXPECT_EQ(Expression("(-2I - 2) sin(x)^2 + (-2I - 2) cos(x)^2").toString(), "-2 - 2 I");
// TODO: simplify
EXPECT_EQ(Expression("E sin(x)^2 + E cos(x)^2").toString(), "E sin(x)^2 + E cos(x)^2");
EXPECT_EQ(Expression("E sin(x)^2 - E cos(x)^2").toString(), "E sin(x)^2 - E cos(x)^2");
EXPECT_EQ(Expression("-E sin(x)^2 + E cos(x)^2").toString(), "-E sin(x)^2 + E cos(x)^2");
EXPECT_EQ(Expression("-E sin(x)^2 - E cos(x)^2").toString(), "-E sin(x)^2 - E cos(x)^2");
EXPECT_EQ(Expression("E^2 sin(x)^2 + E cos(x)^2").toString(), "sin(x)^2 E^2 + E cos(x)^2");
EXPECT_EQ(Expression("E^2 sin(x)^2 - E cos(x)^2").toString(), "sin(x)^2 E^2 - E cos(x)^2");
EXPECT_EQ(Expression("-E^2 sin(x)^2 + E cos(x)^2").toString(), "-sin(x)^2 E^2 + E cos(x)^2");
EXPECT_EQ(Expression("-E^2 sin(x)^2 - E cos(x)^2").toString(), "-sin(x)^2 E^2 - E cos(x)^2");
EXPECT_EQ(Expression("sin(x) * sin(x) + cos(x) * cos(x)").toString(), "1");
EXPECT_EQ(Expression("(sin(x) + cos(x))^2").toString(), "sin(2 x) + 1");
EXPECT_EQ(Expression("(sin(x) - cos(x))^2").toString(), "-sin(2 x) + 1");
EXPECT_EQ(Expression("sin(x)^2 + cos(y)^2").toString(), "sin(x)^2 + cos(y)^2");

EXPECT_EQ(Expression("tan(x) * cot(x)").toString(), "1");
EXPECT_EQ(Expression("cot(x) * tan(x)").toString(), "1");
Expand Down

0 comments on commit f43182b

Please sign in to comment.