From a4c1ffcd91765b8b1fcfb5aeda52a8bf6005b6e1 Mon Sep 17 00:00:00 2001 From: fintarin Date: Wed, 9 Aug 2023 21:12:05 +0300 Subject: [PATCH] Sin constants simplify --- .../expressions/unary/TrigExpression.cpp | 30 ++++++++++++- .../expressions/ExpressionFunctionsTests.cpp | 4 +- tests/src/expressions/ExpressionTests.cpp | 43 ++++++++++++++++++- 3 files changed, 72 insertions(+), 5 deletions(-) diff --git a/src/fintamath/expressions/unary/TrigExpression.cpp b/src/fintamath/expressions/unary/TrigExpression.cpp index cc1cb513d..657d61a77 100644 --- a/src/fintamath/expressions/unary/TrigExpression.cpp +++ b/src/fintamath/expressions/unary/TrigExpression.cpp @@ -89,7 +89,35 @@ ArgumentPtr TrigExpression::trigTableSimplify(const IFunction &func, const Ratio return trigTable.at(func.toString())(rhs); } -ArgumentPtr TrigExpression::trigTableSinSimplify(Rational /*rhs*/) { +ArgumentPtr TrigExpression::trigTableSinSimplify(Rational rhs) { + static const TrigonometryTable trigTable = { + {Rational(0), Integer(0).clone()}, // 0 | 0 + {Rational(1, 6), Rational(1, 2).clone()}, // π/6 | 1/2 + {Rational(1, 4), makeExpr(Div(), *makeExpr(Sqrt(), Integer(2)), Integer(2))}, // π/4 | √2/2 + {Rational(1, 3), makeExpr(Div(), *makeExpr(Sqrt(), Integer(3)), Integer(2))}, // π/3 | √3/2 + {Rational(1, 2), Integer(1).clone()}, // π/2 | 1 + {Rational(2, 3), makeExpr(Div(), *makeExpr(Sqrt(), Integer(3)), Integer(2))}, // 2π/3 | √3/2 + {Rational(3, 4), makeExpr(Div(), *makeExpr(Sqrt(), Integer(2)), Integer(2))}, // 3π/4 | √2/2 + {Rational(5, 6), Rational(1, 2).clone()}, // 5π/6 | 1/2 + {Rational(1), Integer(0).clone()}, // π | 0 + }; + + bool isResNegated = false; + + if (rhs < 0) { + rhs = -rhs; + isResNegated = !isResNegated; + } + + if (rhs.numerator() > rhs.denominator()) { + rhs = Rational(rhs.numerator() % rhs.denominator(), rhs.denominator()); + isResNegated = !isResNegated; + } + + if (auto res = trigTable.find(rhs); res != trigTable.end()) { + return isResNegated ? makeExpr(Neg(), res->second) : res->second; + } + return {}; } diff --git a/tests/src/expressions/ExpressionFunctionsTests.cpp b/tests/src/expressions/ExpressionFunctionsTests.cpp index 06daa9e82..68e535810 100644 --- a/tests/src/expressions/ExpressionFunctionsTests.cpp +++ b/tests/src/expressions/ExpressionFunctionsTests.cpp @@ -145,8 +145,8 @@ TEST(ExpressionFunctionsTests, lgTest) { TEST(ExpressionFunctionsTests, sinTest) { // TODO trigonometry - EXPECT_EQ(sin(Expression("5*Pi")).toString(), "sin(5 Pi)"); - EXPECT_EQ(sin(Expression("Pi/2")).toString(), "sin(Pi/2)"); + EXPECT_EQ(sin(Expression("5*Pi")).toString(), "0"); + EXPECT_EQ(sin(Expression("Pi/2")).toString(), "1"); EXPECT_EQ(sin(Expression("a+b")).toString(), "sin(a + b)"); } diff --git a/tests/src/expressions/ExpressionTests.cpp b/tests/src/expressions/ExpressionTests.cpp index b79943dc8..736dccd22 100644 --- a/tests/src/expressions/ExpressionTests.cpp +++ b/tests/src/expressions/ExpressionTests.cpp @@ -172,8 +172,6 @@ TEST(ExpressionTests, stringConstructorTest) { 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(), "cos(1)^2 + sin(1)^2"); - EXPECT_EQ(Expression("sin(Pi/3)").toString(), "sin(Pi/3)"); - EXPECT_EQ(Expression("cos(Pi/3)").toString(), "cos(Pi/3)"); EXPECT_EQ(Expression("2!*E").toString(), "2 E"); EXPECT_EQ(Expression("E*2!").toString(), "2 E"); EXPECT_EQ(Expression("sqrt((1-cos(2*(Pi/3)))/2)").toString(), "sqrt(-cos((2 Pi)/3)/2 + 1/2)"); @@ -684,6 +682,47 @@ TEST(ExpressionTests, stringConstructorTest) { EXPECT_EQ(Expression("atanh(tanh(x))").toString(), "atanh(tanh(x))"); EXPECT_EQ(Expression("acoth(coth(x))").toString(), "acoth(coth(x))"); + EXPECT_EQ(Expression("sin(-13Pi/6)").toString(), "-1/2"); + EXPECT_EQ(Expression("sin(-2Pi)").toString(), "0"); + EXPECT_EQ(Expression("sin(-11Pi/6)").toString(), "1/2"); + EXPECT_EQ(Expression("sin(-7Pi/4)").toString(), "sqrt(2)/2"); + EXPECT_EQ(Expression("sin(-5Pi/3)").toString(), "sqrt(3)/2"); + EXPECT_EQ(Expression("sin(-3Pi/2)").toString(), "1"); + EXPECT_EQ(Expression("sin(-4Pi/3)").toString(), "sqrt(3)/2"); + EXPECT_EQ(Expression("sin(-5Pi/4)").toString(), "sqrt(2)/2"); + EXPECT_EQ(Expression("sin(-7Pi/6)").toString(), "1/2"); + EXPECT_EQ(Expression("sin(-Pi)").toString(), "0"); + EXPECT_EQ(Expression("sin(-5Pi/6)").toString(), "-1/2"); + EXPECT_EQ(Expression("sin(-3Pi/4)").toString(), "-sqrt(2)/2"); + EXPECT_EQ(Expression("sin(-2Pi/3)").toString(), "-sqrt(3)/2"); + EXPECT_EQ(Expression("sin(-Pi/2)").toString(), "-1"); + EXPECT_EQ(Expression("sin(-Pi/3)").toString(), "-sqrt(3)/2"); + EXPECT_EQ(Expression("sin(-Pi/4)").toString(), "-sqrt(2)/2"); + EXPECT_EQ(Expression("sin(-Pi/6)").toString(), "-1/2"); + EXPECT_EQ(Expression("sin(0)").toString(), "0"); + EXPECT_EQ(Expression("sin(Pi/6)").toString(), "1/2"); + EXPECT_EQ(Expression("sin(Pi/4)").toString(), "sqrt(2)/2"); + EXPECT_EQ(Expression("sin(Pi/3)").toString(), "sqrt(3)/2"); + EXPECT_EQ(Expression("sin(Pi/2)").toString(), "1"); + EXPECT_EQ(Expression("sin(2Pi/3)").toString(), "sqrt(3)/2"); + EXPECT_EQ(Expression("sin(3Pi/4)").toString(), "sqrt(2)/2"); + EXPECT_EQ(Expression("sin(5Pi/6)").toString(), "1/2"); + EXPECT_EQ(Expression("sin(Pi)").toString(), "0"); + EXPECT_EQ(Expression("sin(7Pi/6)").toString(), "-1/2"); + EXPECT_EQ(Expression("sin(5Pi/4)").toString(), "-sqrt(2)/2"); + EXPECT_EQ(Expression("sin(4Pi/3)").toString(), "-sqrt(3)/2"); + EXPECT_EQ(Expression("sin(3Pi/2)").toString(), "-1"); + EXPECT_EQ(Expression("sin(5Pi/3)").toString(), "-sqrt(3)/2"); + EXPECT_EQ(Expression("sin(7Pi/4)").toString(), "-sqrt(2)/2"); + EXPECT_EQ(Expression("sin(11Pi/6)").toString(), "-1/2"); + EXPECT_EQ(Expression("sin(2Pi)").toString(), "0"); + EXPECT_EQ(Expression("sin(13Pi/6)").toString(), "1/2"); + + EXPECT_EQ(Expression("sin(E Pi)").toString(), "sin(E Pi)"); + EXPECT_EQ(Expression("cos(E Pi)").toString(), "cos(E Pi)"); + EXPECT_EQ(Expression("tan(E Pi)").toString(), "tan(E Pi)"); + EXPECT_EQ(Expression("cot(E Pi)").toString(), "cot(E Pi)"); + // EXPECT_EQ(Expression("sin(x)^2 + cos(x)^2").toString(), "1"); // TODO: implement // EXPECT_EQ(Expression("tan(x)*cot(x)").toString(), "1"); // TODO: implement // EXPECT_EQ(Expression("tanh(x)*coth(x)").toString(), "1"); // TODO: implement