mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
[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:
committed by
Émilie Feral
parent
eab8167a56
commit
a9c94236c2
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>);
|
||||
};
|
||||
|
||||
|
||||
@@ -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>);
|
||||
};
|
||||
|
||||
|
||||
@@ -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>);
|
||||
};
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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()); }
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)). */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
Reference in New Issue
Block a user