[poicare/logarithm] Implemented didDerivate and unaryFunctionDifferential for Logarithm

Derivation now computes as expected on logarithms, as long as their base is not a function of the derivation variable.

Change-Id: Ia56da1c1151c0ddf3887be84ddb4bd02664c5188
This commit is contained in:
Gabriel Ozouf
2020-05-20 12:15:13 +02:00
committed by Émilie Feral
parent 407d4bce6e
commit eab8167a56
3 changed files with 54 additions and 0 deletions

View File

@@ -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<typename U> static Complex<U> computeOnComplex(const std::complex<U> 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);

View File

@@ -3,6 +3,7 @@
#include <poincare/approximation_helper.h>
#include <poincare/arithmetic.h>
#include <poincare/constant.h>
#include <poincare/derivative.h>
#include <poincare/division.h>
#include <poincare/infinity.h>
#include <poincare/layout_helper.h>
@@ -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<Symbol>().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());

View File

@@ -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)");
}