[poincare] Implemented further derivation methods and updated tests.

Derivation now works on tangents and the three hyperbolic functions.

Change-Id: I62049e79c661c3c4a031be0a93c403fb936d611b
This commit is contained in:
Gabriel Ozouf
2020-05-20 16:47:22 +02:00
committed by Émilie Feral
parent eab8167a56
commit a9c94236c2
31 changed files with 211 additions and 80 deletions

View File

@@ -58,7 +58,7 @@ private:
Expression shallowBeautify(ReductionContext reductionContext) override;
// Derivation
bool didDerivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) override;
bool derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) override;
/* Evaluation */
template<typename T> static MatrixComplex<T> computeOnMatrixAndComplex(const MatrixComplex<T> m, const std::complex<T> c, Preferences::ComplexFormat complexFormat) {
@@ -84,7 +84,7 @@ public:
// Expression
Expression shallowReduce(ExpressionNode::ReductionContext reductionContext);
Expression shallowBeautify(ExpressionNode::ReductionContext reductionContext);
bool didDerivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue);
bool derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue);
int getPolynomialCoefficients(Context * context, const char * symbolName, Expression coefficients[], ExpressionNode::SymbolicComputation symbolicComputation) const;
void sortChildrenInPlace(NAryExpressionNode::ExpressionOrder order, Context * context, bool canBeInterrupted) {
NAryExpression::sortChildrenInPlace(order, context, true, canBeInterrupted);

View File

@@ -35,7 +35,7 @@ private:
LayoutShape rightLayoutShape() const override { return LayoutShape::BoundaryPunctuation; }
// Derivation
bool didDerivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) override;
bool derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) override;
Expression unaryFunctionDifferential() override;
// Evaluation
@@ -56,7 +56,7 @@ public:
Expression shallowReduce(ExpressionNode::ReductionContext reductionContext);
bool didDerivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue);
bool derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue);
Expression unaryFunctionDifferential();
};

View File

@@ -384,7 +384,7 @@ protected:
/* This method is used for the reduction of Derivative expressions.
* It returns whether the instance is differentiable, and differentiates it if
* able. */
bool didDerivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue) { return node()->didDerivate(reductionContext, symbol, symbolValue); }
bool derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue) { return node()->derivate(reductionContext, symbol, symbolValue); }
Expression unaryFunctionDifferential() { return node()->unaryFunctionDifferential(); }
private:

View File

@@ -223,7 +223,7 @@ public:
/*!*/ virtual void deepReduceChildren(ReductionContext reductionContext);
/*!*/ virtual Expression shallowReduce(ReductionContext reductionContext);
/*!*/ virtual Expression shallowBeautify(ReductionContext reductionContext);
/*!*/ virtual bool didDerivate(ReductionContext, Expression symbol, Expression symbolValue);
/*!*/ virtual bool derivate(ReductionContext, Expression symbol, Expression symbolValue);
virtual Expression unaryFunctionDifferential();
/* Return a clone of the denominator part of the expression */
/*!*/ virtual Expression denominator(ExpressionNode::ReductionContext reductionContext) const;

View File

@@ -25,6 +25,9 @@ private:
// Layout
Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
// Derivation
bool derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) override;
Expression unaryFunctionDifferential() override;
//Evaluation
template<typename T> static Complex<T> computeOnComplex(const std::complex<T> c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit);
Evaluation<float> approximate(SinglePrecision p, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override {
@@ -40,6 +43,9 @@ public:
HyperbolicCosine(const HyperbolicCosineNode * n) : HyperbolicTrigonometricFunction(n) {}
static HyperbolicCosine Builder(Expression child) { return TreeHandle::FixedArityBuilder<HyperbolicCosine, HyperbolicCosineNode>({child}); }
bool derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue);
Expression unaryFunctionDifferential();
static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("cosh", 1, &UntypedBuilderOneChild<HyperbolicCosine>);
};

View File

@@ -23,6 +23,9 @@ private:
// Layout
Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
// Derivation
bool derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) override;
Expression unaryFunctionDifferential() override;
//Evaluation
template<typename T> static Complex<T> computeOnComplex(const std::complex<T> c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit);
Evaluation<float> approximate(SinglePrecision p, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override {
@@ -38,6 +41,9 @@ public:
HyperbolicSine(const HyperbolicSineNode * n) : HyperbolicTrigonometricFunction(n) {}
static HyperbolicSine Builder(Expression child) { return TreeHandle::FixedArityBuilder<HyperbolicSine, HyperbolicSineNode>({child}); }
bool derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue);
Expression unaryFunctionDifferential();
static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("sinh", 1, &UntypedBuilderOneChild<HyperbolicSine>);
};

View File

@@ -23,6 +23,9 @@ private:
// Layout
Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
// Derivation
bool derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) override;
Expression unaryFunctionDifferential() override;
//Evaluation
template<typename T> static Complex<T> computeOnComplex(const std::complex<T> c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit);
Evaluation<float> approximate(SinglePrecision p, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override {
@@ -38,6 +41,9 @@ public:
HyperbolicTangent(const HyperbolicTangentNode * n) : HyperbolicTrigonometricFunction(n) {}
static HyperbolicTangent Builder(Expression child) { return TreeHandle::FixedArityBuilder<HyperbolicTangent, HyperbolicTangentNode>({child}); }
bool derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue);
Expression unaryFunctionDifferential();
static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("tanh", 1, &UntypedBuilderOneChild<HyperbolicTangent>);
};

View File

@@ -33,7 +33,7 @@ public:
LayoutShape leftLayoutShape() const override { return LayoutShape::MoreLetters; };
LayoutShape rightLayoutShape() const override { return LayoutShape::BoundaryPunctuation; }
// Derivation
bool didDerivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) override;
bool derivate(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) {
@@ -56,7 +56,7 @@ public:
Expression shallowReduce(ExpressionNode::ReductionContext reductionContext);
Expression shallowBeautify();
bool didDerivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue);
bool derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue);
Expression unaryFunctionDifferential();
private:

View File

@@ -50,7 +50,7 @@ private:
Expression shallowBeautify(ReductionContext reductionContext) override;
Expression denominator(ExpressionNode::ReductionContext reductionContext) const override;
// Derivation
bool didDerivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) override;
bool derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) override;
// Approximation
template<typename T> static MatrixComplex<T> computeOnMatrixAndComplex(const MatrixComplex<T> m, const std::complex<T> c, Preferences::ComplexFormat complexFormat) {
@@ -91,7 +91,7 @@ public:
NAryExpression::sortChildrenInPlace(order, context, false, canBeInterrupted);
}
// Derivation
bool didDerivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue);
bool derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue);
private:
// Unit
Expression removeUnit(Expression * unit);

View File

@@ -26,7 +26,7 @@ public:
double doubleApproximation() const;
bool didDerivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) override;
bool derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) override;
};
@@ -56,7 +56,7 @@ public:
return Expression::setSign(s, ExpressionNode::ReductionContext(nullptr, Preferences::ComplexFormat::Real, Preferences::AngleUnit::Degree, ExpressionNode::ReductionTarget::User)).convert<Number>();
}
bool didDerivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue);
bool derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue);
protected:
Number() : Expression() {}
NumberNode * node() const { return static_cast<NumberNode *>(Expression::node()); }

View File

@@ -55,7 +55,7 @@ private:
int simplificationOrderGreaterType(const ExpressionNode * e, bool ascending, bool canBeInterrupted, bool ignoreParentheses) const override;
int simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted, bool ignoreParentheses) const override;
Expression denominator(ReductionContext reductionContext) const override;
bool didDerivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) override;
bool derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) override;
// Evaluation
template<typename T> static MatrixComplex<T> computeOnComplexAndMatrix(const std::complex<T> c, const MatrixComplex<T> n, Preferences::ComplexFormat complexFormat);
template<typename T> static MatrixComplex<T> computeOnMatrixAndComplex(const MatrixComplex<T> m, const std::complex<T> d, Preferences::ComplexFormat complexFormat);
@@ -80,7 +80,7 @@ public:
int getPolynomialCoefficients(Context * context, const char * symbolName, Expression coefficients[]) const;
Expression shallowReduce(ExpressionNode::ReductionContext reductionContext);
Expression shallowBeautify(ExpressionNode::ReductionContext reductionContext);
bool didDerivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue);
bool derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue);
private:
constexpr static int k_maxExactPowerMatrix = 100;

View File

@@ -36,7 +36,7 @@ private:
LayoutShape rightLayoutShape() const override { return LayoutShape::BoundaryPunctuation; }
// Derivation
bool didDerivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) override;
bool derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) override;
Expression unaryFunctionDifferential() override;
// Evaluation
@@ -57,7 +57,7 @@ public:
Expression shallowReduce(ExpressionNode::ReductionContext reductionContext);
bool didDerivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue);
bool derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue);
Expression unaryFunctionDifferential();
};

View File

@@ -38,7 +38,7 @@ public:
LayoutShape leftLayoutShape() const override;
/* Derivation */
bool didDerivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) override;
bool derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) override;
/* Approximation */
Evaluation<float> approximate(SinglePrecision p, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, complexFormat, angleUnit); }
@@ -72,7 +72,7 @@ public:
// Expression
Expression shallowReduce(ExpressionNode::ReductionContext reductionContext);
bool didDerivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue);
bool derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue);
Expression replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression);
int getPolynomialCoefficients(Context * context, const char * symbolName, Expression coefficients[], ExpressionNode::SymbolicComputation symbolicComputation) const;
Expression deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly, int parameteredAncestorsCount);

View File

@@ -32,6 +32,10 @@ private:
LayoutShape leftLayoutShape() const override { return LayoutShape::MoreLetters; };
LayoutShape rightLayoutShape() const override { return LayoutShape::BoundaryPunctuation; }
// Derivation
bool derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) override;
Expression unaryFunctionDifferential() override;
// Evaluation
template<typename T> static Complex<T> computeOnComplex(const std::complex<T> c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Radian);
Evaluation<float> approximate(SinglePrecision p, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override {
@@ -50,6 +54,9 @@ public:
static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("tan", 1, &UntypedBuilderOneChild<Tangent>);
Expression shallowReduce(ExpressionNode::ReductionContext reductionContext);
bool derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue);
Expression unaryFunctionDifferential();
};
}

View File

@@ -30,8 +30,8 @@ public:
}
/* Derivation
* Overrides NumberNode's didDerivate to revert to a non-derivable state */
bool didDerivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) override { return false; }
* Overrides NumberNode's derivate to revert to a non-derivable state */
bool derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) override { return false; }
// Layout
Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;

View File

@@ -28,8 +28,8 @@ public:
}
/* Derivation
* Overrides NumberNode's didDerivate to revert to a non-derivable state */
bool didDerivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) override { return false; }
* Overrides NumberNode's derivate to revert to a non-derivable state */
bool derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) override { return false; }
// Layout
Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;

View File

@@ -51,8 +51,8 @@ Expression AdditionNode::shallowBeautify(ReductionContext reductionContext) {
}
// Derivation
bool AdditionNode::didDerivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
return Addition(this).didDerivate(reductionContext, symbol, symbolValue);
bool AdditionNode::derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
return Addition(this).derivate(reductionContext, symbol, symbolValue);
}
// Addition
@@ -328,7 +328,7 @@ Expression Addition::shallowReduce(ExpressionNode::ReductionContext reductionCon
return result;
}
bool Addition::didDerivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
bool Addition::derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
for (int i = 0; i < numberOfChildren(); i++) {
replaceChildAtIndexInPlace(i, Derivative::Builder(childAtIndex(i), symbol.clone().convert<Symbol>(), symbolValue.clone()));
}

View File

@@ -38,8 +38,8 @@ Expression CosineNode::shallowReduce(ReductionContext reductionContext) {
return Cosine(this).shallowReduce(reductionContext);
}
bool CosineNode::didDerivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
return Cosine(this).didDerivate(reductionContext, symbol, symbolValue);
bool CosineNode::derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
return Cosine(this).derivate(reductionContext, symbol, symbolValue);
}
Expression CosineNode::unaryFunctionDifferential() {
@@ -57,7 +57,8 @@ Expression Cosine::shallowReduce(ExpressionNode::ReductionContext reductionConte
return Trigonometry::shallowReduceDirectFunction(*this, reductionContext);
}
bool Cosine::didDerivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
bool Cosine::derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
Derivative::DerivateUnaryFunction(*this, symbol, symbolValue);
return true;
}

View File

@@ -170,14 +170,14 @@ Expression Derivative::shallowReduce(ExpressionNode::ReductionContext reductionC
Expression symbolValue = childAtIndex(2);
/* Since derivand is a child to the derivative node, it can be replaced in
* place without didDerivate having to return the derivative. */
if (!derivand.didDerivate(reductionContext, symbol, symbolValue)) {
* place without derivate having to return the derivative. */
if (!derivand.derivate(reductionContext, symbol, symbolValue)) {
return *this;
}
/* Updates the value of derivand, because didDerivate may call
/* Updates the value of derivand, because derivate may call
* replaceWithInplace on it */
derivand = childAtIndex(0);
/* Deep reduces the child, because didDerivate may not preserve its reduced
/* Deep reduces the child, because derivate may not preserve its reduced
* status. */
derivand = derivand.replaceSymbolWithExpression(symbol, symbolValue);

View File

@@ -127,7 +127,7 @@ Expression ExpressionNode::shallowBeautify(ReductionContext reductionContext) {
return Expression(this).defaultShallowBeautify();
}
bool ExpressionNode::didDerivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
bool ExpressionNode::derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
return Expression(this).defaultDidDerivate();
}

View File

@@ -1,4 +1,6 @@
#include <poincare/hyperbolic_cosine.h>
#include <poincare/derivative.h>
#include <poincare/hyperbolic_sine.h>
#include <poincare/layout_helper.h>
#include <poincare/serialization_helper.h>
@@ -19,6 +21,24 @@ Complex<T> HyperbolicCosineNode::computeOnComplex(const std::complex<T> c, Prefe
return Complex<T>::Builder(ApproximationHelper::NeglectRealOrImaginaryPartIfNeglectable(std::cosh(c), c));
}
bool HyperbolicCosineNode::derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
return HyperbolicCosine(this).derivate(reductionContext, symbol, symbolValue);
}
Expression HyperbolicCosineNode::unaryFunctionDifferential() {
return HyperbolicCosine(this).unaryFunctionDifferential();
}
bool HyperbolicCosine::derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
Derivative::DerivateUnaryFunction(*this, symbol, symbolValue);
return true;
}
Expression HyperbolicCosine::unaryFunctionDifferential() {
return HyperbolicSine::Builder(childAtIndex(0).clone());
}
template Complex<float> Poincare::HyperbolicCosineNode::computeOnComplex<float>(std::complex<float>, Preferences::ComplexFormat, Preferences::AngleUnit);
template Complex<double> Poincare::HyperbolicCosineNode::computeOnComplex<double>(std::complex<double>, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit);

View File

@@ -1,4 +1,6 @@
#include <poincare/hyperbolic_sine.h>
#include <poincare/derivative.h>
#include <poincare/hyperbolic_cosine.h>
#include <poincare/layout_helper.h>
#include <poincare/serialization_helper.h>
@@ -19,6 +21,23 @@ Complex<T> HyperbolicSineNode::computeOnComplex(const std::complex<T> c, Prefere
return Complex<T>::Builder(ApproximationHelper::NeglectRealOrImaginaryPartIfNeglectable(std::sinh(c), c));
}
bool HyperbolicSineNode::derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
return HyperbolicSine(this).derivate(reductionContext, symbol, symbolValue);
}
Expression HyperbolicSineNode::unaryFunctionDifferential() {
return HyperbolicSine(this).unaryFunctionDifferential();
}
bool HyperbolicSine::derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
Derivative::DerivateUnaryFunction(*this, symbol, symbolValue);
return true;
}
Expression HyperbolicSine::unaryFunctionDifferential() {
return HyperbolicCosine::Builder(childAtIndex(0).clone());
}
template Complex<float> Poincare::HyperbolicSineNode::computeOnComplex<float>(std::complex<float>, Preferences::ComplexFormat, Preferences::AngleUnit);
template Complex<double> Poincare::HyperbolicSineNode::computeOnComplex<double>(std::complex<double>, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit);

View File

@@ -1,5 +1,8 @@
#include <poincare/hyperbolic_tangent.h>
#include <poincare/derivative.h>
#include <poincare/hyperbolic_cosine.h>
#include <poincare/layout_helper.h>
#include <poincare/power.h>
#include <poincare/serialization_helper.h>
namespace Poincare {
@@ -19,6 +22,23 @@ Complex<T> HyperbolicTangentNode::computeOnComplex(const std::complex<T> c, Pref
return Complex<T>::Builder(ApproximationHelper::NeglectRealOrImaginaryPartIfNeglectable(std::tanh(c), c));
}
bool HyperbolicTangentNode::derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
return HyperbolicTangent(this).derivate(reductionContext, symbol, symbolValue);
}
Expression HyperbolicTangentNode::unaryFunctionDifferential() {
return HyperbolicTangent(this).unaryFunctionDifferential();
}
bool HyperbolicTangent::derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
Derivative::DerivateUnaryFunction(*this, symbol, symbolValue);
return true;
}
Expression HyperbolicTangent::unaryFunctionDifferential() {
return Power::Builder(HyperbolicCosine::Builder(childAtIndex(0).clone()), Rational::Builder(-2));
}
template Complex<float> Poincare::HyperbolicTangentNode::computeOnComplex<float>(std::complex<float>, Preferences::ComplexFormat, Preferences::AngleUnit);
template Complex<double> Poincare::HyperbolicTangentNode::computeOnComplex<double>(std::complex<double>, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit);

View File

@@ -70,8 +70,8 @@ Expression LogarithmNode<2>::shallowReduce(ExpressionNode::ReductionContext redu
}
template <>
bool LogarithmNode<2>::didDerivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
return Logarithm(this).didDerivate(reductionContext, symbol, symbolValue);
bool LogarithmNode<2>::derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
return Logarithm(this).derivate(reductionContext, symbol, symbolValue);
}
template <>
@@ -82,7 +82,7 @@ Expression LogarithmNode<2>::unaryFunctionDifferential() {
/* Those two methods will not be called, as CommonLogarithm disappears in
* reduction */
template <>
bool LogarithmNode<1>::didDerivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
bool LogarithmNode<1>::derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
assert(false);
return false;
}
@@ -355,7 +355,7 @@ Integer Logarithm::simplifyLogarithmIntegerBaseInteger(Integer i, Integer & base
return i;
}
bool Logarithm::didDerivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
bool Logarithm::derivate(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)). */

View File

@@ -219,8 +219,8 @@ Expression MultiplicationNode::denominator(ReductionContext reductionContext) co
return Multiplication(this).denominator(reductionContext);
}
bool MultiplicationNode::didDerivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
return Multiplication(this).didDerivate(reductionContext, symbol, symbolValue);
bool MultiplicationNode::derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
return Multiplication(this).derivate(reductionContext, symbol, symbolValue);
}
/* Multiplication */
@@ -495,7 +495,7 @@ Expression Multiplication::denominator(ExpressionNode::ReductionContext reductio
return denom;
}
bool Multiplication::didDerivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
bool Multiplication::derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
Addition resultingAddition = Addition::Builder();
int numberOfTerms = numberOfChildren();
assert (numberOfTerms > 0);

View File

@@ -41,8 +41,8 @@ double NumberNode::doubleApproximation() const {
}
}
bool NumberNode::didDerivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
return Number(this).didDerivate(reductionContext, symbol, symbolValue);
bool NumberNode::derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
return Number(this).derivate(reductionContext, symbol, symbolValue);
}
Number Number::ParseNumber(const char * integralPart, size_t integralLength, const char * decimalPart, size_t decimalLenght, bool exponentIsNegative, const char * exponentPart, size_t exponentLength) {
@@ -146,7 +146,7 @@ int Number::NaturalOrder(const Number & i, const Number & j) {
}
}
bool Number::didDerivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
bool Number::derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
replaceWithInPlace(Rational::Builder(0));
return true;
}

View File

@@ -252,8 +252,8 @@ Expression PowerNode::denominator(ReductionContext reductionContext) const {
return Power(this).denominator(reductionContext);
}
bool PowerNode::didDerivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
return Power(this).didDerivate(reductionContext, symbol, symbolValue);
bool PowerNode::derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
return Power(this).derivate(reductionContext, symbol, symbolValue);
}
// Evaluation
@@ -1020,7 +1020,7 @@ Expression Power::shallowBeautify(ExpressionNode::ReductionContext reductionCont
return *this;
}
bool Power::didDerivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
bool Power::derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
/* Generalized power derivation formula
* (f^g)` = (e^(g * ln(f)))`
* = (g * ln(f))` * f^g

View File

@@ -36,8 +36,8 @@ Expression SineNode::shallowReduce(ReductionContext reductionContext) {
return Sine(this).shallowReduce(reductionContext);
}
bool SineNode::didDerivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
return Sine(this).didDerivate(reductionContext, symbol, symbolValue);
bool SineNode::derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
return Sine(this).derivate(reductionContext, symbol, symbolValue);
}
Expression SineNode::unaryFunctionDifferential() {
@@ -55,7 +55,7 @@ Expression Sine::shallowReduce(ExpressionNode::ReductionContext reductionContext
return Trigonometry::shallowReduceDirectFunction(*this, reductionContext);
}
bool Sine::didDerivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
bool Sine::derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
Derivative::DerivateUnaryFunction(*this, symbol, symbolValue);
return true;
}

View File

@@ -107,8 +107,8 @@ ExpressionNode::LayoutShape SymbolNode::leftLayoutShape() const {
return LayoutShape::MoreLetters;
}
bool SymbolNode::didDerivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
return Symbol(this).didDerivate(reductionContext, symbol, symbolValue);
bool SymbolNode::derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
return Symbol(this).derivate(reductionContext, symbol, symbolValue);
}
template<typename T>
@@ -196,7 +196,7 @@ Expression Symbol::shallowReduce(ExpressionNode::ReductionContext reductionConte
return result.deepReduce(reductionContext);
}
bool Symbol::didDerivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
bool Symbol::derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
replaceWithInPlace(Rational::Builder(strcmp(name(), symbol.convert<Symbol>().name()) == 0));
return true;
}

View File

@@ -1,7 +1,10 @@
#include <poincare/tangent.h>
#include <poincare/cosine.h>
#include <poincare/derivative.h>
#include <poincare/division.h>
#include <poincare/layout_helper.h>
#include <poincare/power.h>
#include <poincare/rational.h>
#include <poincare/serialization_helper.h>
#include <poincare/sine.h>
@@ -37,6 +40,13 @@ Expression TangentNode::shallowReduce(ReductionContext reductionContext) {
return Tangent(this).shallowReduce(reductionContext);
}
bool TangentNode::derivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
return Tangent(this).derivate(reductionContext, symbol, symbolValue);
}
Expression TangentNode::unaryFunctionDifferential() {
return Tangent(this).unaryFunctionDifferential();
}
Expression Tangent::shallowReduce(ExpressionNode::ReductionContext reductionContext) {
{
@@ -60,4 +70,13 @@ Expression Tangent::shallowReduce(ExpressionNode::ReductionContext reductionCont
return newExpression;
}
bool Tangent::derivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
Derivative::DerivateUnaryFunction(*this, symbol, symbolValue);
return true;
}
Expression Tangent::unaryFunctionDifferential() {
return Power::Builder(Cosine::Builder(childAtIndex(0).clone()), Rational::Builder(-2));
}
}

View File

@@ -9,46 +9,73 @@ using namespace Poincare;
void assert_parses_and_reduces_as(const char * expression, const char * derivative) {
Shared::GlobalContext globalContext;
Expression d = parse_expression(derivative, &globalContext, false).reduce(ExpressionNode::ReductionContext(&globalContext, Cartesian, Radian, User));
Expression e = parse_expression(expression, &globalContext, false);
Expression eReduced = e.reduce(ExpressionNode::ReductionContext(&globalContext, Cartesian, Radian, User));
Expression d = parse_expression(derivative, &globalContext, false).reduce(ExpressionNode::ReductionContext(&globalContext, Cartesian, Radian, User));
quiz_assert_print_if_failure(eReduced.isIdenticalTo(d), expression);
}
QUIZ_CASE(poincare_differential_operations) {
QUIZ_CASE(poincare_derivative_literals) {
assert_parses_and_reduces_as("diff(1,x,1)", "0");
assert_parses_and_reduces_as("diff(x,x,1)", "1");
assert_parses_and_reduces_as("diff(1+2,x,1)", "0");
assert_parses_and_reduces_as("diff(1,x,y)", "0");
assert_parses_and_reduces_as("diff(1,x,x)", "0");
assert_parses_and_reduces_as("diff(a,x,1)", "0");
assert_parses_and_reduces_as("diff(diff(x^2,x,y),y,1)","2");
assert_parses_and_reduces_as("diff(a,x,y)", "0");
assert_parses_and_reduces_as("diff(a,x,x)", "0");
assert_parses_and_reduces_as("diff(1+x,x,1)", "1");
assert_parses_and_reduces_as("diff(undef,x,1)", "undef");
assert_parses_and_reduces_as("diff(x,x,1)", "1");
assert_parses_and_reduces_as("diff(x,x,y)", "1");
assert_parses_and_reduces_as("diff(x,x,x)", "1");
assert_parses_and_reduces_as("diff(x+x,x,4)", "2");
assert_parses_and_reduces_as("diff(2*x,x,1)", "2");
assert_parses_and_reduces_as("diff(-x,x,1)", "-1");
assert_parses_and_reduces_as("diff(3-x,x,1)", "-1");
assert_parses_and_reduces_as("diff(a*x,x,2)", "a");
assert_parses_and_reduces_as("diff(a*x+b,x,x)", "a");
assert_parses_and_reduces_as("diff(x*x,x,3)", "6");
assert_parses_and_reduces_as("diff(x^2,x,2)", "4");
assert_parses_and_reduces_as("diff(2^x,x,0)", "ln(2)");
assert_parses_and_reduces_as("diff(x^2,x,x)", "2*x");
assert_parses_and_reduces_as("diff(a*x^2+b*x+c,x,x)", "2*a*x+b");
assert_parses_and_reduces_as("diff(1/x,x,1)", "-1");
assert_parses_and_reduces_as("diff(undef,x,0)", "undef");
}
QUIZ_CASE(poicare_differential_unary_functions) {
assert_parses_and_reduces_as("diff(sin(x),x,π)","-1");
assert_parses_and_reduces_as("diff(sin(2y),y,π/12)","√(3)");
assert_parses_and_reduces_as("diff(sin(2x)+sin(3x),x,π/6)","1");
QUIZ_CASE(poincare_derivative_additions) {
assert_parses_and_reduces_as("diff(1+x,x,1)", "1");
assert_parses_and_reduces_as("diff(x+a,x,x)", "1");
assert_parses_and_reduces_as("diff(a+b,x,y)", "0");
}
assert_parses_and_reduces_as("diff(cos(x),x,π/2)","-1");
QUIZ_CASE(poincare_derivative_multiplications) {
assert_parses_and_reduces_as("diff(2x,x,1)", "2");
assert_parses_and_reduces_as("diff(x*a,x,y)", "a");
assert_parses_and_reduces_as("diff(a*x+b,x,x)", "a");
assert_parses_and_reduces_as("diff(a*b+c,x,1)", "0");
assert_parses_and_reduces_as("diff(-x,x,y)", "-1");
assert_parses_and_reduces_as("diff(2-5x,x,x)", "-5");
}
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))");
QUIZ_CASE(poincare_derivative_powers) {
assert_parses_and_reduces_as("diff(x*x,x,1)", "2");
assert_parses_and_reduces_as("diff(x^2,x,y)", "2y");
assert_parses_and_reduces_as("diff(x^3/3,x,x)", "x^2");
assert_parses_and_reduces_as("diff(1/x,x,1)", "-1");
assert_parses_and_reduces_as("diff(2^x,x,y)", "ln(2)*2^y");
assert_parses_and_reduces_as("diff(x^(-2),x,x)", "-2/(x^3)");
assert_parses_and_reduces_as("diff(a^b,x,1)", "0");
assert_parses_and_reduces_as("diff(x^a,x,y)", "a*y^(a-1)");
assert_parses_and_reduces_as("diff(a*x^2+b*x+c,x,x)", "2a*x+b");
assert_parses_and_reduces_as("diff((1+x)(2-x),x,1)", "-1");
assert_parses_and_reduces_as("diff(diff(x^3/6,x,y),y,z)", "z");
}
assert_parses_and_reduces_as("diff(ln(cos(x)),x,a)","-tan(a)");
QUIZ_CASE(poincare_derivative_functions) {
assert_parses_and_reduces_as("diff(sin(x),x,x)", "cos(x)");
assert_parses_and_reduces_as("diff(cos(x),x,x)", "-sin(x)");
assert_parses_and_reduces_as("diff(tan(x),x,0)", "1");
assert_parses_and_reduces_as("diff(sin(a)+cos(b)+tan(c),x,y)", "0");
assert_parses_and_reduces_as("diff(sin(cos(x)),x,y)", "-sin(y)*cos(cos(y))");
assert_parses_and_reduces_as("diff(ln(x),x,x)", "1/x");
assert_parses_and_reduces_as("diff(ln(a*x),x,x)", "1/x");
assert_parses_and_reduces_as("diff(log(x),x,x)", "(x*ln(10))^(-1)");
assert_parses_and_reduces_as("diff(ln(cos(x)),x,x)", "-tan(x)");
assert_parses_and_reduces_as("diff(diff(ln(x),x,1/tan(x)),x,x)", "1/(cos(x))^2");
assert_parses_and_reduces_as("diff(ln(a),x,1)", "0");
assert_parses_and_reduces_as("diff(sinh(x),x,x)", "cosh(x)");
assert_parses_and_reduces_as("diff(cosh(x),x,x)", "sinh(x)");
assert_parses_and_reduces_as("diff(tanh(x),x,0)", "1");
assert_parses_and_reduces_as("diff(ln(cosh(x)),x,0)", "0");
}