mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
[poincare] Allow replacement of sequences by their definition if rank is an integer
This commit is contained in:
@@ -124,7 +124,7 @@ void MathVariableBoxController::willDisplayCellForIndex(HighlightCell * cell, in
|
|||||||
symbolName,
|
symbolName,
|
||||||
Shared::Sequence::k_maxNameWithArgumentSize
|
Shared::Sequence::k_maxNameWithArgumentSize
|
||||||
);
|
);
|
||||||
Expression symbolExpression = Expression::ParseAndSimplify(symbolName, AppsContainer::sharedAppsContainer()->globalContext(), Poincare::Preferences::sharedPreferences()->complexFormat(), Poincare::Preferences::sharedPreferences()->angleUnit(), GlobalPreferences::sharedGlobalPreferences()->unitFormat());
|
Expression symbolExpression = Expression::Parse(symbolName, AppsContainer::sharedAppsContainer()->globalContext());
|
||||||
symbolLayout = symbolExpression.createLayout(Poincare::Preferences::sharedPreferences()->displayMode(), Poincare::Preferences::sharedPreferences()->numberOfSignificantDigits());
|
symbolLayout = symbolExpression.createLayout(Poincare::Preferences::sharedPreferences()->displayMode(), Poincare::Preferences::sharedPreferences()->numberOfSignificantDigits());
|
||||||
}
|
}
|
||||||
if (symbolLayout.isUninitialized()) {
|
if (symbolLayout.isUninitialized()) {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public:
|
|||||||
static constexpr char funcExtension[] = "func";
|
static constexpr char funcExtension[] = "func";
|
||||||
static constexpr char seqExtension[] = "seq";
|
static constexpr char seqExtension[] = "seq";
|
||||||
|
|
||||||
class Record {
|
class Record {
|
||||||
/* A Record is identified by the CRC32 on its fullName because:
|
/* A Record is identified by the CRC32 on its fullName because:
|
||||||
* - A record is identified by its fullName, which is unique
|
* - A record is identified by its fullName, which is unique
|
||||||
* - We cannot keep the address pointing to the fullName because if another
|
* - We cannot keep the address pointing to the fullName because if another
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ public:
|
|||||||
None,
|
None,
|
||||||
Function,
|
Function,
|
||||||
Sequence,
|
Sequence,
|
||||||
Symbol
|
Symbol,
|
||||||
|
Integer // Used to simplify sequences
|
||||||
};
|
};
|
||||||
virtual SymbolAbstractType expressionTypeForIdentifier(const char * identifier, int length) = 0;
|
virtual SymbolAbstractType expressionTypeForIdentifier(const char * identifier, int length) = 0;
|
||||||
virtual const Expression expressionForSymbolAbstract(const SymbolAbstract & symbol, bool clone, float unknownSymbolValue = NAN) = 0;
|
virtual const Expression expressionForSymbolAbstract(const SymbolAbstract & symbol, bool clone, float unknownSymbolValue = NAN) = 0;
|
||||||
|
|||||||
24
poincare/include/poincare/integer_variable_context.h
Normal file
24
poincare/include/poincare/integer_variable_context.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef POINCARE_INTEGER_VARIABLE_CONTEXT_H
|
||||||
|
#define POINCARE_INTEGER_VARIABLE_CONTEXT_H
|
||||||
|
|
||||||
|
#include <poincare/context_with_parent.h>
|
||||||
|
#include <poincare/float.h>
|
||||||
|
|
||||||
|
namespace Poincare {
|
||||||
|
|
||||||
|
class IntegerVariableContext : public ContextWithParent {
|
||||||
|
public:
|
||||||
|
IntegerVariableContext(const char * name, Context * parentContext) :
|
||||||
|
ContextWithParent(parentContext),
|
||||||
|
m_name(name)
|
||||||
|
{}
|
||||||
|
|
||||||
|
SymbolAbstractType expressionTypeForIdentifier(const char * identifier, int length) override { return strcmp(m_name, identifier) == 0 ? SymbolAbstractType::Integer : ContextWithParent::expressionTypeForIdentifier(identifier, length); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char * m_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -18,6 +18,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
Type type() const override { return Type::Sequence; }
|
Type type() const override { return Type::Sequence; }
|
||||||
|
virtual Expression deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly, int parameteredAncestorsCount) override;
|
||||||
Expression replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression) override;
|
Expression replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression) override;
|
||||||
int simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted, bool ignoreParentheses) const override;
|
int simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted, bool ignoreParentheses) const override;
|
||||||
|
|
||||||
@@ -46,6 +47,7 @@ public:
|
|||||||
static Sequence Builder(const char * name, size_t length, Expression child = Expression());
|
static Sequence Builder(const char * name, size_t length, Expression child = Expression());
|
||||||
|
|
||||||
// Simplification
|
// Simplification
|
||||||
|
Expression replacedByDefinitionIfPossible(Context * reductionContext);
|
||||||
Expression replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression);
|
Expression replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression);
|
||||||
Expression shallowReduce(ExpressionNode::ReductionContext reductionContext);
|
Expression shallowReduce(ExpressionNode::ReductionContext reductionContext);
|
||||||
Expression deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly, int parameteredAncestorsCount);
|
Expression deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly, int parameteredAncestorsCount);
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ namespace Poincare {
|
|||||||
class SumAndProductNode : public ParameteredExpressionNode {
|
class SumAndProductNode : public ParameteredExpressionNode {
|
||||||
public:
|
public:
|
||||||
int numberOfChildren() const override { return 4; }
|
int numberOfChildren() const override { return 4; }
|
||||||
|
virtual void deepReduceChildren(ReductionContext reductionContext) override;
|
||||||
|
virtual Expression deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly, int parameteredAncestorsCount) override;
|
||||||
private:
|
private:
|
||||||
Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
|
Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
|
||||||
virtual Layout createSumAndProductLayout(Layout argumentLayout, Layout symbolLayout, Layout subscriptLayout, Layout superscriptLayout) const = 0;
|
virtual Layout createSumAndProductLayout(Layout argumentLayout, Layout symbolLayout, Layout subscriptLayout, Layout superscriptLayout) const = 0;
|
||||||
@@ -28,6 +30,7 @@ private:
|
|||||||
class SumAndProduct : public Expression {
|
class SumAndProduct : public Expression {
|
||||||
public:
|
public:
|
||||||
SumAndProduct(const SumAndProductNode * n) : Expression(n) {}
|
SumAndProduct(const SumAndProductNode * n) : Expression(n) {}
|
||||||
|
Expression deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly, int parameteredAncestorsCount);
|
||||||
Expression shallowReduce(Context * context);
|
Expression shallowReduce(Context * context);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ Expression Function::shallowReduce(ExpressionNode::ReductionContext reductionCon
|
|||||||
Expression Function::deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly, int parameteredAncestorsCount) {
|
Expression Function::deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly, int parameteredAncestorsCount) {
|
||||||
{
|
{
|
||||||
// Replace replaceable symbols in child
|
// Replace replaceable symbols in child
|
||||||
Expression self = defaultReplaceReplaceableSymbols(context, didReplace, replaceFunctionsOnly ,parameteredAncestorsCount);
|
Expression self = defaultReplaceReplaceableSymbols(context, didReplace, replaceFunctionsOnly, parameteredAncestorsCount);
|
||||||
if (self.isUninitialized()) { // if the child is circularly defined, escape
|
if (self.isUninitialized()) { // if the child is circularly defined, escape
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,10 @@
|
|||||||
#include <poincare/parenthesis.h>
|
#include <poincare/parenthesis.h>
|
||||||
#include <poincare/complex.h>
|
#include <poincare/complex.h>
|
||||||
#include <apps/shared/sequence.h>
|
#include <apps/shared/sequence.h>
|
||||||
|
#include <poincare/context.h>
|
||||||
|
#include <poincare/rational.h>
|
||||||
|
#include <poincare/undefined.h>
|
||||||
|
#include <ion/storage.h>
|
||||||
|
|
||||||
namespace Poincare {
|
namespace Poincare {
|
||||||
|
|
||||||
@@ -106,19 +110,94 @@ Expression Sequence::replaceSymbolWithExpression(const SymbolAbstract & symbol,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Expression Sequence::shallowReduce(ExpressionNode::ReductionContext reductionContext) {
|
Expression Sequence::shallowReduce(ExpressionNode::ReductionContext reductionContext) {
|
||||||
Expression e = Expression::defaultShallowReduce();
|
|
||||||
e = e.defaultHandleUnitsInChildren();
|
|
||||||
if (e.isUndefined()) {
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
if (reductionContext.symbolicComputation() == ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithUndefined) {
|
if (reductionContext.symbolicComputation() == ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithUndefined) {
|
||||||
return replaceWithUndefinedInPlace();
|
return replaceWithUndefinedInPlace();
|
||||||
}
|
}
|
||||||
return *this;
|
|
||||||
|
if (reductionContext.symbolicComputation() == ExpressionNode::SymbolicComputation::DoNotReplaceAnySymbol) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression result = replacedByDefinitionIfPossible(reductionContext.context());
|
||||||
|
result = Expression::ExpressionWithoutSymbols(result, reductionContext.context());
|
||||||
|
|
||||||
|
if (result.isUninitialized()) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
replaceWithInPlace(result);
|
||||||
|
|
||||||
|
// We simplify the expression entered by the user
|
||||||
|
return result.deepReduce(reductionContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression SequenceNode::deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly, int parameteredAncestorsCount) {
|
||||||
|
return Sequence(this).deepReplaceReplaceableSymbols(context, didReplace, replaceFunctionsOnly, parameteredAncestorsCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
Expression Sequence::deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly, int parameteredAncestorsCount) {
|
Expression Sequence::deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly, int parameteredAncestorsCount) {
|
||||||
|
{
|
||||||
|
// Replace replaceable symbols in child
|
||||||
|
Expression self = defaultReplaceReplaceableSymbols(context, didReplace, replaceFunctionsOnly, parameteredAncestorsCount);
|
||||||
|
if (self.isUninitialized()) { // if the child is circularly defined, escape
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
assert(*this == self);
|
||||||
|
}
|
||||||
|
Expression e = replacedByDefinitionIfPossible(context);
|
||||||
|
if (e.isUninitialized()) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
// If the function contains itself, return undefined
|
||||||
|
if (e.hasExpression([](Expression e, const void * context) {
|
||||||
|
if (e.type() != ExpressionNode::Type::Sequence) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return strcmp(static_cast<Sequence&>(e).name(), reinterpret_cast<const char *>(context)) == 0;
|
||||||
|
}, reinterpret_cast<const void *>(name())))
|
||||||
|
{
|
||||||
|
return Expression();
|
||||||
|
}
|
||||||
|
replaceWithInPlace(e);
|
||||||
|
*didReplace = true;
|
||||||
|
return e;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expression Sequence::replacedByDefinitionIfPossible(Context * context) {
|
||||||
|
// We try to replace the sequence by his definition ONLY if the index is an integer
|
||||||
|
bool canBeReplacedByExpression = false;
|
||||||
|
|
||||||
|
if (childAtIndex(0).type() == ExpressionNode::Type::Symbol) {
|
||||||
|
const char * symbolName = (childAtIndex(0).convert<SymbolAbstract>()).name();
|
||||||
|
if (context->expressionTypeForIdentifier(symbolName, strlen(symbolName)) == Context::SymbolAbstractType::Integer) {
|
||||||
|
canBeReplacedByExpression = true;
|
||||||
|
}
|
||||||
|
} else if (childAtIndex(0).type() == ExpressionNode::Type::Rational) {
|
||||||
|
Rational r = childAtIndex(0).convert<Rational>();
|
||||||
|
if (r.isInteger()) {
|
||||||
|
canBeReplacedByExpression = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!canBeReplacedByExpression) {
|
||||||
|
return Expression();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ion::Storage::Record r = Ion::Storage::sharedStorage()->recordBaseNamedWithExtension(name(), Ion::Storage::seqExtension);
|
||||||
|
|
||||||
|
if (r.isNull()) {
|
||||||
|
return Expression();
|
||||||
|
}
|
||||||
|
|
||||||
|
Shared::Sequence seq(r);
|
||||||
|
|
||||||
|
if (seq.type() != Shared::Sequence::Type::Explicit) {
|
||||||
|
return Expression();
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression result = seq.expressionClone();
|
||||||
|
return result.replaceSymbolWithExpression(Symbol::Builder(UCodePointUnknown), childAtIndex(0));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
#include <poincare/decimal.h>
|
#include <poincare/decimal.h>
|
||||||
#include <poincare/undefined.h>
|
#include <poincare/undefined.h>
|
||||||
#include <poincare/variable_context.h>
|
#include <poincare/variable_context.h>
|
||||||
|
#include <poincare/integer_variable_context.h>
|
||||||
|
#include <poincare/sum.h>
|
||||||
|
#include <poincare/product.h>
|
||||||
|
#include <poincare/symbol.h>
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -56,6 +60,36 @@ Evaluation<T> SumAndProductNode::templatedApproximate(ApproximationContext appro
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expression SumAndProductNode::deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly, int parameteredAncestorsCount) {
|
||||||
|
return SumAndProduct(this).deepReplaceReplaceableSymbols(context, didReplace, replaceFunctionsOnly, parameteredAncestorsCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression SumAndProduct::deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly, int parameteredAncestorsCount) {
|
||||||
|
int nbChildren = numberOfChildren();
|
||||||
|
for (int i = 1; i < nbChildren; i++) {
|
||||||
|
Expression c = childAtIndex(i).deepReplaceReplaceableSymbols(context, didReplace, replaceFunctionsOnly, parameteredAncestorsCount);
|
||||||
|
if (c.isUninitialized()) {
|
||||||
|
return Expression();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Symbol symbol = childAtIndex(1).convert<Symbol>();
|
||||||
|
IntegerVariableContext newContext = IntegerVariableContext(symbol.name(), context);
|
||||||
|
Expression c = childAtIndex(0).deepReplaceReplaceableSymbols(&newContext, didReplace, replaceFunctionsOnly, parameteredAncestorsCount);
|
||||||
|
if (c.isUninitialized()) {
|
||||||
|
return Expression();
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SumAndProductNode::deepReduceChildren(ReductionContext reductionContext) {
|
||||||
|
SymbolNode * symbol = static_cast<SymbolNode *>(childAtIndex(1));
|
||||||
|
IntegerVariableContext newContext = IntegerVariableContext(symbol->name(), reductionContext.context());
|
||||||
|
reductionContext.setContext(&newContext);
|
||||||
|
ExpressionNode::deepReduceChildren(reductionContext);
|
||||||
|
}
|
||||||
|
|
||||||
Expression SumAndProduct::shallowReduce(Context * context) {
|
Expression SumAndProduct::shallowReduce(Context * context) {
|
||||||
{
|
{
|
||||||
Expression e = Expression::defaultShallowReduce();
|
Expression e = Expression::defaultShallowReduce();
|
||||||
|
|||||||
Reference in New Issue
Block a user