mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +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,
|
||||
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());
|
||||
}
|
||||
if (symbolLayout.isUninitialized()) {
|
||||
|
||||
@@ -28,7 +28,7 @@ public:
|
||||
static constexpr char funcExtension[] = "func";
|
||||
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 its fullName, which is unique
|
||||
* - We cannot keep the address pointing to the fullName because if another
|
||||
|
||||
@@ -16,7 +16,8 @@ public:
|
||||
None,
|
||||
Function,
|
||||
Sequence,
|
||||
Symbol
|
||||
Symbol,
|
||||
Integer // Used to simplify sequences
|
||||
};
|
||||
virtual SymbolAbstractType expressionTypeForIdentifier(const char * identifier, int length) = 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
|
||||
|
||||
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;
|
||||
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());
|
||||
|
||||
// Simplification
|
||||
Expression replacedByDefinitionIfPossible(Context * reductionContext);
|
||||
Expression replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression);
|
||||
Expression shallowReduce(ExpressionNode::ReductionContext reductionContext);
|
||||
Expression deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly, int parameteredAncestorsCount);
|
||||
|
||||
@@ -10,6 +10,8 @@ namespace Poincare {
|
||||
class SumAndProductNode : public ParameteredExpressionNode {
|
||||
public:
|
||||
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:
|
||||
Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
|
||||
virtual Layout createSumAndProductLayout(Layout argumentLayout, Layout symbolLayout, Layout subscriptLayout, Layout superscriptLayout) const = 0;
|
||||
@@ -28,6 +30,7 @@ private:
|
||||
class SumAndProduct : public Expression {
|
||||
public:
|
||||
SumAndProduct(const SumAndProductNode * n) : Expression(n) {}
|
||||
Expression deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly, int parameteredAncestorsCount);
|
||||
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) {
|
||||
{
|
||||
// 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
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,10 @@
|
||||
#include <poincare/parenthesis.h>
|
||||
#include <poincare/complex.h>
|
||||
#include <apps/shared/sequence.h>
|
||||
#include <poincare/context.h>
|
||||
#include <poincare/rational.h>
|
||||
#include <poincare/undefined.h>
|
||||
#include <ion/storage.h>
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
@@ -106,19 +110,94 @@ Expression Sequence::replaceSymbolWithExpression(const SymbolAbstract & symbol,
|
||||
}
|
||||
|
||||
Expression Sequence::shallowReduce(ExpressionNode::ReductionContext reductionContext) {
|
||||
Expression e = Expression::defaultShallowReduce();
|
||||
e = e.defaultHandleUnitsInChildren();
|
||||
if (e.isUndefined()) {
|
||||
return e;
|
||||
}
|
||||
if (reductionContext.symbolicComputation() == ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithUndefined) {
|
||||
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) {
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
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/undefined.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" {
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
@@ -56,6 +60,36 @@ Evaluation<T> SumAndProductNode::templatedApproximate(ApproximationContext appro
|
||||
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 e = Expression::defaultShallowReduce();
|
||||
|
||||
Reference in New Issue
Block a user