diff --git a/poincare/include/poincare/hyperbolic_arc_cosine.h b/poincare/include/poincare/hyperbolic_arc_cosine.h index f4a6ef928..c49ca9617 100644 --- a/poincare/include/poincare/hyperbolic_arc_cosine.h +++ b/poincare/include/poincare/hyperbolic_arc_cosine.h @@ -20,6 +20,8 @@ public: // Properties Type type() const override { return Type::HyperbolicArcCosine; } private: + // Simplification + bool isNotableValue(Expression e) const override { return e.isRationalOne(); } // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/hyperbolic_cosine.h b/poincare/include/poincare/hyperbolic_cosine.h index 749540b8e..efd9e632d 100644 --- a/poincare/include/poincare/hyperbolic_cosine.h +++ b/poincare/include/poincare/hyperbolic_cosine.h @@ -20,6 +20,8 @@ public: // Properties Type type() const override { return Type::HyperbolicCosine; } private: + // Simplification + Expression imageOfNotableValue() const override { return Rational::Builder(1); } // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/hyperbolic_trigonometric_function.h b/poincare/include/poincare/hyperbolic_trigonometric_function.h index 798beb928..62a896c49 100644 --- a/poincare/include/poincare/hyperbolic_trigonometric_function.h +++ b/poincare/include/poincare/hyperbolic_trigonometric_function.h @@ -3,10 +3,12 @@ #include #include +#include namespace Poincare { class HyperbolicTrigonometricFunctionNode : public ExpressionNode { + friend class HyperbolicTrigonometricFunction; public: // TreeNode int numberOfChildren() const override { return 1; } @@ -15,12 +17,16 @@ private: LayoutShape leftLayoutShape() const override { return LayoutShape::MoreLetters; }; LayoutShape rightLayoutShape() const override { return LayoutShape::BoundaryPunctuation; } Expression shallowReduce(ReductionContext reductionContext) override; + virtual bool isNotableValue(Expression e) const { return e.isRationalZero(); } + virtual Expression imageOfNotableValue() const { return Rational::Builder(0); } }; class HyperbolicTrigonometricFunction : public Expression { public: HyperbolicTrigonometricFunction(const HyperbolicTrigonometricFunctionNode * n) : Expression(n) {} Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); +private: + HyperbolicTrigonometricFunctionNode * node() const { return static_cast(Expression::node()); } }; } diff --git a/poincare/src/hyperbolic_trigonometric_function.cpp b/poincare/src/hyperbolic_trigonometric_function.cpp index c502760d8..adcb252ff 100644 --- a/poincare/src/hyperbolic_trigonometric_function.cpp +++ b/poincare/src/hyperbolic_trigonometric_function.cpp @@ -17,18 +17,23 @@ Expression HyperbolicTrigonometricFunction::shallowReduce(ExpressionNode::Reduct } Expression thisExpression = *this; - - // Step 1. Map on matrix child if possible Expression c = childAtIndex(0); - if (childAtIndex(0).type() == ExpressionNode::Type::Matrix) { + + // Step 0. Map on matrix child if possible + if (c.type() == ExpressionNode::Type::Matrix) { return mapOnMatrixFirstChild(reductionContext); } - // Step 2. TODO EMILIE ?? Try finding an easy standard calculation reduction + // Step 1. Notable values + if (node()->isNotableValue(c)) { + Expression result = node()->imageOfNotableValue(); + replaceWithInPlace(result); + return result; + } - // Step 3. Look for an expression of type "cosh(acosh(z))", return z + // Step 2. Look for an expression of type "cosh(acosh(z))", return z ExpressionNode::Type t = type(); - ExpressionNode::Type childT = childAtIndex(0).type(); + ExpressionNode::Type childT = c.type(); { Expression result; if (t == ExpressionNode::Type::HyperbolicCosine) { @@ -90,7 +95,7 @@ Expression HyperbolicTrigonometricFunction::shallowReduce(ExpressionNode::Reduct } } - // Step 4. Look for an expression of type "cosh(-x)", return "+/-cosh(x)" + // Step 3. Look for an expression of type "cosh(-x)", return "+/-cosh(x)" if (t != ExpressionNode::Type::HyperbolicArcCosine) { Expression positiveArg = childAtIndex(0).makePositiveAnyNegativeNumeralFactor(reductionContext); if (!positiveArg.isUninitialized()) { diff --git a/poincare/test/simplification.cpp b/poincare/test/simplification.cpp index 6b73a0c3d..d9e22fc9d 100644 --- a/poincare/test/simplification.cpp +++ b/poincare/test/simplification.cpp @@ -597,6 +597,15 @@ QUIZ_CASE(poincare_simplication_trigonometry_functions) { assert_parsed_expression_simplify_to("tan(asin(-x))", "-x/√(-x^2+1)", User, Degree); } +QUIZ_CASE(poincare_simplication_hyperbolic_trigonometry_functions) { + assert_parsed_expression_simplify_to("sinh(0)", "0"); + assert_parsed_expression_simplify_to("cosh(0)", "1"); + assert_parsed_expression_simplify_to("tanh(0)", "0"); + assert_parsed_expression_simplify_to("asinh(0)", "0"); + assert_parsed_expression_simplify_to("acosh(1)", "0"); + assert_parsed_expression_simplify_to("atanh(0)", "0"); +} + QUIZ_CASE(poincare_simplication_matrix) { // Addition Matrix assert_parsed_expression_simplify_to("1+[[1,2,3][4,5,6]]", Undefined::Name()); @@ -699,11 +708,11 @@ QUIZ_CASE(poincare_simplification_functions_of_matrices) { assert_parsed_expression_simplify_to("gcd(1,[[0,180]])", Undefined::Name()); assert_parsed_expression_simplify_to("gcd([[0,180]],[[1]])", Undefined::Name()); assert_parsed_expression_simplify_to("acosh([[0,π]])", "[[acosh(0),acosh(π)]]"); - assert_parsed_expression_simplify_to("asinh([[0,π]])", "[[asinh(0),asinh(π)]]"); - assert_parsed_expression_simplify_to("atanh([[0,π]])", "[[atanh(0),atanh(π)]]"); - assert_parsed_expression_simplify_to("cosh([[0,π]])", "[[cosh(0),cosh(π)]]"); - assert_parsed_expression_simplify_to("sinh([[0,π]])", "[[sinh(0),sinh(π)]]"); - assert_parsed_expression_simplify_to("tanh([[0,π]])", "[[tanh(0),tanh(π)]]"); + assert_parsed_expression_simplify_to("asinh([[0,π]])", "[[0,asinh(π)]]"); + assert_parsed_expression_simplify_to("atanh([[0,π]])", "[[0,atanh(π)]]"); + assert_parsed_expression_simplify_to("cosh([[0,π]])", "[[1,cosh(π)]]"); + assert_parsed_expression_simplify_to("sinh([[0,π]])", "[[0,sinh(π)]]"); + assert_parsed_expression_simplify_to("tanh([[0,π]])", "[[0,tanh(π)]]"); assert_parsed_expression_simplify_to("im([[1/√(2),1/2][1,-1]])", "[[0,0][0,0]]"); assert_parsed_expression_simplify_to("im([[1,1+𝐢]])", "[[0,1]]"); assert_parsed_expression_simplify_to("int([[0,180]],x,1,2)", Undefined::Name());