mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[poincare] Implemented didDerivate method for Power
Derivation now propagates to powers as expected, whether the base, the exponent, or both are functions of the variable. This also makes division derive as intended. Change-Id: I51cbd5f7ec9f6aaa1df068625bbda1437941fa08
This commit is contained in:
committed by
Émilie Feral
parent
6f378ef3ef
commit
648cdbaa29
@@ -55,6 +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;
|
||||
// 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);
|
||||
@@ -79,6 +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);
|
||||
|
||||
private:
|
||||
constexpr static int k_maxExactPowerMatrix = 100;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <poincare/binomial_coefficient.h>
|
||||
#include <poincare/constant.h>
|
||||
#include <poincare/cosine.h>
|
||||
#include <poincare/derivative.h>
|
||||
#include <poincare/division.h>
|
||||
#include <poincare/float.h>
|
||||
#include <poincare/horizontal_layout.h>
|
||||
@@ -251,6 +252,10 @@ 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);
|
||||
}
|
||||
|
||||
// Evaluation
|
||||
template<typename T> MatrixComplex<T> PowerNode::computeOnComplexAndMatrix(const std::complex<T> c, const MatrixComplex<T> n, Preferences::ComplexFormat complexFormat) {
|
||||
return MatrixComplex<T>::Undefined();
|
||||
@@ -1015,6 +1020,47 @@ Expression Power::shallowBeautify(ExpressionNode::ReductionContext reductionCont
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Power::didDerivate(ExpressionNode::ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
|
||||
/* Generalized power derivation formula
|
||||
* (f^g)` = (e^(g * ln(f)))`
|
||||
* = (g * ln(f))` * f^g
|
||||
* = (g`ln(f) + gf`/f) * f^g
|
||||
* = g`ln(f)f^g + gf`f^(g-1)
|
||||
*
|
||||
* Valid whenever f,g are derivable and f > 0 */
|
||||
|
||||
/* We might want to be able to derivate f^n when f <= 0 and n is a positive
|
||||
* integer */
|
||||
|
||||
Expression base = childAtIndex(0);
|
||||
Expression exponent = childAtIndex(1);
|
||||
Multiplication derivedFromBase = Multiplication::Builder();
|
||||
Multiplication derivedFromExponent = Multiplication::Builder();
|
||||
|
||||
derivedFromExponent.addChildAtIndexInPlace(NaperianLogarithm::Builder(base.clone()), 0, 0);
|
||||
derivedFromExponent.addChildAtIndexInPlace(clone(), 1, 1);
|
||||
derivedFromExponent.addChildAtIndexInPlace(Derivative::Builder(
|
||||
exponent.clone(),
|
||||
symbol.clone().convert<Symbol>(),
|
||||
symbolValue.clone()
|
||||
), 2, 2);
|
||||
|
||||
derivedFromBase.addChildAtIndexInPlace(exponent.clone() , 0, 0);
|
||||
derivedFromBase.addChildAtIndexInPlace(Power::Builder(
|
||||
base.clone(),
|
||||
Subtraction::Builder(exponent.clone(), Rational::Builder(1))
|
||||
), 1, 1);
|
||||
derivedFromBase.addChildAtIndexInPlace(Derivative::Builder(
|
||||
base.clone(),
|
||||
symbol.clone().convert<Symbol>(),
|
||||
symbolValue.clone()
|
||||
), 2, 2);
|
||||
|
||||
Addition result = Addition::Builder(derivedFromBase, derivedFromExponent);
|
||||
replaceWithInPlace(result);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Private
|
||||
|
||||
// Simplification
|
||||
|
||||
@@ -7,12 +7,6 @@
|
||||
|
||||
using namespace Poincare;
|
||||
|
||||
void assert_differentiates_as(Expression expression, Expression derivative, const char * information) {
|
||||
Shared::GlobalContext globalContext;
|
||||
Expression expressionReduced = expression.reduce(ExpressionNode::ReductionContext(&globalContext, Cartesian, Radian, User));
|
||||
quiz_assert_print_if_failure(expressionReduced.isIdenticalTo(derivative), information);
|
||||
}
|
||||
|
||||
void assert_parses_and_reduces_as(const char * expression, const char * derivative) {
|
||||
Shared::GlobalContext globalContext;
|
||||
Expression e = parse_expression(expression, &globalContext, false);
|
||||
@@ -32,8 +26,15 @@ QUIZ_CASE(poincare_differential_addition) {
|
||||
|
||||
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)", "3");
|
||||
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");
|
||||
}
|
||||
Reference in New Issue
Block a user