diff --git a/poincare/include/poincare/logarithm.h b/poincare/include/poincare/logarithm.h index 75d23f0f7..c43e1dbea 100644 --- a/poincare/include/poincare/logarithm.h +++ b/poincare/include/poincare/logarithm.h @@ -32,6 +32,9 @@ public: Expression shallowBeautify(ReductionContext reductionContext) override; LayoutShape leftLayoutShape() const override { return LayoutShape::MoreLetters; }; LayoutShape rightLayoutShape() const override { return LayoutShape::BoundaryPunctuation; } + // Derivation + bool didDerivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) override; + Expression unaryFunctionDifferential() override; // Evaluation template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { /* log has a branch cut on ]-inf, 0]: it is then multivalued on this cut. We @@ -53,6 +56,8 @@ public: Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); Expression shallowBeautify(); + bool didDerivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue); + Expression unaryFunctionDifferential(); private: void deepReduceChildren(ExpressionNode::ReductionContext reductionContext); diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 803dfc18d..4bb930f10 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -68,6 +69,31 @@ Expression LogarithmNode<2>::shallowReduce(ExpressionNode::ReductionContext redu return Logarithm(this).shallowReduce(reductionContext); } +template <> +bool LogarithmNode<2>::didDerivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) { + return Logarithm(this).didDerivate(reductionContext, symbol, symbolValue); +} + +template <> +Expression LogarithmNode<2>::unaryFunctionDifferential() { + return Logarithm(this).unaryFunctionDifferential(); +} + +/* Those two methods will not be called, as CommonLogarithm disappears in + * reduction */ +template <> +bool LogarithmNode<1>::didDerivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) { + assert(false); + return false; +} + +template <> +Expression LogarithmNode<1>::unaryFunctionDifferential() { + assert(false); + return Expression(); +} +/**/ + template<> Expression LogarithmNode<1>::shallowBeautify(ReductionContext reductionContext) { return CommonLogarithm(this); @@ -329,6 +355,24 @@ Integer Logarithm::simplifyLogarithmIntegerBaseInteger(Integer i, Integer & base return i; } +bool Logarithm::didDerivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue) { + /* We do nothing if the base is a function of the derivation variable, as the + * log is then not an unary function anymore. + * TODO : Check whether we want to deal with the case log(..., f(x)). */ + if (childAtIndex(1).polynomialDegree(reductionContext.context(), symbol.convert().name()) != 0) { + return false; + } + Derivative::DerivateUnaryFunction(*this, symbol, symbolValue); + return true; +} + +Expression Logarithm::unaryFunctionDifferential() { + /* log(x, b)` = (ln(x)/ln(b))` + * = 1 / (x * ln(b)) + */ + return Power::Builder(Multiplication::Builder(childAtIndex(0).clone(), NaperianLogarithm::Builder(childAtIndex(1).clone())), Rational::Builder(-1)); +} + Expression Logarithm::splitLogarithmInteger(Integer i, bool isDenominator, ExpressionNode::ReductionContext reductionContext) { assert(!i.isZero()); assert(!i.isNegative()); diff --git a/poincare/test/derivative.cpp b/poincare/test/derivative.cpp index 66ea36cb2..57d4307a9 100644 --- a/poincare/test/derivative.cpp +++ b/poincare/test/derivative.cpp @@ -46,4 +46,9 @@ QUIZ_CASE(poicare_differential_unary_functions) { assert_parses_and_reduces_as("diff(sin(2x)+sin(3x),x,π/6)","1"); assert_parses_and_reduces_as("diff(cos(x),x,π/2)","-1"); + + assert_parses_and_reduces_as("diff(ln(x),x,x)","1/x"); + assert_parses_and_reduces_as("diff(log(x,10),x,x)","1/(x*ln(10))"); + + assert_parses_and_reduces_as("diff(ln(cos(x)),x,a)","-tan(a)"); } \ No newline at end of file