[AbsoluteValue] Adding formal derivate to absolute value

This will prevent diff(|x|, x, 0) to be evaluated to 0 instead of undef
This fixes issue #1393
Change-Id: I73f40aa29f04c373cd3e9edbbd4fbe7be6d7a988
This commit is contained in:
Arthur Camouseigt
2020-07-31 17:41:12 +02:00
committed by Émilie Feral
parent f562886a7e
commit 58b69c2779
3 changed files with 27 additions and 0 deletions

View File

@@ -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<AbsoluteValue>);
Expression shallowReduce(ExpressionNode::ReductionContext reductionContext);
bool derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue);
};
}

View File

@@ -5,6 +5,8 @@
#include <poincare/absolute_value_layout.h>
#include <poincare/complex_cartesian.h>
#include <poincare/multiplication.h>
#include <poincare/power.h>
#include <poincare/derivative.h>
#include <assert.h>
#include <cmath>
@@ -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<Symbol>(),
symbolValue.clone()
),0,0);
result.addChildAtIndexInPlace(f.clone(),1,1);
replaceWithInPlace(result);
result.addChildAtIndexInPlace(Power::Builder(*this,Rational::Builder(-1)),2,2);
return true;
}
}

View File

@@ -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();