diff --git a/apps/regression/regression_context.cpp b/apps/regression/regression_context.cpp index 956da75d8..ef84c9aad 100644 --- a/apps/regression/regression_context.cpp +++ b/apps/regression/regression_context.cpp @@ -9,7 +9,7 @@ using namespace Shared; namespace Regression { -const Expression RegressionContext::expressionForSymbolAbstract(const SymbolAbstract & symbol, bool clone) { +const Expression RegressionContext::expressionForSymbolAbstract(const Poincare::SymbolAbstract & symbol, bool clone, float unknownSymbolValue ) { if (symbol.type() == ExpressionNode::Type::Symbol && Symbol::isRegressionSymbol(symbol.name(), nullptr)) { const char * seriesName = symbol.name(); assert(strlen(seriesName) == 2); diff --git a/apps/regression/regression_context.h b/apps/regression/regression_context.h index c9e5fe8dd..0ab483acc 100644 --- a/apps/regression/regression_context.h +++ b/apps/regression/regression_context.h @@ -9,7 +9,7 @@ namespace Regression { class RegressionContext : public Shared::StoreContext { public: using Shared::StoreContext::StoreContext; - const Poincare::Expression expressionForSymbolAbstract(const Poincare::SymbolAbstract & symbol, bool clone) override; + const Poincare::Expression expressionForSymbolAbstract(const Poincare::SymbolAbstract & symbol, bool clone, float unknownSymbolValue = NAN) override; }; } diff --git a/apps/shared/cache_context.cpp b/apps/shared/cache_context.cpp index 41425558f..0758ba9b4 100644 --- a/apps/shared/cache_context.cpp +++ b/apps/shared/cache_context.cpp @@ -19,7 +19,7 @@ CacheContext::CacheContext(Context * parentContext) : } template -const Expression CacheContext::expressionForSymbolAbstract(const SymbolAbstract & symbol, bool clone) { +const Expression CacheContext::expressionForSymbolAbstract(const Poincare::SymbolAbstract & symbol, bool clone, float unknownSymbolValue ) { // [u|v|w](n(+1)?) if (symbol.type() == ExpressionNode::Type::Sequence) { int index = nameIndexForSymbol(const_cast(static_cast(symbol))); diff --git a/apps/shared/cache_context.h b/apps/shared/cache_context.h index 7f10a99f9..3dabf0cfe 100644 --- a/apps/shared/cache_context.h +++ b/apps/shared/cache_context.h @@ -12,7 +12,7 @@ template class CacheContext : public Poincare::ContextWithParent { public: CacheContext(Poincare::Context * parentContext); - const Poincare::Expression expressionForSymbolAbstract(const Poincare::SymbolAbstract & symbol, bool clone) override; + const Poincare::Expression expressionForSymbolAbstract(const Poincare::SymbolAbstract & symbol, bool clone, float unknownSymbolValue = NAN) override; void setValueForSymbol(T value, const Poincare::Symbol & symbol); void setNValue(int n) { m_nValue = n; } void setSequenceContext(SequenceContext * sequenceContext) { m_sequenceContext = sequenceContext;} diff --git a/apps/shared/global_context.cpp b/apps/shared/global_context.cpp index 43817af5b..b5b6d6fe2 100644 --- a/apps/shared/global_context.cpp +++ b/apps/shared/global_context.cpp @@ -2,6 +2,7 @@ #include "continuous_function.h" #include "sequence.h" #include "poincare_helpers.h" +#include #include #include @@ -56,9 +57,9 @@ Context::SymbolAbstractType GlobalContext::expressionTypeForIdentifier(const cha } } -const Expression GlobalContext::expressionForSymbolAbstract(const SymbolAbstract & symbol, bool clone) { +const Expression GlobalContext::expressionForSymbolAbstract(const Poincare::SymbolAbstract & symbol, bool clone, float unknownSymbolValue ) { Ion::Storage::Record r = SymbolAbstractRecordWithBaseName(symbol.name()); - return ExpressionForSymbolAndRecord(symbol, r, this); + return ExpressionForSymbolAndRecord(symbol, r, this, unknownSymbolValue); } void GlobalContext::setExpressionForSymbolAbstract(const Expression & expression, const SymbolAbstract & symbol) { @@ -83,14 +84,14 @@ void GlobalContext::setExpressionForSymbolAbstract(const Expression & expression } } -const Expression GlobalContext::ExpressionForSymbolAndRecord(const SymbolAbstract & symbol, Ion::Storage::Record r, Context * ctx) { +const Expression GlobalContext::ExpressionForSymbolAndRecord(const SymbolAbstract & symbol, Ion::Storage::Record r, Context * ctx, float unknownSymbolValue ) { if (symbol.type() == ExpressionNode::Type::Symbol) { return ExpressionForActualSymbol(r); } else if (symbol.type() == ExpressionNode::Type::Function) { return ExpressionForFunction(symbol, r); } assert(symbol.type() == ExpressionNode::Type::Sequence); - return ExpressionForSequence(symbol, r, ctx); + return ExpressionForSequence(symbol, r, ctx, unknownSymbolValue); } const Expression GlobalContext::ExpressionForActualSymbol(Ion::Storage::Record r) { @@ -115,14 +116,17 @@ const Expression GlobalContext::ExpressionForFunction(const SymbolAbstract & sym return e; } -const Expression GlobalContext::ExpressionForSequence(const SymbolAbstract & symbol, Ion::Storage::Record r, Context * ctx) { +const Expression GlobalContext::ExpressionForSequence(const SymbolAbstract & symbol, Ion::Storage::Record r, Context * ctx, float unknownSymbolValue) { if (!Ion::Storage::FullNameHasExtension(r.fullName(), Ion::Storage::seqExtension, strlen(Ion::Storage::seqExtension))) { return Expression(); } /* An function record value has metadata before the expression. To get the * expression, use the function record handle. */ Sequence seq(r); - double rank = PoincareHelpers::ApproximateToScalar(symbol.childAtIndex(0), ctx); + constexpr int bufferSize = CodePoint::MaxCodePointCharLength + 1; + char unknownN[bufferSize]; + Poincare::SerializationHelper::CodePoint(unknownN, bufferSize, UCodePointUnknown); + float rank = symbol.childAtIndex(0).approximateWithValueForSymbol(unknownN, unknownSymbolValue, ctx, Preferences::sharedPreferences()->complexFormat(),Preferences::sharedPreferences()->angleUnit()); if (std::floor(rank) == rank) { SequenceContext sqctx(ctx, sequenceStore()); return Float::Builder(seq.evaluateXYAtParameter(rank, &sqctx).x2()); diff --git a/apps/shared/global_context.h b/apps/shared/global_context.h index f17aa44fd..bf71a2c99 100644 --- a/apps/shared/global_context.h +++ b/apps/shared/global_context.h @@ -29,15 +29,15 @@ public: * The expression recorded in global context is already an expression. * Otherwise, we would need the context and the angle unit to evaluate it */ SymbolAbstractType expressionTypeForIdentifier(const char * identifier, int length) override; - const Poincare::Expression expressionForSymbolAbstract(const Poincare::SymbolAbstract & symbol, bool clone) override; + const Poincare::Expression expressionForSymbolAbstract(const Poincare::SymbolAbstract & symbol, bool clone, float unknownSymbolValue = NAN) override; void setExpressionForSymbolAbstract(const Poincare::Expression & expression, const Poincare::SymbolAbstract & symbol) override; static SequenceStore * sequenceStore(); private: // Expression getters - static const Poincare::Expression ExpressionForSymbolAndRecord(const Poincare::SymbolAbstract & symbol, Ion::Storage::Record r, Context * ctx); + static const Poincare::Expression ExpressionForSymbolAndRecord(const Poincare::SymbolAbstract & symbol, Ion::Storage::Record r, Context * ctx, float unknownSymbolValue = NAN); static const Poincare::Expression ExpressionForActualSymbol(Ion::Storage::Record r); static const Poincare::Expression ExpressionForFunction(const Poincare::SymbolAbstract & symbol, Ion::Storage::Record r); - static const Poincare::Expression ExpressionForSequence(const Poincare::SymbolAbstract & symbol, Ion::Storage::Record r, Context * ctx); + static const Poincare::Expression ExpressionForSequence(const Poincare::SymbolAbstract & symbol, Ion::Storage::Record r, Context * ctx, float unknownSymbolValue = NAN); // Expression setters static Ion::Storage::Record::ErrorStatus SetExpressionForActualSymbol(const Poincare::Expression & expression, const Poincare::SymbolAbstract & symbol, Ion::Storage::Record previousRecord); static Ion::Storage::Record::ErrorStatus SetExpressionForFunction(const Poincare::Expression & expression, const Poincare::SymbolAbstract & symbol, Ion::Storage::Record previousRecord); diff --git a/apps/statistics/statistics_context.cpp b/apps/statistics/statistics_context.cpp index 96a891d43..f781635a7 100644 --- a/apps/statistics/statistics_context.cpp +++ b/apps/statistics/statistics_context.cpp @@ -9,7 +9,7 @@ using namespace Shared; namespace Statistics { -const Expression StatisticsContext::expressionForSymbolAbstract(const SymbolAbstract & symbol, bool clone) { +const Expression StatisticsContext::expressionForSymbolAbstract(const Poincare::SymbolAbstract & symbol, bool clone, float unknownSymbolValue ) { if (symbol.type() == ExpressionNode::Type::Symbol && Symbol::isSeriesSymbol(symbol.name(), nullptr)) { const char * seriesName = symbol.name(); assert(strlen(seriesName) == 2); diff --git a/apps/statistics/statistics_context.h b/apps/statistics/statistics_context.h index 2ca69c089..6a37d663d 100644 --- a/apps/statistics/statistics_context.h +++ b/apps/statistics/statistics_context.h @@ -8,7 +8,7 @@ namespace Statistics { class StatisticsContext : public Shared::StoreContext { public: using Shared::StoreContext::StoreContext; - const Poincare::Expression expressionForSymbolAbstract(const Poincare::SymbolAbstract & symbol, bool clone) override; + const Poincare::Expression expressionForSymbolAbstract(const Poincare::SymbolAbstract & symbol, bool clone, float unknownSymbolValue = NAN) override; }; } diff --git a/poincare/include/poincare/context.h b/poincare/include/poincare/context.h index c695d4711..5b23367c7 100644 --- a/poincare/include/poincare/context.h +++ b/poincare/include/poincare/context.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -18,7 +19,7 @@ public: Symbol }; virtual SymbolAbstractType expressionTypeForIdentifier(const char * identifier, int length) = 0; - virtual const Expression expressionForSymbolAbstract(const SymbolAbstract & symbol, bool clone) = 0; + virtual const Expression expressionForSymbolAbstract(const SymbolAbstract & symbol, bool clone, float unknownSymbolValue = NAN) = 0; virtual void setExpressionForSymbolAbstract(const Expression & expression, const SymbolAbstract & symbol) = 0; }; diff --git a/poincare/include/poincare/context_with_parent.h b/poincare/include/poincare/context_with_parent.h index 4e52ce828..6b80cd907 100644 --- a/poincare/include/poincare/context_with_parent.h +++ b/poincare/include/poincare/context_with_parent.h @@ -14,7 +14,7 @@ public: // Context SymbolAbstractType expressionTypeForIdentifier(const char * identifier, int length) override { return m_parentContext->expressionTypeForIdentifier(identifier, length); } void setExpressionForSymbolAbstract(const Expression & expression, const SymbolAbstract & symbol) override { m_parentContext->setExpressionForSymbolAbstract(expression, symbol); } - const Expression expressionForSymbolAbstract(const SymbolAbstract & symbol, bool clone) override { return m_parentContext->expressionForSymbolAbstract(symbol, clone); } + const Expression expressionForSymbolAbstract(const SymbolAbstract & symbol, bool clone, float unknownSymbolValue = NAN) override { return m_parentContext->expressionForSymbolAbstract(symbol, clone, unknownSymbolValue); } private: Context * m_parentContext; diff --git a/poincare/include/poincare/empty_context.h b/poincare/include/poincare/empty_context.h index f8e7e65c5..a3fe24fa3 100644 --- a/poincare/include/poincare/empty_context.h +++ b/poincare/include/poincare/empty_context.h @@ -12,7 +12,7 @@ public: // Context SymbolAbstractType expressionTypeForIdentifier(const char * identifier, int length) override { return SymbolAbstractType::None; } void setExpressionForSymbolAbstract(const Expression & expression, const SymbolAbstract & symbol) override { assert(false); } - const Expression expressionForSymbolAbstract(const SymbolAbstract & symbol, bool clone) override { return Expression(); } + const Expression expressionForSymbolAbstract(const SymbolAbstract & symbol, bool clone, float unknownSymbolValue = NAN) override { return Expression(); } }; } diff --git a/poincare/include/poincare/variable_context.h b/poincare/include/poincare/variable_context.h index 06d9f7992..19b413607 100644 --- a/poincare/include/poincare/variable_context.h +++ b/poincare/include/poincare/variable_context.h @@ -18,7 +18,7 @@ public: // Context void setExpressionForSymbolAbstract(const Expression & expression, const SymbolAbstract & symbol) override; - const Expression expressionForSymbolAbstract(const SymbolAbstract & symbol, bool clone) override; + const Expression expressionForSymbolAbstract(const SymbolAbstract & symbol, bool clone, float unknownSymbolValue = NAN) override; private: const char * m_name; diff --git a/poincare/src/variable_context.cpp b/poincare/src/variable_context.cpp index 75812fab7..f7191a1a2 100644 --- a/poincare/src/variable_context.cpp +++ b/poincare/src/variable_context.cpp @@ -23,14 +23,18 @@ void VariableContext::setExpressionForSymbolAbstract(const Expression & expressi } } -const Expression VariableContext::expressionForSymbolAbstract(const SymbolAbstract & symbol, bool clone) { +const Expression VariableContext::expressionForSymbolAbstract(const SymbolAbstract & symbol, bool clone, float unknownSymbolValue ) { if (m_name != nullptr && strcmp(symbol.name(), m_name) == 0) { if (symbol.type() == ExpressionNode::Type::Symbol) { return clone ? m_value.clone() : m_value; } return Undefined::Builder(); } else { - return ContextWithParent::expressionForSymbolAbstract(symbol, clone); + Symbol unknownSymbol = Symbol::Builder(UCodePointUnknown); + if (m_name != nullptr && strcmp(m_name, unknownSymbol.name()) == 0) { + unknownSymbolValue = m_value.approximateToScalar(this, Preferences::sharedPreferences()->complexFormat(),Preferences::sharedPreferences()->angleUnit()); + } + return ContextWithParent::expressionForSymbolAbstract(symbol, clone, unknownSymbolValue); } }