mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
[poincare] Added method didDerivate to Expression and ExpressionNode
This method is to be implemented by derivable expression subclasses, for use in Derivative::shallowReduce. It performs the calculation for the derivative, and returns whether calculations happened. Change-Id: I13cdb131e2044578392f5178a9f389314c1c4c8a
This commit is contained in:
committed by
Émilie Feral
parent
eed1648363
commit
051e608835
@@ -162,6 +162,7 @@ tests_src += $(addprefix poincare/test/,\
|
||||
arithmetic.cpp\
|
||||
context.cpp\
|
||||
erf_inv.cpp \
|
||||
derivative.cpp\
|
||||
expression.cpp\
|
||||
expression_order.cpp\
|
||||
expression_properties.cpp\
|
||||
|
||||
@@ -53,7 +53,7 @@ public:
|
||||
static Expression UntypedBuilder(Expression children);
|
||||
static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("diff", 3, &UntypedBuilder);
|
||||
|
||||
Expression shallowReduce(Context * context);
|
||||
Expression shallowReduce(ExpressionNode::ReductionContext context);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -380,6 +380,12 @@ protected:
|
||||
// WARNING: this must be called on reduced expressions
|
||||
Expression setSign(ExpressionNode::Sign s, ExpressionNode::ReductionContext reductionContext);
|
||||
|
||||
/* Derivation */
|
||||
/* 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); }
|
||||
|
||||
private:
|
||||
static constexpr int k_maxSymbolReplacementsCount = 10;
|
||||
static bool sSymbolReplacementsCountLock;
|
||||
@@ -407,6 +413,7 @@ private:
|
||||
Expression defaultHandleUnitsInChildren(); // Children must be reduced
|
||||
Expression shallowReduceUsingApproximation(ExpressionNode::ReductionContext reductionContext);
|
||||
Expression defaultShallowBeautify() { return *this; }
|
||||
bool defaultDidDerivate() { return false; }
|
||||
|
||||
/* Approximation */
|
||||
template<typename U> Evaluation<U> approximateToEvaluation(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const;
|
||||
|
||||
@@ -223,6 +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);
|
||||
/* Return a clone of the denominator part of the expression */
|
||||
/*!*/ virtual Expression denominator(ExpressionNode::ReductionContext reductionContext) const;
|
||||
/* LayoutShape is used to check if the multiplication sign can be omitted between two expressions. It depends on the "layout syle" of the on the right of the left expression */
|
||||
|
||||
@@ -36,7 +36,7 @@ int DerivativeNode::serialize(char * buffer, int bufferSize, Preferences::PrintF
|
||||
}
|
||||
|
||||
Expression DerivativeNode::shallowReduce(ReductionContext reductionContext) {
|
||||
return Derivative(this).shallowReduce(reductionContext.context());
|
||||
return Derivative(this).shallowReduce(reductionContext);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -151,7 +151,7 @@ T DerivativeNode::riddersApproximation(Context * context, Preferences::ComplexFo
|
||||
return ans;
|
||||
}
|
||||
|
||||
Expression Derivative::shallowReduce(Context * context) {
|
||||
Expression Derivative::shallowReduce(ExpressionNode::ReductionContext reductionContext) {
|
||||
{
|
||||
Expression e = Expression::defaultShallowReduce();
|
||||
e = e.defaultHandleUnitsInChildren();
|
||||
@@ -159,12 +159,30 @@ Expression Derivative::shallowReduce(Context * context) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
Context * context = reductionContext.context();
|
||||
assert(!childAtIndex(1).deepIsMatrix(context));
|
||||
if (childAtIndex(0).deepIsMatrix(context) || childAtIndex(2).deepIsMatrix(context)) {
|
||||
return replaceWithUndefinedInPlace();
|
||||
}
|
||||
// TODO: to be implemented diff(+) -> +diff() etc
|
||||
return *this;
|
||||
|
||||
Expression derivand = childAtIndex(0);
|
||||
Symbol symbol = childAtIndex(1).convert<Symbol>();
|
||||
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)) {
|
||||
return *this;
|
||||
}
|
||||
/* Updates the value of derivand, because didDerivate may call
|
||||
* replaceWithInplace on it */
|
||||
derivand = childAtIndex(0);
|
||||
/* Deep reduces the child, because didDerivate may not preserve its reduced
|
||||
* status. */
|
||||
derivand = derivand.deepReduce(reductionContext);
|
||||
replaceWithInPlace(derivand);
|
||||
return derivand;
|
||||
|
||||
}
|
||||
|
||||
Expression Derivative::UntypedBuilder(Expression children) {
|
||||
|
||||
@@ -127,6 +127,10 @@ Expression ExpressionNode::shallowBeautify(ReductionContext reductionContext) {
|
||||
return Expression(this).defaultShallowBeautify();
|
||||
}
|
||||
|
||||
bool ExpressionNode::didDerivate(ReductionContext reductionContext, Expression symbol, Expression symbolValue) {
|
||||
return Expression(this).defaultDidDerivate();
|
||||
}
|
||||
|
||||
bool ExpressionNode::isOfType(Type * types, int length) const {
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (type() == types[i]) {
|
||||
|
||||
18
poincare/test/derivative.cpp
Normal file
18
poincare/test/derivative.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#include <poincare/derivative.h>
|
||||
#include <poincare/init.h>
|
||||
#include <poincare/src/parsing/parser.h>
|
||||
#include <poincare_nodes.h>
|
||||
#include <apps/shared/global_context.h>
|
||||
#include "helper.h"
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
QUIZ_CASE(poincare_differential_addition) {
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user