mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[VariableBox] Added sequences to the variable box
It is now possible to call the value of a defined sequence anywhere. Change-Id: I1990e93c50f9add175b7ea274e07004ba63289e5
This commit is contained in:
committed by
Émilie Feral
parent
c006ed7b10
commit
3dca515441
@@ -98,6 +98,7 @@ class Expression : public TreeHandle {
|
||||
friend class SubtractionNode;
|
||||
friend class Sum;
|
||||
friend class SumAndProduct;
|
||||
friend class SumAndProductNode;
|
||||
friend class Symbol;
|
||||
friend class SymbolAbstractNode;
|
||||
friend class Tangent;
|
||||
|
||||
@@ -19,6 +19,7 @@ public:
|
||||
|
||||
Type type() const override { return Type::Sequence; }
|
||||
Expression replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression) override;
|
||||
int simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted, bool ignoreParentheses) const override;
|
||||
|
||||
private:
|
||||
char m_name[0];
|
||||
|
||||
@@ -66,6 +66,7 @@ class SymbolAbstract : public Expression {
|
||||
friend class Symbol;
|
||||
friend class SymbolNode;
|
||||
friend class SymbolAbstractNode;
|
||||
friend class SumAndProductNode;
|
||||
public:
|
||||
const char * name() const { return node()->name(); }
|
||||
bool hasSameNameAs(const SymbolAbstract & other) const;
|
||||
|
||||
@@ -416,13 +416,9 @@ void Parser::parseSequence(Expression & leftHandSide, const char name, Token::Ty
|
||||
Expression rank = parseUntil(rightDelimiter);
|
||||
if (m_status != Status::Progress) {
|
||||
} else if (!popTokenIfType(rightDelimiter)) {
|
||||
m_status = Status::Error; // Right delimiter missing.
|
||||
} else if (rank.type() == ExpressionNode::Type::BasedInteger
|
||||
|| rank.isIdenticalTo(Symbol::Builder('n'))
|
||||
|| rank.isIdenticalTo(Addition::Builder(Symbol::Builder('n'), BasedInteger::Builder("1")))) {
|
||||
leftHandSide = Sequence::Builder(&name, 1, rank);
|
||||
m_status = Status::Error; // Right delimiter missing
|
||||
} else {
|
||||
m_status = Status::Error; // Unexpected parameter.
|
||||
leftHandSide = Sequence::Builder(&name, 1, rank);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,28 +20,29 @@ Expression SequenceNode::replaceSymbolWithExpression(const SymbolAbstract & symb
|
||||
return Sequence(this).replaceSymbolWithExpression(symbol, expression);
|
||||
}
|
||||
|
||||
int SequenceNode::simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted, bool ignoreParentheses) const {
|
||||
/* This function ensures that terms like u(n) and u(n+1), u(n) and v(n),
|
||||
* u(a) and u(b) do not factorize.
|
||||
* We never want to factorize. The only cases where it could be useful are
|
||||
* like the following : u(n)+u(n). But thanks to the cache system, no
|
||||
* computation is needed for the second term.*/
|
||||
assert(type() == e->type());
|
||||
assert(numberOfChildren() == 1);
|
||||
assert(e->numberOfChildren() == 1);
|
||||
ExpressionNode * seq = const_cast<ExpressionNode*>(e);
|
||||
int delta = strcmp(name(), reinterpret_cast<SequenceNode *>(seq)->name());
|
||||
if (delta == 0) {
|
||||
return SimplificationOrder(childAtIndex(0), e->childAtIndex(0), ascending, canBeInterrupted, ignoreParentheses);
|
||||
}
|
||||
return delta;
|
||||
}
|
||||
|
||||
Layout SequenceNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const {
|
||||
assert(name()[0] >= 'u' && name()[0] <= 'w');
|
||||
Layout rank;
|
||||
for (char sequenceName = 'u'; sequenceName <= 'w'; sequenceName++) {
|
||||
if (name()[0] == sequenceName) {
|
||||
// Checking for the sequence children
|
||||
if (childAtIndex(0)->type() == Type::Symbol) {
|
||||
// u(n)
|
||||
rank = LayoutHelper::String("n", strlen("n"));
|
||||
} else if (childAtIndex(0)->type() == Type::Addition) {
|
||||
rank = LayoutHelper::String("n+1", strlen("n+1"));
|
||||
} else {
|
||||
assert(childAtIndex(0)->type() == Type::BasedInteger);
|
||||
rank = static_cast<BasedIntegerNode &>(*childAtIndex(0)).integer().createLayout();
|
||||
}
|
||||
return HorizontalLayout::Builder(
|
||||
CodePointLayout::Builder(sequenceName),
|
||||
VerticalOffsetLayout::Builder(rank, VerticalOffsetLayoutNode::Position::Subscript));
|
||||
}
|
||||
}
|
||||
assert(false);
|
||||
return LayoutHelper::String(name(), strlen(name()));
|
||||
Layout rank = childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits);
|
||||
return HorizontalLayout::Builder(
|
||||
CodePointLayout::Builder(name()[0]),
|
||||
VerticalOffsetLayout::Builder(rank, VerticalOffsetLayoutNode::Position::Subscript));
|
||||
}
|
||||
|
||||
int SequenceNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const {
|
||||
@@ -49,7 +50,7 @@ int SequenceNode::serialize(char * buffer, int bufferSize, Preferences::PrintFlo
|
||||
}
|
||||
|
||||
Expression SequenceNode::shallowReduce(ReductionContext reductionContext) {
|
||||
return Sequence(this).shallowReduce(reductionContext); // This uses Symbol::shallowReduce
|
||||
return Sequence(this).shallowReduce(reductionContext);
|
||||
}
|
||||
|
||||
Evaluation<float> SequenceNode::approximate(SinglePrecision p, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const {
|
||||
@@ -95,8 +96,12 @@ Expression Sequence::replaceSymbolWithExpression(const SymbolAbstract & symbol,
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Those two functions will be updated in a comming commit
|
||||
Expression Sequence::shallowReduce(ExpressionNode::ReductionContext reductionContext) {
|
||||
if (reductionContext.symbolicComputation() == ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithUndefined
|
||||
|| childAtIndex(0).isUndefined())
|
||||
{
|
||||
return replaceWithUndefinedInPlace();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,14 +32,22 @@ Evaluation<T> SumAndProductNode::templatedApproximate(Context * context, Prefere
|
||||
if (std::isnan(start) || std::isnan(end) || start != (int)start || end != (int)end || end - start > k_maxNumberOfSteps) {
|
||||
return Complex<T>::Undefined();
|
||||
}
|
||||
VariableContext nContext = VariableContext(static_cast<SymbolNode *>(childAtIndex(1))->name(), context);
|
||||
SymbolNode * symbol = static_cast<SymbolNode *>(childAtIndex(1));
|
||||
VariableContext nContext = VariableContext(symbol->name(), context);
|
||||
Evaluation<T> result = Complex<T>::Builder((T)emptySumAndProductValue());
|
||||
for (int i = (int)start; i <= (int)end; i++) {
|
||||
if (Expression::ShouldStopProcessing()) {
|
||||
return Complex<T>::Undefined();
|
||||
}
|
||||
nContext.setApproximationForVariable<T>((T)i);
|
||||
result = evaluateWithNextTerm(T(), result, childAtIndex(0)->approximate(T(), &nContext, complexFormat, angleUnit), complexFormat);
|
||||
Expression child = Expression(childAtIndex(0)).clone();
|
||||
if (child.type() == ExpressionNode::Type::Sequence) {
|
||||
/* Since we cannot get the expression of a sequence term like we would for
|
||||
* a function, we replace its potential abstract rank by the value it should
|
||||
* have. We can then evaluate its value */
|
||||
child.childAtIndex(0).replaceSymbolWithExpression(symbol, Float<T>::Builder(i));
|
||||
}
|
||||
result = evaluateWithNextTerm(T(), result, child.node()->approximate(T(), &nContext, complexFormat, angleUnit), complexFormat);
|
||||
if (result.isUndefined()) {
|
||||
return Complex<T>::Undefined();
|
||||
}
|
||||
|
||||
@@ -37,11 +37,6 @@ Expression SymbolAbstractNode::setSign(ExpressionNode::Sign s, ReductionContext
|
||||
|
||||
int SymbolAbstractNode::simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted, bool ignoreParentheses) const {
|
||||
assert(type() == e->type());
|
||||
/* We do not want the sequences to be factorized. Otherwise, u(n) will be
|
||||
* factorized with u(n+1). */
|
||||
if (type() == Type::Sequence) {
|
||||
return -1;
|
||||
}
|
||||
return strcmp(name(), static_cast<const SymbolAbstractNode *>(e)->name());
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include <poincare/preferences.h>
|
||||
#include <poincare/symbol.h>
|
||||
#include <poincare/undefined.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
Reference in New Issue
Block a user