diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 57be4dd32..bdbfc37d5 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -41,6 +41,8 @@ public: // Simplification Expression shallowReduce(ReductionContext reductionContext) override; LayoutShape leftLayoutShape() const override { return LayoutShape::BoundaryPunctuation; } +private: + bool derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) override; }; class AbsoluteValue final : public Expression { @@ -52,6 +54,7 @@ public: static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("abs", 1, &UntypedBuilderOneChild); Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); + bool derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue); }; } diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 6945e1fc5..905f08d22 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include #include @@ -31,6 +33,10 @@ Expression AbsoluteValueNode::shallowReduce(ReductionContext reductionContext) { return AbsoluteValue(this).shallowReduce(reductionContext); } +bool AbsoluteValueNode::derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) { + return AbsoluteValue(this).derivate(reductionContext, symbol, symbolValue); +} + Expression AbsoluteValue::shallowReduce(ExpressionNode::ReductionContext reductionContext) { Expression e = Expression::defaultShallowReduce(); e = e.defaultHandleUnitsInChildren(); @@ -113,4 +119,18 @@ Expression AbsoluteValue::shallowReduce(ExpressionNode::ReductionContext reducti return *this; } +// Derivate of |f(x)| is f'(x)*sg(x) (and undef in 0) = f'(x)*(f(x)/|f(x)|) +bool AbsoluteValue::derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue) { + Expression f = childAtIndex(0); + Multiplication result = Multiplication::Builder(); + result.addChildAtIndexInPlace(Derivative::Builder(f.clone(), + symbol.clone().convert(), + symbolValue.clone() + ),0,0); + result.addChildAtIndexInPlace(f.clone(),1,1); + replaceWithInPlace(result); + result.addChildAtIndexInPlace(Power::Builder(*this,Rational::Builder(-1)),2,2); + return true; +} + } diff --git a/poincare/test/derivative.cpp b/poincare/test/derivative.cpp index f4da054b2..05d2a0a1a 100644 --- a/poincare/test/derivative.cpp +++ b/poincare/test/derivative.cpp @@ -159,6 +159,10 @@ QUIZ_CASE(poincare_derivative_functions) { assert_parses_and_reduces_as("diff(diff(ln(x),x,1/tan(x)),x,z)", "undef"); assert_parses_and_reduces_as("diff(sinh(x),x,z)", "undef"); assert_parses_and_reduces_as("diff(cosh(x),x,z)", "undef"); + + assert_parses_and_reduces_as("diff(abs(x),x,0)", "undef"); + assert_parses_and_reduces_as("diff(abs(x),x,1)", "1"); + assert_parses_and_reduces_as("diff(abs(-2x),x,1)", "2"); #endif emptyGlobalContext();