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
@@ -41,7 +41,10 @@ apps_src += $(addprefix apps/,\
|
|||||||
title_bar_view.cpp \
|
title_bar_view.cpp \
|
||||||
)
|
)
|
||||||
|
|
||||||
tests_src += apps/exam_mode_configuration_official.cpp
|
tests_src += $(addprefix apps/,\
|
||||||
|
exam_mode_configuration_official.cpp \
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
snapshots_declaration = $(foreach i,$(apps),$(i)::Snapshot m_snapshot$(subst :,,$(i))Snapshot;)
|
snapshots_declaration = $(foreach i,$(apps),$(i)::Snapshot m_snapshot$(subst :,,$(i))Snapshot;)
|
||||||
apps_declaration = $(foreach i,$(apps),$(i) m_$(subst :,,$(i));)
|
apps_declaration = $(foreach i,$(apps),$(i) m_$(subst :,,$(i));)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "history_controller.h"
|
#include "history_controller.h"
|
||||||
#include "../shared/text_field_delegate_app.h"
|
#include "../shared/text_field_delegate_app.h"
|
||||||
#include <escher.h>
|
#include <escher.h>
|
||||||
|
#include "../shared/shared_app.h"
|
||||||
|
|
||||||
namespace Calculation {
|
namespace Calculation {
|
||||||
|
|
||||||
@@ -17,7 +18,7 @@ public:
|
|||||||
I18n::Message upperName() override;
|
I18n::Message upperName() override;
|
||||||
const Image * icon() override;
|
const Image * icon() override;
|
||||||
};
|
};
|
||||||
class Snapshot : public ::App::Snapshot {
|
class Snapshot : public ::SharedApp::Snapshot {
|
||||||
public:
|
public:
|
||||||
Snapshot();
|
Snapshot();
|
||||||
App * unpack(Container * container) override;
|
App * unpack(Container * container) override;
|
||||||
|
|||||||
@@ -169,7 +169,8 @@ Calculation::DisplayOutput Calculation::displayOutput(Context * context) {
|
|||||||
ExpressionNode::Type::Sum,
|
ExpressionNode::Type::Sum,
|
||||||
ExpressionNode::Type::Derivative,
|
ExpressionNode::Type::Derivative,
|
||||||
ExpressionNode::Type::ConfidenceInterval,
|
ExpressionNode::Type::ConfidenceInterval,
|
||||||
ExpressionNode::Type::PredictionInterval
|
ExpressionNode::Type::PredictionInterval,
|
||||||
|
ExpressionNode::Type::Sequence
|
||||||
};
|
};
|
||||||
return e.isOfType(approximateOnlyTypes, sizeof(approximateOnlyTypes)/sizeof(ExpressionNode::Type));
|
return e.isOfType(approximateOnlyTypes, sizeof(approximateOnlyTypes)/sizeof(ExpressionNode::Type));
|
||||||
}, context)
|
}, context)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "script_store.h"
|
#include "script_store.h"
|
||||||
#include "python_toolbox.h"
|
#include "python_toolbox.h"
|
||||||
#include "variable_box_controller.h"
|
#include "variable_box_controller.h"
|
||||||
|
#include "../shared/shared_app.h"
|
||||||
|
|
||||||
namespace Code {
|
namespace Code {
|
||||||
|
|
||||||
@@ -20,7 +21,7 @@ public:
|
|||||||
I18n::Message upperName() override;
|
I18n::Message upperName() override;
|
||||||
const Image * icon() override;
|
const Image * icon() override;
|
||||||
};
|
};
|
||||||
class Snapshot : public ::App::Snapshot {
|
class Snapshot : public SharedApp::Snapshot {
|
||||||
public:
|
public:
|
||||||
Snapshot();
|
Snapshot();
|
||||||
App * unpack(Container * container) override;
|
App * unpack(Container * container) override;
|
||||||
|
|||||||
@@ -11,12 +11,13 @@
|
|||||||
#include "led_test_controller.h"
|
#include "led_test_controller.h"
|
||||||
#include "serial_number_controller.h"
|
#include "serial_number_controller.h"
|
||||||
#include "vblank_test_controller.h"
|
#include "vblank_test_controller.h"
|
||||||
|
#include "../shared/shared_app.h"
|
||||||
|
|
||||||
namespace HardwareTest {
|
namespace HardwareTest {
|
||||||
|
|
||||||
class App : public ::App {
|
class App : public ::App {
|
||||||
public:
|
public:
|
||||||
class Snapshot : public ::App::Snapshot {
|
class Snapshot : public ::SharedApp::Snapshot {
|
||||||
public:
|
public:
|
||||||
App * unpack(Container * container) override;
|
App * unpack(Container * container) override;
|
||||||
Descriptor * descriptor() override;
|
Descriptor * descriptor() override;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <escher.h>
|
#include <escher.h>
|
||||||
#include "controller.h"
|
#include "controller.h"
|
||||||
|
#include "../shared/shared_app.h"
|
||||||
|
|
||||||
namespace Home {
|
namespace Home {
|
||||||
|
|
||||||
@@ -13,7 +14,7 @@ public:
|
|||||||
I18n::Message name() override;
|
I18n::Message name() override;
|
||||||
I18n::Message upperName() override;
|
I18n::Message upperName() override;
|
||||||
};
|
};
|
||||||
class Snapshot : public ::App::Snapshot, public SelectableTableViewDataSource {
|
class Snapshot : public ::SharedApp::Snapshot, public SelectableTableViewDataSource {
|
||||||
public:
|
public:
|
||||||
App * unpack(Container * container) override;
|
App * unpack(Container * container) override;
|
||||||
Descriptor * descriptor() override;
|
Descriptor * descriptor() override;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <poincare/preferences.h>
|
#include <poincare/preferences.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <apps/shared/sequence.h>
|
||||||
|
|
||||||
using namespace Poincare;
|
using namespace Poincare;
|
||||||
using namespace Shared;
|
using namespace Shared;
|
||||||
@@ -76,6 +77,8 @@ int MathVariableBoxController::numberOfRows() const {
|
|||||||
return Storage::sharedStorage()->numberOfRecordsWithExtension(Ion::Storage::expExtension);
|
return Storage::sharedStorage()->numberOfRecordsWithExtension(Ion::Storage::expExtension);
|
||||||
case Page::Function:
|
case Page::Function:
|
||||||
return Storage::sharedStorage()->numberOfRecordsWithExtension(Ion::Storage::funcExtension);
|
return Storage::sharedStorage()->numberOfRecordsWithExtension(Ion::Storage::funcExtension);
|
||||||
|
case Page::Sequence:
|
||||||
|
return Storage::sharedStorage()->numberOfRecordsWithExtension(Ion::Storage::seqExtension);
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -104,13 +107,19 @@ void MathVariableBoxController::willDisplayCellForIndex(HighlightCell * cell, in
|
|||||||
if (m_currentPage == Page::Expression) {
|
if (m_currentPage == Page::Expression) {
|
||||||
static_assert(Shared::Function::k_maxNameWithArgumentSize > Poincare::SymbolAbstract::k_maxNameSize, "Forgot argument's size?");
|
static_assert(Shared::Function::k_maxNameWithArgumentSize > Poincare::SymbolAbstract::k_maxNameSize, "Forgot argument's size?");
|
||||||
symbolLength = SymbolAbstract::TruncateExtension(symbolName, record.fullName(), SymbolAbstract::k_maxNameSize);
|
symbolLength = SymbolAbstract::TruncateExtension(symbolName, record.fullName(), SymbolAbstract::k_maxNameSize);
|
||||||
} else {
|
} else if (m_currentPage == Page::Function) {
|
||||||
assert(m_currentPage == Page::Function);
|
|
||||||
ContinuousFunction f(record);
|
ContinuousFunction f(record);
|
||||||
symbolLength = f.nameWithArgument(
|
symbolLength = f.nameWithArgument(
|
||||||
symbolName,
|
symbolName,
|
||||||
Shared::Function::k_maxNameWithArgumentSize
|
Shared::Function::k_maxNameWithArgumentSize
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
assert(m_currentPage == Page::Sequence);
|
||||||
|
Shared::Sequence u(record);
|
||||||
|
symbolLength = u.nameWithArgument(
|
||||||
|
symbolName,
|
||||||
|
Shared::Sequence::k_maxNameWithArgumentSize
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Layout symbolLayout = LayoutHelper::String(symbolName, symbolLength);
|
Layout symbolLayout = LayoutHelper::String(symbolName, symbolLength);
|
||||||
myCell->setLayout(symbolLayout);
|
myCell->setLayout(symbolLayout);
|
||||||
@@ -147,7 +156,7 @@ MessageTableCellWithChevron * MathVariableBoxController::nodeCellAtIndex(int ind
|
|||||||
}
|
}
|
||||||
|
|
||||||
MathVariableBoxController::Page MathVariableBoxController::pageAtIndex(int index) {
|
MathVariableBoxController::Page MathVariableBoxController::pageAtIndex(int index) {
|
||||||
Page pages[2] = {Page::Expression, Page::Function};
|
Page pages[k_numberOfMenuRows] = {Page::Expression, Page::Function, Page::Sequence};
|
||||||
return pages[index];
|
return pages[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,7 +221,7 @@ bool MathVariableBoxController::selectLeaf(int selectedRow) {
|
|||||||
|
|
||||||
I18n::Message MathVariableBoxController::nodeLabelAtIndex(int index) {
|
I18n::Message MathVariableBoxController::nodeLabelAtIndex(int index) {
|
||||||
assert(m_currentPage == Page::RootMenu);
|
assert(m_currentPage == Page::RootMenu);
|
||||||
I18n::Message labels[2] = {I18n::Message::Expressions, I18n::Message::Functions};
|
I18n::Message labels[k_numberOfMenuRows] = {I18n::Message::Expressions, I18n::Message::Functions, I18n::Message::Sequences};
|
||||||
return labels[index];
|
return labels[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,7 +257,14 @@ Layout MathVariableBoxController::expressionLayoutForRecord(Storage::Record reco
|
|||||||
|
|
||||||
const char * MathVariableBoxController::extension() const {
|
const char * MathVariableBoxController::extension() const {
|
||||||
assert(m_currentPage != Page::RootMenu);
|
assert(m_currentPage != Page::RootMenu);
|
||||||
return m_currentPage == Page::Function ? Ion::Storage::funcExtension : Ion::Storage::expExtension;
|
if (m_currentPage == Page::Function) {
|
||||||
|
return Ion::Storage::funcExtension;
|
||||||
|
} else if (m_currentPage == Page::Expression) {
|
||||||
|
return Ion::Storage::expExtension;
|
||||||
|
} else {
|
||||||
|
assert(m_currentPage == Page::Sequence);
|
||||||
|
return Ion::Storage::seqExtension;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Storage::Record MathVariableBoxController::recordAtIndex(int rowIndex) {
|
Storage::Record MathVariableBoxController::recordAtIndex(int rowIndex) {
|
||||||
|
|||||||
@@ -27,13 +27,14 @@ public:
|
|||||||
enum class Page {
|
enum class Page {
|
||||||
RootMenu = 0,
|
RootMenu = 0,
|
||||||
Expression = 1,
|
Expression = 1,
|
||||||
Function = 2
|
Function = 2,
|
||||||
|
Sequence = 3
|
||||||
};
|
};
|
||||||
void lockDeleteEvent(Page page) { m_lockPageDelete = page; }
|
void lockDeleteEvent(Page page) { m_lockPageDelete = page; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
constexpr static int k_maxNumberOfDisplayedRows = (Ion::Display::Height - Metric::TitleBarHeight - Metric::PopUpTopMargin - Metric::StackTitleHeight) / Metric::ToolboxRowHeight + 2; // (240 - 18 - 50 - 20) / 40 = 3.8; the 0.8 cell can be above and below so we add +2 to get 5
|
constexpr static int k_maxNumberOfDisplayedRows = (Ion::Display::Height - Metric::TitleBarHeight - Metric::PopUpTopMargin - Metric::StackTitleHeight) / Metric::ToolboxRowHeight + 2; // (240 - 18 - 50 - 20) / 40 = 3.8; the 0.8 cell can be above and below so we add +2 to get 5
|
||||||
constexpr static int k_numberOfMenuRows = 2;
|
constexpr static int k_numberOfMenuRows = 3;
|
||||||
constexpr static KDCoordinate k_leafMargin = 20;
|
constexpr static KDCoordinate k_leafMargin = 20;
|
||||||
ExpressionTableCellWithExpression * leafCellAtIndex(int index) override;
|
ExpressionTableCellWithExpression * leafCellAtIndex(int index) override;
|
||||||
MessageTableCellWithChevron * nodeCellAtIndex(int index) override;
|
MessageTableCellWithChevron * nodeCellAtIndex(int index) override;
|
||||||
|
|||||||
@@ -45,6 +45,12 @@ void MathVariableBoxEmptyController::setType(Type type) {
|
|||||||
layout = Poincare::LayoutHelper::String(storeFunction, strlen(storeFunction), MathVariableBoxEmptyView::k_font);
|
layout = Poincare::LayoutHelper::String(storeFunction, strlen(storeFunction), MathVariableBoxEmptyView::k_font);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Type::Sequence:
|
||||||
|
{
|
||||||
|
messages[0] = I18n::Message::EmptySequenceBox0;
|
||||||
|
messages[3] = I18n::Message::Default;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ public:
|
|||||||
enum class Type {
|
enum class Type {
|
||||||
None = 0,
|
None = 0,
|
||||||
Expressions = 1,
|
Expressions = 1,
|
||||||
Functions = 2
|
Functions = 2,
|
||||||
|
Sequence = 3
|
||||||
};
|
};
|
||||||
void setType(Type type);
|
void setType(Type type);
|
||||||
// View Controller
|
// View Controller
|
||||||
|
|||||||
@@ -4,12 +4,13 @@
|
|||||||
#include <escher.h>
|
#include <escher.h>
|
||||||
#include "logo_controller.h"
|
#include "logo_controller.h"
|
||||||
#include "localization_controller.h"
|
#include "localization_controller.h"
|
||||||
|
#include "../shared/shared_app.h"
|
||||||
|
|
||||||
namespace OnBoarding {
|
namespace OnBoarding {
|
||||||
|
|
||||||
class App : public ::App {
|
class App : public ::App {
|
||||||
public:
|
public:
|
||||||
class Snapshot : public ::App::Snapshot {
|
class Snapshot : public ::SharedApp::Snapshot {
|
||||||
public:
|
public:
|
||||||
App * unpack(Container * container) override;
|
App * unpack(Container * container) override;
|
||||||
Descriptor * descriptor() override;
|
Descriptor * descriptor() override;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include "calculation/left_integral_calculation.h"
|
#include "calculation/left_integral_calculation.h"
|
||||||
#include "calculation/right_integral_calculation.h"
|
#include "calculation/right_integral_calculation.h"
|
||||||
#include "calculation/finite_integral_calculation.h"
|
#include "calculation/finite_integral_calculation.h"
|
||||||
|
#include "../shared/shared_app.h"
|
||||||
|
|
||||||
constexpr static size_t max(const int * data, int seed = 0) {
|
constexpr static size_t max(const int * data, int seed = 0) {
|
||||||
return (*data == 0 ? seed : max(data+1, *data > seed ? *data : seed));
|
return (*data == 0 ? seed : max(data+1, *data > seed ? *data : seed));
|
||||||
@@ -29,7 +30,7 @@ public:
|
|||||||
I18n::Message upperName() override;
|
I18n::Message upperName() override;
|
||||||
const Image * icon() override;
|
const Image * icon() override;
|
||||||
};
|
};
|
||||||
class Snapshot : public ::App::Snapshot {
|
class Snapshot : public ::SharedApp::Snapshot {
|
||||||
public:
|
public:
|
||||||
enum class Page {
|
enum class Page {
|
||||||
Distribution,
|
Distribution,
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "regression_controller.h"
|
#include "regression_controller.h"
|
||||||
#include "store.h"
|
#include "store.h"
|
||||||
#include "store_controller.h"
|
#include "store_controller.h"
|
||||||
|
#include "../shared/shared_app.h"
|
||||||
|
|
||||||
namespace Regression {
|
namespace Regression {
|
||||||
|
|
||||||
@@ -19,7 +20,7 @@ public:
|
|||||||
I18n::Message upperName() override;
|
I18n::Message upperName() override;
|
||||||
const Image * icon() override;
|
const Image * icon() override;
|
||||||
};
|
};
|
||||||
class Snapshot : public ::App::Snapshot, public TabViewDataSource {
|
class Snapshot : public ::SharedApp::Snapshot, public TabViewDataSource {
|
||||||
public:
|
public:
|
||||||
Snapshot();
|
Snapshot();
|
||||||
App * unpack(Container * container) override;
|
App * unpack(Container * container) override;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "app.h"
|
#include "app.h"
|
||||||
#include "../apps_container.h"
|
#include "../apps_container.h"
|
||||||
#include "sequence_icon.h"
|
#include "sequence_icon.h"
|
||||||
|
#include "../shared/global_context.h"
|
||||||
|
|
||||||
using namespace Poincare;
|
using namespace Poincare;
|
||||||
|
|
||||||
@@ -20,7 +21,6 @@ const Image * App::Descriptor::icon() {
|
|||||||
|
|
||||||
App::Snapshot::Snapshot() :
|
App::Snapshot::Snapshot() :
|
||||||
Shared::FunctionApp::Snapshot::Snapshot(),
|
Shared::FunctionApp::Snapshot::Snapshot(),
|
||||||
m_sequenceStore(),
|
|
||||||
m_graphRange()
|
m_graphRange()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -40,13 +40,12 @@ App::Descriptor * App::Snapshot::descriptor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void App::Snapshot::tidy() {
|
void App::Snapshot::tidy() {
|
||||||
m_sequenceStore.tidy();
|
|
||||||
m_graphRange.setDelegate(nullptr);
|
m_graphRange.setDelegate(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
App::App(Snapshot * snapshot) :
|
App::App(Snapshot * snapshot) :
|
||||||
FunctionApp(snapshot, &m_inputViewController),
|
FunctionApp(snapshot, &m_inputViewController),
|
||||||
m_sequenceContext(AppsContainer::sharedAppsContainer()->globalContext(), snapshot->functionStore()),
|
m_sequenceContext(AppsContainer::sharedAppsContainer()->globalContext(), static_cast<Shared::GlobalContext *>(AppsContainer::sharedAppsContainer()->globalContext())->sequenceStore()),
|
||||||
m_listController(&m_listFooter, this, &m_listHeader, &m_listFooter),
|
m_listController(&m_listFooter, this, &m_listHeader, &m_listFooter),
|
||||||
m_listFooter(&m_listHeader, &m_listController, &m_listController, ButtonRowController::Position::Bottom, ButtonRowController::Style::EmbossedGray),
|
m_listFooter(&m_listHeader, &m_listController, &m_listController, ButtonRowController::Position::Bottom, ButtonRowController::Style::EmbossedGray),
|
||||||
m_listHeader(nullptr, &m_listFooter, &m_listController),
|
m_listHeader(nullptr, &m_listFooter, &m_listController),
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
#include "values/values_controller.h"
|
#include "values/values_controller.h"
|
||||||
#include "../shared/function_app.h"
|
#include "../shared/function_app.h"
|
||||||
#include "../shared/interval.h"
|
#include "../shared/interval.h"
|
||||||
|
#include "../shared/global_context.h"
|
||||||
|
#include "../apps_container.h"
|
||||||
|
|
||||||
namespace Sequence {
|
namespace Sequence {
|
||||||
|
|
||||||
@@ -27,12 +29,11 @@ public:
|
|||||||
App * unpack(Container * container) override;
|
App * unpack(Container * container) override;
|
||||||
void reset() override;
|
void reset() override;
|
||||||
Descriptor * descriptor() override;
|
Descriptor * descriptor() override;
|
||||||
Shared::SequenceStore * functionStore() override { return &m_sequenceStore; }
|
Shared::SequenceStore * functionStore() override { return static_cast<Shared::GlobalContext *>(AppsContainer::sharedAppsContainer()->globalContext())->sequenceStore(); }
|
||||||
CurveViewRange * graphRange() { return &m_graphRange; }
|
CurveViewRange * graphRange() { return &m_graphRange; }
|
||||||
Shared::Interval * interval() { return &m_interval; }
|
Shared::Interval * interval() { return &m_interval; }
|
||||||
private:
|
private:
|
||||||
void tidy() override;
|
void tidy() override;
|
||||||
Shared::SequenceStore m_sequenceStore;
|
|
||||||
CurveViewRange m_graphRange;
|
CurveViewRange m_graphRange;
|
||||||
Shared::Interval m_interval;
|
Shared::Interval m_interval;
|
||||||
};
|
};
|
||||||
@@ -47,7 +48,7 @@ public:
|
|||||||
// NestedMenuController * variableBoxForInputEventHandler(InputEventHandler * textInput) override;
|
// NestedMenuController * variableBoxForInputEventHandler(InputEventHandler * textInput) override;
|
||||||
CodePoint XNT() override { return 'n'; }
|
CodePoint XNT() override { return 'n'; }
|
||||||
Shared::SequenceContext * localContext() override;
|
Shared::SequenceContext * localContext() override;
|
||||||
Shared::SequenceStore * functionStore() override { return snapshot()->functionStore(); }
|
Shared::SequenceStore * functionStore() override { return static_cast<Shared::GlobalContext *>(AppsContainer::sharedAppsContainer()->globalContext())->sequenceStore(); }
|
||||||
Shared::Interval * interval() { return snapshot()->interval(); }
|
Shared::Interval * interval() { return snapshot()->interval(); }
|
||||||
ValuesController * valuesController() override {
|
ValuesController * valuesController() override {
|
||||||
return &m_valuesController;
|
return &m_valuesController;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "main_controller.h"
|
#include "main_controller.h"
|
||||||
#include "../shared/text_field_delegate_app.h"
|
#include "../shared/text_field_delegate_app.h"
|
||||||
|
#include "../shared/shared_app.h"
|
||||||
|
|
||||||
namespace Settings {
|
namespace Settings {
|
||||||
|
|
||||||
@@ -14,7 +15,7 @@ public:
|
|||||||
I18n::Message upperName() override;
|
I18n::Message upperName() override;
|
||||||
const Image * icon() override;
|
const Image * icon() override;
|
||||||
};
|
};
|
||||||
class Snapshot : public ::App::Snapshot {
|
class Snapshot : public ::SharedApp::Snapshot {
|
||||||
public:
|
public:
|
||||||
App * unpack(Container * container) override;
|
App * unpack(Container * container) override;
|
||||||
Descriptor * descriptor() override;
|
Descriptor * descriptor() override;
|
||||||
|
|||||||
@@ -64,14 +64,15 @@ app_shared_src = $(addprefix apps/shared/,\
|
|||||||
range_parameter_controller.cpp \
|
range_parameter_controller.cpp \
|
||||||
regular_table_view_data_source.cpp \
|
regular_table_view_data_source.cpp \
|
||||||
round_cursor_view.cpp \
|
round_cursor_view.cpp \
|
||||||
|
scrollable_multiple_expressions_view.cpp \
|
||||||
|
scrollable_two_expressions_cell.cpp \
|
||||||
sequence.cpp\
|
sequence.cpp\
|
||||||
sequence_context.cpp\
|
sequence_context.cpp\
|
||||||
sequence_store.cpp\
|
sequence_store.cpp\
|
||||||
sequence_title_cell.cpp \
|
sequence_title_cell.cpp \
|
||||||
scrollable_multiple_expressions_view.cpp \
|
|
||||||
scrollable_two_expressions_cell.cpp \
|
|
||||||
separable.cpp \
|
separable.cpp \
|
||||||
separator_even_odd_buffer_text_cell.cpp \
|
separator_even_odd_buffer_text_cell.cpp \
|
||||||
|
shared_app.cpp \
|
||||||
simple_interactive_curve_view_controller.cpp \
|
simple_interactive_curve_view_controller.cpp \
|
||||||
store_cell.cpp \
|
store_cell.cpp \
|
||||||
store_controller.cpp \
|
store_controller.cpp \
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
#include "cache_context.h"
|
#include "cache_context.h"
|
||||||
#include "sequence.h"
|
#include "sequence.h"
|
||||||
#include "sequence_store.h"
|
#include "sequence_store.h"
|
||||||
#include "../shared/poincare_helpers.h"
|
#include "poincare_helpers.h"
|
||||||
#include <poincare/serialization_helper.h>
|
#include <poincare/serialization_helper.h>
|
||||||
|
#include <poincare/addition.h>
|
||||||
|
#include <poincare/rational.h>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
using namespace Poincare;
|
using namespace Poincare;
|
||||||
@@ -20,23 +22,22 @@ template<typename T>
|
|||||||
const Expression CacheContext<T>::expressionForSymbolAbstract(const SymbolAbstract & symbol, bool clone) {
|
const Expression CacheContext<T>::expressionForSymbolAbstract(const SymbolAbstract & symbol, bool clone) {
|
||||||
// [u|v|w](n(+1)?)
|
// [u|v|w](n(+1)?)
|
||||||
if (symbol.type() == ExpressionNode::Type::Sequence) {
|
if (symbol.type() == ExpressionNode::Type::Sequence) {
|
||||||
Symbol s = const_cast<Symbol &>(static_cast<const Symbol &>(symbol));
|
int index = nameIndexForSymbol(const_cast<Symbol &>(static_cast<const Symbol &>(symbol)));
|
||||||
if (s.childAtIndex(0).type() == ExpressionNode::Type::Symbol) {
|
Expression rank = symbol.childAtIndex(0).clone();
|
||||||
return Float<T>::Builder(m_values[nameIndexForSymbol(s)][0]);
|
if (rank.isIdenticalTo(Symbol::Builder(UCodePointUnknown))) {
|
||||||
} else if (s.childAtIndex(0).type() == ExpressionNode::Type::Addition) {
|
return Float<T>::Builder(m_values[index][0]);
|
||||||
return Float<T>::Builder(m_values[nameIndexForSymbol(s)][1]);
|
} if (rank.isIdenticalTo(Addition::Builder(Symbol::Builder(UCodePointUnknown), Rational::Builder(1)))) {
|
||||||
|
return Float<T>::Builder(m_values[index][1]);
|
||||||
|
}
|
||||||
|
Ion::Storage::Record record = m_sequenceContext->sequenceStore()->recordAtIndex(index);
|
||||||
|
Sequence * seq = m_sequenceContext->sequenceStore()->modelForRecord(record);
|
||||||
|
rank.replaceSymbolWithExpression(Symbol::Builder(UCodePointUnknown), Float<T>::Builder(m_nValue));
|
||||||
|
T n = PoincareHelpers::ApproximateToScalar<T>(rank, this);
|
||||||
|
// In case the rank is not int or sequence referenced is not defined, return NAN
|
||||||
|
if (std::floor(n) == n && seq->fullName() != nullptr) {
|
||||||
|
return Float<T>::Builder(seq->valueAtRank<T>(n, m_sequenceContext));
|
||||||
} else {
|
} else {
|
||||||
Sequence seq = m_sequenceContext->sequenceStore()->sequenceAtIndex(nameIndexForSymbol(s));
|
return Float<T>::Builder(NAN);
|
||||||
// In case the sequence referenced is not defined, return NAN
|
|
||||||
if (seq.fullName() == nullptr) {
|
|
||||||
return Float<T>::Builder(NAN);
|
|
||||||
}
|
|
||||||
Expression rank = symbol.childAtIndex(0);
|
|
||||||
if (rank.isNumber()) {
|
|
||||||
return Float<T>::Builder(seq.valueAtRank<T>(rank.approximateToScalar<double>(this, Poincare::Preferences::ComplexFormat::Cartesian, Poincare::Preferences::AngleUnit::Radian), m_sequenceContext));
|
|
||||||
} else {
|
|
||||||
return Float<T>::Builder(NAN);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ContextWithParent::expressionForSymbolAbstract(symbol, clone);
|
return ContextWithParent::expressionForSymbolAbstract(symbol, clone);
|
||||||
|
|||||||
@@ -14,11 +14,13 @@ public:
|
|||||||
CacheContext(Poincare::Context * parentContext);
|
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) override;
|
||||||
void setValueForSymbol(T value, const Poincare::Symbol & symbol);
|
void setValueForSymbol(T value, const Poincare::Symbol & symbol);
|
||||||
|
void setNValue(int n) { m_nValue = n; }
|
||||||
void setSequenceContext(SequenceContext * sequenceContext) { m_sequenceContext = sequenceContext;}
|
void setSequenceContext(SequenceContext * sequenceContext) { m_sequenceContext = sequenceContext;}
|
||||||
private:
|
private:
|
||||||
int nameIndexForSymbol(const Poincare::Symbol & symbol);
|
int nameIndexForSymbol(const Poincare::Symbol & symbol);
|
||||||
int rankIndexForSymbol(const Poincare::Symbol & symbol);
|
int rankIndexForSymbol(const Poincare::Symbol & symbol);
|
||||||
T m_values[MaxNumberOfSequences][MaxRecurrenceDepth];
|
T m_values[MaxNumberOfSequences][MaxRecurrenceDepth];
|
||||||
|
int m_nValue;
|
||||||
SequenceContext * m_sequenceContext;
|
SequenceContext * m_sequenceContext;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public:
|
|||||||
|
|
||||||
// Name
|
// Name
|
||||||
int name(char * buffer, size_t bufferSize);
|
int name(char * buffer, size_t bufferSize);
|
||||||
int nameWithArgument(char * buffer, size_t bufferSize);
|
virtual int nameWithArgument(char * buffer, size_t bufferSize);
|
||||||
virtual int printValue(double cursorT, double cursorX, double cursorY, char * buffer, int bufferSize, int precision, Poincare::Context * context);
|
virtual int printValue(double cursorT, double cursorX, double cursorY, char * buffer, int bufferSize, int precision, Poincare::Context * context);
|
||||||
virtual I18n::Message parameterMessageName() const = 0;
|
virtual I18n::Message parameterMessageName() const = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -6,12 +6,13 @@
|
|||||||
#include "function_store.h"
|
#include "function_store.h"
|
||||||
#include "curve_view_cursor.h"
|
#include "curve_view_cursor.h"
|
||||||
#include "values_controller.h"
|
#include "values_controller.h"
|
||||||
|
#include "shared_app.h"
|
||||||
|
|
||||||
namespace Shared {
|
namespace Shared {
|
||||||
|
|
||||||
class FunctionApp : public ExpressionFieldDelegateApp {
|
class FunctionApp : public ExpressionFieldDelegateApp {
|
||||||
public:
|
public:
|
||||||
class Snapshot : public ::App::Snapshot, public TabViewDataSource {
|
class Snapshot : public ::SharedApp::Snapshot, public TabViewDataSource {
|
||||||
public:
|
public:
|
||||||
Snapshot();
|
Snapshot();
|
||||||
CurveViewCursor * cursor() { return &m_cursor; }
|
CurveViewCursor * cursor() { return &m_cursor; }
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "global_context.h"
|
#include "global_context.h"
|
||||||
#include "continuous_function.h"
|
#include "continuous_function.h"
|
||||||
|
#include "sequence.h"
|
||||||
#include "poincare_helpers.h"
|
#include "poincare_helpers.h"
|
||||||
#include <poincare/undefined.h>
|
#include <poincare/undefined.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@@ -10,6 +11,13 @@ namespace Shared {
|
|||||||
|
|
||||||
constexpr const char * GlobalContext::k_extensions[];
|
constexpr const char * GlobalContext::k_extensions[];
|
||||||
|
|
||||||
|
SequenceStore * GlobalContext::sequenceStore() {
|
||||||
|
static SequenceStore sequenceStore;
|
||||||
|
return &sequenceStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool GlobalContext::SymbolAbstractNameIsFree(const char * baseName) {
|
bool GlobalContext::SymbolAbstractNameIsFree(const char * baseName) {
|
||||||
return SymbolAbstractRecordWithBaseName(baseName).isNull();
|
return SymbolAbstractRecordWithBaseName(baseName).isNull();
|
||||||
}
|
}
|
||||||
@@ -18,9 +26,11 @@ const Layout GlobalContext::LayoutForRecord(Ion::Storage::Record record) {
|
|||||||
assert(!record.isNull());
|
assert(!record.isNull());
|
||||||
if (Ion::Storage::FullNameHasExtension(record.fullName(), Ion::Storage::expExtension, strlen(Ion::Storage::expExtension))) {
|
if (Ion::Storage::FullNameHasExtension(record.fullName(), Ion::Storage::expExtension, strlen(Ion::Storage::expExtension))) {
|
||||||
return PoincareHelpers::CreateLayout(ExpressionForActualSymbol(record));
|
return PoincareHelpers::CreateLayout(ExpressionForActualSymbol(record));
|
||||||
} else {
|
} else if (Ion::Storage::FullNameHasExtension(record.fullName(), Ion::Storage::funcExtension, strlen(Ion::Storage::funcExtension))) {
|
||||||
assert(Ion::Storage::FullNameHasExtension(record.fullName(), Ion::Storage::funcExtension, strlen(Ion::Storage::funcExtension)));
|
|
||||||
return ContinuousFunction(record).layout();
|
return ContinuousFunction(record).layout();
|
||||||
|
} else {
|
||||||
|
assert(Ion::Storage::FullNameHasExtension(record.fullName(), Ion::Storage::seqExtension, strlen(Ion::Storage::seqExtension)));
|
||||||
|
return Sequence(record).layout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,22 +46,26 @@ Context::SymbolAbstractType GlobalContext::expressionTypeForIdentifier(const cha
|
|||||||
const char * extension = Ion::Storage::sharedStorage()->extensionOfRecordBaseNamedWithExtensions(identifier, length, k_extensions, k_numberOfExtensions);
|
const char * extension = Ion::Storage::sharedStorage()->extensionOfRecordBaseNamedWithExtensions(identifier, length, k_extensions, k_numberOfExtensions);
|
||||||
if (extension == nullptr) {
|
if (extension == nullptr) {
|
||||||
return Context::SymbolAbstractType::None;
|
return Context::SymbolAbstractType::None;
|
||||||
|
} else if (extension == Ion::Storage::expExtension) {
|
||||||
|
return Context::SymbolAbstractType::Symbol;
|
||||||
|
} else if (extension == Ion::Storage::funcExtension) {
|
||||||
|
return Context::SymbolAbstractType::Function;
|
||||||
|
} else {
|
||||||
|
assert(extension == Ion::Storage::seqExtension);
|
||||||
|
return Context::SymbolAbstractType::Sequence;
|
||||||
}
|
}
|
||||||
assert(k_numberOfExtensions == 2);
|
|
||||||
assert(extension == Ion::Storage::expExtension || extension == Ion::Storage::funcExtension);
|
|
||||||
return extension == Ion::Storage::expExtension ? Context::SymbolAbstractType::Symbol : Context::SymbolAbstractType::Function;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Expression GlobalContext::expressionForSymbolAbstract(const SymbolAbstract & symbol, bool clone) {
|
const Expression GlobalContext::expressionForSymbolAbstract(const SymbolAbstract & symbol, bool clone) {
|
||||||
Ion::Storage::Record r = SymbolAbstractRecordWithBaseName(symbol.name());
|
Ion::Storage::Record r = SymbolAbstractRecordWithBaseName(symbol.name());
|
||||||
return ExpressionForSymbolAndRecord(symbol, r);
|
return ExpressionForSymbolAndRecord(symbol, r, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlobalContext::setExpressionForSymbolAbstract(const Expression & expression, const SymbolAbstract & symbol) {
|
void GlobalContext::setExpressionForSymbolAbstract(const Expression & expression, const SymbolAbstract & symbol) {
|
||||||
/* If the new expression contains the symbol, replace it because it will be
|
/* If the new expression contains the symbol, replace it because it will be
|
||||||
* destroyed afterwards (to be able to do A+2->A) */
|
* destroyed afterwards (to be able to do A+2->A) */
|
||||||
Ion::Storage::Record record = SymbolAbstractRecordWithBaseName(symbol.name());
|
Ion::Storage::Record record = SymbolAbstractRecordWithBaseName(symbol.name());
|
||||||
Expression e = ExpressionForSymbolAndRecord(symbol, record);
|
Expression e = ExpressionForSymbolAndRecord(symbol, record, this);
|
||||||
if (e.isUninitialized()) {
|
if (e.isUninitialized()) {
|
||||||
e = Undefined::Builder();
|
e = Undefined::Builder();
|
||||||
}
|
}
|
||||||
@@ -69,12 +83,14 @@ void GlobalContext::setExpressionForSymbolAbstract(const Expression & expression
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Expression GlobalContext::ExpressionForSymbolAndRecord(const SymbolAbstract & symbol, Ion::Storage::Record r) {
|
const Expression GlobalContext::ExpressionForSymbolAndRecord(const SymbolAbstract & symbol, Ion::Storage::Record r, Context * ctx) {
|
||||||
if (symbol.type() == ExpressionNode::Type::Symbol) {
|
if (symbol.type() == ExpressionNode::Type::Symbol) {
|
||||||
return ExpressionForActualSymbol(r);
|
return ExpressionForActualSymbol(r);
|
||||||
|
} else if (symbol.type() == ExpressionNode::Type::Function) {
|
||||||
|
return ExpressionForFunction(symbol, r);
|
||||||
}
|
}
|
||||||
assert(symbol.type() == ExpressionNode::Type::Function);
|
assert(symbol.type() == ExpressionNode::Type::Sequence);
|
||||||
return ExpressionForFunction(symbol, r);
|
return ExpressionForSequence(symbol, r, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Expression GlobalContext::ExpressionForActualSymbol(Ion::Storage::Record r) {
|
const Expression GlobalContext::ExpressionForActualSymbol(Ion::Storage::Record r) {
|
||||||
@@ -99,6 +115,22 @@ const Expression GlobalContext::ExpressionForFunction(const SymbolAbstract & sym
|
|||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Expression GlobalContext::ExpressionForSequence(const SymbolAbstract & symbol, Ion::Storage::Record r, Context * ctx) {
|
||||||
|
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<float>(symbol.childAtIndex(0), ctx);
|
||||||
|
if (std::floor(rank) == rank) {
|
||||||
|
SequenceContext sqctx(ctx, sequenceStore());
|
||||||
|
return Float<double>::Builder(seq.evaluateXYAtParameter(rank, &sqctx).x2());
|
||||||
|
} else {
|
||||||
|
return Float<double>::Builder(NAN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ion::Storage::Record::ErrorStatus GlobalContext::SetExpressionForActualSymbol(const Expression & expression, const SymbolAbstract & symbol, Ion::Storage::Record previousRecord) {
|
Ion::Storage::Record::ErrorStatus GlobalContext::SetExpressionForActualSymbol(const Expression & expression, const SymbolAbstract & symbol, Ion::Storage::Record previousRecord) {
|
||||||
if (!previousRecord.isNull() && Ion::Storage::FullNameHasExtension(previousRecord.fullName(), Ion::Storage::funcExtension, strlen(Ion::Storage::funcExtension))) {
|
if (!previousRecord.isNull() && Ion::Storage::FullNameHasExtension(previousRecord.fullName(), Ion::Storage::funcExtension, strlen(Ion::Storage::funcExtension))) {
|
||||||
/* A function can overwrite a variable, but a variable cannot be created if
|
/* A function can overwrite a variable, but a variable cannot be created if
|
||||||
|
|||||||
@@ -8,13 +8,14 @@
|
|||||||
#include <poincare/symbol.h>
|
#include <poincare/symbol.h>
|
||||||
#include <ion/storage.h>
|
#include <ion/storage.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include "sequence_store.h"
|
||||||
|
|
||||||
namespace Shared {
|
namespace Shared {
|
||||||
|
|
||||||
class GlobalContext final : public Poincare::Context {
|
class GlobalContext final : public Poincare::Context {
|
||||||
public:
|
public:
|
||||||
static constexpr int k_numberOfExtensions = 2;
|
static constexpr int k_numberOfExtensions = 3;
|
||||||
static constexpr const char * k_extensions[] = {Ion::Storage::expExtension, Ion::Storage::funcExtension};
|
static constexpr const char * k_extensions[] = {Ion::Storage::expExtension, Ion::Storage::funcExtension, Ion::Storage::seqExtension};
|
||||||
|
|
||||||
// Storage information
|
// Storage information
|
||||||
static bool SymbolAbstractNameIsFree(const char * baseName);
|
static bool SymbolAbstractNameIsFree(const char * baseName);
|
||||||
@@ -30,19 +31,19 @@ public:
|
|||||||
SymbolAbstractType expressionTypeForIdentifier(const char * identifier, int length) override;
|
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) override;
|
||||||
void setExpressionForSymbolAbstract(const Poincare::Expression & expression, const Poincare::SymbolAbstract & symbol) override;
|
void setExpressionForSymbolAbstract(const Poincare::Expression & expression, const Poincare::SymbolAbstract & symbol) override;
|
||||||
|
static SequenceStore * sequenceStore();
|
||||||
private:
|
private:
|
||||||
// Expression getters
|
// Expression getters
|
||||||
static const Poincare::Expression ExpressionForSymbolAndRecord(const Poincare::SymbolAbstract & symbol, Ion::Storage::Record r);
|
static const Poincare::Expression ExpressionForSymbolAndRecord(const Poincare::SymbolAbstract & symbol, Ion::Storage::Record r, Context * ctx);
|
||||||
static const Poincare::Expression ExpressionForActualSymbol(Ion::Storage::Record r);
|
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 ExpressionForFunction(const Poincare::SymbolAbstract & symbol, Ion::Storage::Record r);
|
||||||
|
static const Poincare::Expression ExpressionForSequence(const Poincare::SymbolAbstract & symbol, Ion::Storage::Record r, Context * ctx);
|
||||||
// Expression setters
|
// 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 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);
|
static Ion::Storage::Record::ErrorStatus SetExpressionForFunction(const Poincare::Expression & expression, const Poincare::SymbolAbstract & symbol, Ion::Storage::Record previousRecord);
|
||||||
// Record getter
|
// Record getter
|
||||||
static Ion::Storage::Record SymbolAbstractRecordWithBaseName(const char * name);
|
static Ion::Storage::Record SymbolAbstractRecordWithBaseName(const char * name);
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,31 @@ I18n::Message Sequence::parameterMessageName() const {
|
|||||||
return I18n::Message::N;
|
return I18n::Message::N;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Sequence::nameWithArgument(char * buffer, size_t bufferSize) {
|
||||||
|
int seqNameSize = name(buffer, bufferSize);
|
||||||
|
assert(seqNameSize > 0);
|
||||||
|
size_t result = seqNameSize;
|
||||||
|
assert(result <= bufferSize);
|
||||||
|
buffer[result++] = '(';
|
||||||
|
assert(result <= bufferSize);
|
||||||
|
assert(UTF8Decoder::CharSizeOfCodePoint(symbol()) <= 2);
|
||||||
|
result += UTF8Decoder::CodePointToChars(symbol(), buffer+result, bufferSize-result);
|
||||||
|
assert(result <= bufferSize);
|
||||||
|
switch (type())
|
||||||
|
{
|
||||||
|
case Type::Explicit:
|
||||||
|
result += strlcpy(buffer+result, ")", bufferSize-result);
|
||||||
|
break;
|
||||||
|
case Type::SingleRecurrence:
|
||||||
|
result += strlcpy(buffer+result, "+1)", bufferSize-result);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result += strlcpy(buffer+result, "+2)", bufferSize-result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void Sequence::tidy() {
|
void Sequence::tidy() {
|
||||||
m_definition.tidyName();
|
m_definition.tidyName();
|
||||||
Function::tidy(); // m_definitionName.tidy()
|
Function::tidy(); // m_definitionName.tidy()
|
||||||
@@ -111,7 +136,7 @@ T Sequence::templatedApproximateAtAbscissa(T x, SequenceContext * sqctx) const {
|
|||||||
T n = std::round(x);
|
T n = std::round(x);
|
||||||
int sequenceIndex = SequenceStore::sequenceIndexForName(fullName()[0]);
|
int sequenceIndex = SequenceStore::sequenceIndexForName(fullName()[0]);
|
||||||
if (sqctx->iterateUntilRank<T>(n)) {
|
if (sqctx->iterateUntilRank<T>(n)) {
|
||||||
return sqctx->valueOfSequenceAtPreviousRank<T>(sequenceIndex, 0);
|
return sqctx->valueOfCommonRankSequenceAtPreviousRank<T>(sequenceIndex, 0);
|
||||||
}
|
}
|
||||||
return NAN;
|
return NAN;
|
||||||
}
|
}
|
||||||
@@ -122,20 +147,19 @@ T Sequence::valueAtRank(int n, SequenceContext *sqctx) {
|
|||||||
return NAN;
|
return NAN;
|
||||||
}
|
}
|
||||||
int sequenceIndex = SequenceStore::sequenceIndexForName(fullName()[0]);
|
int sequenceIndex = SequenceStore::sequenceIndexForName(fullName()[0]);
|
||||||
if (sqctx->independantSequenceRank<T>(sequenceIndex) > n || sqctx->independantSequenceRank<T>(sequenceIndex) < 0) {
|
if (sqctx->independentSequenceRank<T>(sequenceIndex) > n || sqctx->independentSequenceRank<T>(sequenceIndex) < 0) {
|
||||||
// Reset cache indexes and cache values
|
// Reset cache indexes and cache values
|
||||||
sqctx->setIndependantSequenceRank<T>(-1, sequenceIndex);
|
sqctx->setIndependentSequenceRank<T>(-1, sequenceIndex);
|
||||||
for (int i = 0 ; i < MaxRecurrenceDepth+1; i++) {
|
for (int i = 0 ; i < MaxRecurrenceDepth+1; i++) {
|
||||||
sqctx->setIndependantSequenceValue(NAN, sequenceIndex, i);
|
sqctx->setIndependentSequenceValue(NAN, sequenceIndex, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
while(sqctx->independentSequenceRank<T>(sequenceIndex) < n) {
|
||||||
while(sqctx->independantSequenceRank<T>(sequenceIndex) < n) {
|
|
||||||
sqctx->stepSequenceAtIndex<T>(sequenceIndex);
|
sqctx->stepSequenceAtIndex<T>(sequenceIndex);
|
||||||
}
|
}
|
||||||
/* In case we have sqctx->independantSequenceRank<T>(sequenceIndex) = n, we can return the
|
/* In case we have sqctx->independentSequenceRank<T>(sequenceIndex) = n, we can return the
|
||||||
* value */
|
* value */
|
||||||
T value = sqctx->independantSequenceValue<T>(sequenceIndex, 0);
|
T value = sqctx->independentSequenceValue<T>(sequenceIndex, 0);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,22 +180,22 @@ T Sequence::approximateToNextRank(int n, SequenceContext * sqctx, int sequenceIn
|
|||||||
|
|
||||||
/* In case we step only one sequence to the next step, the data stored in
|
/* In case we step only one sequence to the next step, the data stored in
|
||||||
* values is not necessarily u(n), u(n-1).... Indeed, since the indexes are
|
* values is not necessarily u(n), u(n-1).... Indeed, since the indexes are
|
||||||
* independant, if the index for u is 3 but the one for v is 5, value will
|
* independent, if the index for u is 3 but the one for v is 5, value will
|
||||||
* hold u(3), u(2), u(1) | v(5), v(4), v(3). Therefore, the calculation will
|
* hold u(3), u(2), u(1) | v(5), v(4), v(3). Therefore, the calculation will
|
||||||
* be wrong if they relay on a symbol such as u(n). To prevent this, we align
|
* be wrong if they relay on a symbol such as u(n). To prevent this, we align
|
||||||
* all the values around the index of the sequence we are stepping. */
|
* all the values around the index of the sequence we are stepping. */
|
||||||
int independantRank = sqctx->independantSequenceRank<T>(sequenceIndex);
|
int independentRank = sqctx->independentSequenceRank<T>(sequenceIndex);
|
||||||
for (int i = 0; i < MaxNumberOfSequences; i++) {
|
for (int i = 0; i < MaxNumberOfSequences; i++) {
|
||||||
if (sequenceIndex != -1 && sqctx->independantSequenceRank<T>(i) != independantRank) {
|
if (sequenceIndex != -1 && sqctx->independentSequenceRank<T>(i) != independentRank) {
|
||||||
int offset = independantRank - sqctx->independantSequenceRank<T>(i);
|
int offset = independentRank - sqctx->independentSequenceRank<T>(i);
|
||||||
if (offset != 0) {
|
if (offset != 0) {
|
||||||
for (int j = MaxRecurrenceDepth; j >= 0; j--) {
|
for (int j = MaxRecurrenceDepth; j >= 0; j--) {
|
||||||
values[i][j] = j-offset < 0 ? NAN : sqctx->independantSequenceValue<T>(i, j-offset);
|
values[i][j] = j-offset < 0 ? NAN : sqctx->independentSequenceValue<T>(i, j-offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int j = 0; j < MaxRecurrenceDepth+1; j++) {
|
for (int j = 0; j < MaxRecurrenceDepth+1; j++) {
|
||||||
values[i][j] = sequenceIndex != -1 ? sqctx->independantSequenceValue<T>(i, j) : sqctx->valueOfSequenceAtPreviousRank<T>(i, j);
|
values[i][j] = sequenceIndex != -1 ? sqctx->independentSequenceValue<T>(i, j) : sqctx->valueOfCommonRankSequenceAtPreviousRank<T>(i, j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,7 +208,7 @@ T Sequence::approximateToNextRank(int n, SequenceContext * sqctx, int sequenceIn
|
|||||||
symbols[i][j] = Symbol::Builder(name[j], strlen(name[j]));
|
symbols[i][j] = Symbol::Builder(name[j], strlen(name[j]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ctx.setNValue(n);
|
||||||
switch (type()) {
|
switch (type()) {
|
||||||
case Type::Explicit:
|
case Type::Explicit:
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#ifndef SEQUENCE_SEQUENCE_H
|
#ifndef APPS_SHARED_SEQUENCE_H
|
||||||
#define SEQUENCE_SEQUENCE_H
|
#define APPS_SHARED_SEQUENCE_H
|
||||||
|
|
||||||
#include "../shared/function.h"
|
#include "../shared/function.h"
|
||||||
#include "sequence_context.h"
|
#include "sequence_context.h"
|
||||||
@@ -29,6 +29,7 @@ public:
|
|||||||
}
|
}
|
||||||
I18n::Message parameterMessageName() const override;
|
I18n::Message parameterMessageName() const override;
|
||||||
CodePoint symbol() const override { return 'n'; }
|
CodePoint symbol() const override { return 'n'; }
|
||||||
|
int nameWithArgument(char * buffer, size_t bufferSize) override;
|
||||||
void tidy() override;
|
void tidy() override;
|
||||||
// MetaData getters
|
// MetaData getters
|
||||||
Type type() const;
|
Type type() const;
|
||||||
|
|||||||
@@ -12,13 +12,13 @@ template<typename T>
|
|||||||
TemplatedSequenceContext<T>::TemplatedSequenceContext() :
|
TemplatedSequenceContext<T>::TemplatedSequenceContext() :
|
||||||
m_commonRank(-1),
|
m_commonRank(-1),
|
||||||
m_commonRankValues{{NAN, NAN, NAN}, {NAN, NAN, NAN}, {NAN, NAN, NAN}},
|
m_commonRankValues{{NAN, NAN, NAN}, {NAN, NAN, NAN}, {NAN, NAN, NAN}},
|
||||||
m_independantRanks{-1, -1, -1},
|
m_independentRanks{-1, -1, -1},
|
||||||
m_independantRankValues{{NAN, NAN, NAN}, {NAN, NAN, NAN}, {NAN, NAN, NAN}}
|
m_independentRankValues{{NAN, NAN, NAN}, {NAN, NAN, NAN}, {NAN, NAN, NAN}}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T TemplatedSequenceContext<T>::valueOfSequenceAtPreviousRank(int sequenceIndex, int rank) const {
|
T TemplatedSequenceContext<T>::valueOfCommonRankSequenceAtPreviousRank(int sequenceIndex, int rank) const {
|
||||||
return m_commonRankValues[sequenceIndex][rank];
|
return m_commonRankValues[sequenceIndex][rank];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,11 +26,11 @@ template<typename T>
|
|||||||
void TemplatedSequenceContext<T>::resetCache() {
|
void TemplatedSequenceContext<T>::resetCache() {
|
||||||
/* We only need to reset the ranks. Indeed, when we compute the values of the
|
/* We only need to reset the ranks. Indeed, when we compute the values of the
|
||||||
* sequences, we use ranks as memoization indexes. Therefore, we know that the
|
* sequences, we use ranks as memoization indexes. Therefore, we know that the
|
||||||
* values stored in m_commomValues and m_independantRankValues are dirty
|
* values stored in m_commomValues and m_independentRankValues are dirty
|
||||||
* and do not use them. */
|
* and do not use them. */
|
||||||
m_commonRank = -1;
|
m_commonRank = -1;
|
||||||
for (int i = 0; i < MaxNumberOfSequences; i ++) {
|
for (int i = 0; i < MaxNumberOfSequences; i ++) {
|
||||||
m_independantRanks[i] = -1;
|
m_independentRanks[i] = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ void TemplatedSequenceContext<T>::step(SequenceContext * sqctx, int sequenceInde
|
|||||||
if (stepMultipleSequences) {
|
if (stepMultipleSequences) {
|
||||||
m_commonRank++;
|
m_commonRank++;
|
||||||
} else {
|
} else {
|
||||||
setIndependantSequenceRank(independantSequenceRank(sequenceIndex) + 1, sequenceIndex);
|
setIndependentSequenceRank(independentSequenceRank(sequenceIndex) + 1, sequenceIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then we shift the values stored in the arrays
|
// Then we shift the values stored in the arrays
|
||||||
@@ -69,8 +69,8 @@ void TemplatedSequenceContext<T>::step(SequenceContext * sqctx, int sequenceInde
|
|||||||
} else {
|
} else {
|
||||||
start = sequenceIndex;
|
start = sequenceIndex;
|
||||||
stop = sequenceIndex + 1;
|
stop = sequenceIndex + 1;
|
||||||
sequenceArray = reinterpret_cast<T*>(&m_independantRankValues);
|
sequenceArray = reinterpret_cast<T*>(&m_independentRankValues);
|
||||||
rank = independantSequenceRank(sequenceIndex);
|
rank = independentSequenceRank(sequenceIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = start; i < stop; i++) {
|
for (int i = start; i < stop; i++) {
|
||||||
@@ -107,7 +107,7 @@ void TemplatedSequenceContext<T>::step(SequenceContext * sqctx, int sequenceInde
|
|||||||
T * pointerToUpdate = sequenceArray + i * (MaxRecurrenceDepth + 1);
|
T * pointerToUpdate = sequenceArray + i * (MaxRecurrenceDepth + 1);
|
||||||
if (std::isnan(*(pointerToUpdate))) {
|
if (std::isnan(*(pointerToUpdate))) {
|
||||||
int j = stepMultipleSequences ? i : 0;
|
int j = stepMultipleSequences ? i : 0;
|
||||||
*(pointerToUpdate) = sequences[j] ? sequences[j]->template approximateToNextRank<T>(rank, sqctx, sequenceIndex) : NAN;
|
*pointerToUpdate = sequences[j] ? sequences[j]->template approximateToNextRank<T>(rank, sqctx, sequenceIndex) : NAN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#ifndef SEQUENCE_SEQUENCE_CONTEXT_H
|
#ifndef APPS_SHARED_SEQUENCE_CONTEXT_H
|
||||||
#define SEQUENCE_SEQUENCE_CONTEXT_H
|
#define APPS_SHARED_SEQUENCE_CONTEXT_H
|
||||||
|
|
||||||
#include <poincare/context_with_parent.h>
|
#include <poincare/context_with_parent.h>
|
||||||
#include <poincare/expression.h>
|
#include <poincare/expression.h>
|
||||||
@@ -17,14 +17,14 @@ template<typename T>
|
|||||||
class TemplatedSequenceContext {
|
class TemplatedSequenceContext {
|
||||||
public:
|
public:
|
||||||
TemplatedSequenceContext();
|
TemplatedSequenceContext();
|
||||||
T valueOfSequenceAtPreviousRank(int sequenceIndex, int rank) const;
|
T valueOfCommonRankSequenceAtPreviousRank(int sequenceIndex, int rank) const;
|
||||||
void resetCache();
|
void resetCache();
|
||||||
bool iterateUntilRank(int n, SequenceStore * sequenceStore, SequenceContext * sqctx);
|
bool iterateUntilRank(int n, SequenceStore * sequenceStore, SequenceContext * sqctx);
|
||||||
|
|
||||||
int independantSequenceRank(int sequenceIndex) { return m_independantRanks[sequenceIndex]; }
|
int independentSequenceRank(int sequenceIndex) { return m_independentRanks[sequenceIndex]; }
|
||||||
void setIndependantSequenceRank(int rank, int sequenceIndex) { m_independantRanks[sequenceIndex] = rank; }
|
void setIndependentSequenceRank(int rank, int sequenceIndex) { m_independentRanks[sequenceIndex] = rank; }
|
||||||
T independantSequenceValue(int sequenceIndex, int depth) { return m_independantRankValues[sequenceIndex][depth]; }
|
T independentSequenceValue(int sequenceIndex, int depth) { return m_independentRankValues[sequenceIndex][depth]; }
|
||||||
void setIndependantSequenceValue(T value, int sequenceIndex, int depth) { m_independantRankValues[sequenceIndex][depth] = value; }
|
void setIndependentSequenceValue(T value, int sequenceIndex, int depth) { m_independentRankValues[sequenceIndex][depth] = value; }
|
||||||
void step(SequenceContext * sqctx, int sequenceIndex = -1);
|
void step(SequenceContext * sqctx, int sequenceIndex = -1);
|
||||||
private:
|
private:
|
||||||
constexpr static int k_maxRecurrentRank = 10000;
|
constexpr static int k_maxRecurrentRank = 10000;
|
||||||
@@ -41,16 +41,16 @@ private:
|
|||||||
* sequence is defined using a fixed term of another, u(3) for instance, we
|
* sequence is defined using a fixed term of another, u(3) for instance, we
|
||||||
* compute its value through the second type of cache. This way, we do not
|
* compute its value through the second type of cache. This way, we do not
|
||||||
* erase the data stored in the first type of cache and we can compute the
|
* erase the data stored in the first type of cache and we can compute the
|
||||||
* values of each sequence at independant rank. This means that
|
* values of each sequence at independent rank. This means that
|
||||||
* (u(3), v(5), w(10)) can be computed at the same time.
|
* (u(3), v(5), w(10)) can be computed at the same time.
|
||||||
* This cache is therefore used for independant steps of sequences
|
* This cache is therefore used for independent steps of sequences
|
||||||
*/
|
*/
|
||||||
int m_commonRank;
|
int m_commonRank;
|
||||||
T m_commonRankValues[MaxNumberOfSequences][MaxRecurrenceDepth+1];
|
T m_commonRankValues[MaxNumberOfSequences][MaxRecurrenceDepth+1];
|
||||||
|
|
||||||
// Used for fixed computations
|
// Used for fixed computations
|
||||||
int m_independantRanks[MaxNumberOfSequences];
|
int m_independentRanks[MaxNumberOfSequences];
|
||||||
T m_independantRankValues[MaxNumberOfSequences][MaxRecurrenceDepth+1];
|
T m_independentRankValues[MaxNumberOfSequences][MaxRecurrenceDepth+1];
|
||||||
};
|
};
|
||||||
|
|
||||||
class SequenceContext : public Poincare::ContextWithParent {
|
class SequenceContext : public Poincare::ContextWithParent {
|
||||||
@@ -64,8 +64,8 @@ public:
|
|||||||
* context respective methods. Indeed, special chars like n, u(n), u(n+1),
|
* context respective methods. Indeed, special chars like n, u(n), u(n+1),
|
||||||
* v(n), v(n+1) are taken into accound only when evaluating sequences which
|
* v(n), v(n+1) are taken into accound only when evaluating sequences which
|
||||||
* is done in another context. */
|
* is done in another context. */
|
||||||
template<typename T> T valueOfSequenceAtPreviousRank(int sequenceIndex, int rank) {
|
template<typename T> T valueOfCommonRankSequenceAtPreviousRank(int sequenceIndex, int rank) {
|
||||||
return static_cast<TemplatedSequenceContext<T>*>(helper<T>())->valueOfSequenceAtPreviousRank(sequenceIndex, rank);
|
return static_cast<TemplatedSequenceContext<T>*>(helper<T>())->valueOfCommonRankSequenceAtPreviousRank(sequenceIndex, rank);
|
||||||
}
|
}
|
||||||
|
|
||||||
void resetCache() {
|
void resetCache() {
|
||||||
@@ -77,20 +77,20 @@ public:
|
|||||||
return static_cast<TemplatedSequenceContext<T>*>(helper<T>())->iterateUntilRank(n, m_sequenceStore, this);
|
return static_cast<TemplatedSequenceContext<T>*>(helper<T>())->iterateUntilRank(n, m_sequenceStore, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> int independantSequenceRank(int sequenceIndex) {
|
template<typename T> int independentSequenceRank(int sequenceIndex) {
|
||||||
return static_cast<TemplatedSequenceContext<T>*>(helper<T>())->independantSequenceRank(sequenceIndex);
|
return static_cast<TemplatedSequenceContext<T>*>(helper<T>())->independentSequenceRank(sequenceIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> void setIndependantSequenceRank(int rank, int sequenceIndex) {
|
template<typename T> void setIndependentSequenceRank(int rank, int sequenceIndex) {
|
||||||
static_cast<TemplatedSequenceContext<T>*>(helper<T>())->setIndependantSequenceRank(rank, sequenceIndex);
|
static_cast<TemplatedSequenceContext<T>*>(helper<T>())->setIndependentSequenceRank(rank, sequenceIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> T independantSequenceValue(int sequenceIndex, int depth) {
|
template<typename T> T independentSequenceValue(int sequenceIndex, int depth) {
|
||||||
return static_cast<TemplatedSequenceContext<T>*>(helper<T>())->independantSequenceValue(sequenceIndex, depth);
|
return static_cast<TemplatedSequenceContext<T>*>(helper<T>())->independentSequenceValue(sequenceIndex, depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> void setIndependantSequenceValue(T value, int sequenceIndex, int depth) {
|
template<typename T> void setIndependentSequenceValue(T value, int sequenceIndex, int depth) {
|
||||||
static_cast<TemplatedSequenceContext<T>*>(helper<T>())->setIndependantSequenceValue(value, sequenceIndex, depth);
|
static_cast<TemplatedSequenceContext<T>*>(helper<T>())->setIndependentSequenceValue(value, sequenceIndex, depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> void stepSequenceAtIndex(int sequenceIndex) {
|
template<typename T> void stepSequenceAtIndex(int sequenceIndex) {
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
#ifndef SEQUENCE_SEQUENCE_STORE_H
|
#ifndef APPS_SHARED_SEQUENCE_STORE_H
|
||||||
#define SEQUENCE_SEQUENCE_STORE_H
|
#define APPS_SHARED_SEQUENCE_STORE_H
|
||||||
|
|
||||||
#include "../shared/function_store.h"
|
#include "../shared/function_store.h"
|
||||||
#include "../shared/global_context.h"
|
|
||||||
#include "sequence.h"
|
#include "sequence.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <escher.h>
|
#include <escher.h>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#ifndef SEQUENCE_SEQUENCE_TITLE_CELL_H
|
#ifndef APPS_SHARED_SEQUENCE_TITLE_CELL_H
|
||||||
#define SEQUENCE_SEQUENCE_TITLE_CELL_H
|
#define APPS_SHARED_SEQUENCE_TITLE_CELL_H
|
||||||
|
|
||||||
#include "../shared/function_title_cell.h"
|
#include "../shared/function_title_cell.h"
|
||||||
#include <poincare_layouts.h>
|
#include <poincare_layouts.h>
|
||||||
|
|||||||
10
apps/shared/shared_app.cpp
Normal file
10
apps/shared/shared_app.cpp
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#include "shared_app.h"
|
||||||
|
#include "global_context.h"
|
||||||
|
#include <apps/apps_container.h>
|
||||||
|
|
||||||
|
void SharedApp::Snapshot::pack(App * app) {
|
||||||
|
/* Since the sequence store is now accessible from every app, when exiting
|
||||||
|
* any application, we need to tidy it.*/
|
||||||
|
static_cast<Shared::GlobalContext *>(AppsContainer::sharedAppsContainer()->globalContext())->sequenceStore()->tidy();
|
||||||
|
App::Snapshot::pack(app);
|
||||||
|
}
|
||||||
14
apps/shared/shared_app.h
Normal file
14
apps/shared/shared_app.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#ifndef SHARED_APP_H
|
||||||
|
#define SHARED_APP_H
|
||||||
|
|
||||||
|
#include <escher/app.h>
|
||||||
|
|
||||||
|
class SharedApp : public App {
|
||||||
|
public:
|
||||||
|
class Snapshot : public App::Snapshot {
|
||||||
|
public:
|
||||||
|
void pack(App * app) override;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "equation_store.h"
|
#include "equation_store.h"
|
||||||
#include "interval_controller.h"
|
#include "interval_controller.h"
|
||||||
#include "solutions_controller.h"
|
#include "solutions_controller.h"
|
||||||
|
#include "../shared/shared_app.h"
|
||||||
|
|
||||||
namespace Solver {
|
namespace Solver {
|
||||||
|
|
||||||
@@ -18,7 +19,7 @@ public:
|
|||||||
I18n::Message upperName() override;
|
I18n::Message upperName() override;
|
||||||
const Image * icon() override;
|
const Image * icon() override;
|
||||||
};
|
};
|
||||||
class Snapshot : public ::App::Snapshot {
|
class Snapshot : public ::SharedApp::Snapshot {
|
||||||
public:
|
public:
|
||||||
Snapshot();
|
Snapshot();
|
||||||
App * unpack(Container * container) override;
|
App * unpack(Container * container) override;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "store.h"
|
#include "store.h"
|
||||||
#include "store_controller.h"
|
#include "store_controller.h"
|
||||||
#include "../shared/text_field_delegate_app.h"
|
#include "../shared/text_field_delegate_app.h"
|
||||||
|
#include "../shared/shared_app.h"
|
||||||
|
|
||||||
namespace Statistics {
|
namespace Statistics {
|
||||||
|
|
||||||
@@ -19,7 +20,7 @@ public:
|
|||||||
I18n::Message upperName() override;
|
I18n::Message upperName() override;
|
||||||
const Image * icon() override;
|
const Image * icon() override;
|
||||||
};
|
};
|
||||||
class Snapshot : public ::App::Snapshot, public TabViewDataSource {
|
class Snapshot : public ::SharedApp::Snapshot, public TabViewDataSource {
|
||||||
public:
|
public:
|
||||||
Snapshot();
|
Snapshot();
|
||||||
App * unpack(Container * container) override;
|
App * unpack(Container * container) override;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "escher/include/escher/app.h"
|
#include "escher/include/escher/app.h"
|
||||||
#include "usb_connected_controller.h"
|
#include "usb_connected_controller.h"
|
||||||
|
#include "../shared/shared_app.h"
|
||||||
|
|
||||||
namespace USB {
|
namespace USB {
|
||||||
|
|
||||||
@@ -13,7 +14,7 @@ public:
|
|||||||
I18n::Message name() override;
|
I18n::Message name() override;
|
||||||
I18n::Message upperName() override;
|
I18n::Message upperName() override;
|
||||||
};
|
};
|
||||||
class Snapshot : public ::App::Snapshot {
|
class Snapshot : public ::SharedApp::Snapshot {
|
||||||
public:
|
public:
|
||||||
App * unpack(Container * container) override;
|
App * unpack(Container * container) override;
|
||||||
Descriptor * descriptor() override;
|
Descriptor * descriptor() override;
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
Variables = "Variablen"
|
Variables = "Variablen"
|
||||||
Expressions = "Ausdrücke"
|
Expressions = "Ausdrücke"
|
||||||
Functions = "Funktionen"
|
Functions = "Funktionen"
|
||||||
|
Sequences = "Folgen"
|
||||||
EmptyExpressionBox0 = "Sie haben keine Variable definiert."
|
EmptyExpressionBox0 = "Sie haben keine Variable definiert."
|
||||||
EmptyFunctionBox0 = "Sie haben keine Funktion definiert."
|
EmptyFunctionBox0 = "Sie haben keine Funktion definiert."
|
||||||
|
EmptySequenceBox0 = "Sie haben keine Folge definiert."
|
||||||
EmptyExpressionBox1 = "Um eine Variable zu definieren:"
|
EmptyExpressionBox1 = "Um eine Variable zu definieren:"
|
||||||
EmptyFunctionBox1 = "Um eine Funktion zu definieren:"
|
EmptyFunctionBox1 = "Um eine Funktion zu definieren:"
|
||||||
EmptyExpressionBox2 = "Erlaubte Zeichen im Namen:"
|
EmptyExpressionBox2 = "Erlaubte Zeichen im Namen:"
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
Variables = "Variables"
|
Variables = "Variables"
|
||||||
Expressions = "Expressions"
|
Expressions = "Expressions"
|
||||||
Functions = "Functions"
|
Functions = "Functions"
|
||||||
|
Sequences = "Sequences"
|
||||||
EmptyExpressionBox0 = "You have not defined any variables."
|
EmptyExpressionBox0 = "You have not defined any variables."
|
||||||
EmptyFunctionBox0 = "You have not defined any functions."
|
EmptyFunctionBox0 = "You have not defined any functions."
|
||||||
|
EmptySequenceBox0 = "You have not defined any sequences."
|
||||||
EmptyExpressionBox1 = "To define a variable, type:"
|
EmptyExpressionBox1 = "To define a variable, type:"
|
||||||
EmptyFunctionBox1 = "To define a function, type:"
|
EmptyFunctionBox1 = "To define a function, type:"
|
||||||
EmptyExpressionBox2 = "The variable name can contain:"
|
EmptyExpressionBox2 = "The variable name can contain:"
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
Variables = "Variables"
|
Variables = "Variables"
|
||||||
Expressions = "Expresiones"
|
Expressions = "Expresiones"
|
||||||
Functions = "Funciones"
|
Functions = "Funciones"
|
||||||
|
Sequences = "Sucesiones"
|
||||||
EmptyExpressionBox0 = "Ninguna variable definida."
|
EmptyExpressionBox0 = "Ninguna variable definida."
|
||||||
EmptyFunctionBox0 = "Ninguna función definida."
|
EmptyFunctionBox0 = "Ninguna función definida."
|
||||||
|
EmptySequenceBox0 = "Ninguna sucesión definida."
|
||||||
EmptyExpressionBox1 = "Para definir una, teclear :"
|
EmptyExpressionBox1 = "Para definir una, teclear :"
|
||||||
EmptyFunctionBox1 = "Para definir una, teclear :"
|
EmptyFunctionBox1 = "Para definir una, teclear :"
|
||||||
EmptyExpressionBox2 = "El nombre de variable debe"
|
EmptyExpressionBox2 = "El nombre de variable debe"
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
Variables = "Variables"
|
Variables = "Variables"
|
||||||
Expressions = "Expressions"
|
Expressions = "Expressions"
|
||||||
Functions = "Fonctions"
|
Functions = "Fonctions"
|
||||||
|
Sequences = "Suites"
|
||||||
EmptyExpressionBox0 = "Vous n'avez défini aucune variable."
|
EmptyExpressionBox0 = "Vous n'avez défini aucune variable."
|
||||||
EmptyFunctionBox0 = "Vous n'avez défini aucune fonction."
|
EmptyFunctionBox0 = "Vous n'avez défini aucune fonction."
|
||||||
|
EmptySequenceBox0 = "Vous n'avez défini aucune suite."
|
||||||
EmptyExpressionBox1 = "Pour définir une variable, tapez :"
|
EmptyExpressionBox1 = "Pour définir une variable, tapez :"
|
||||||
EmptyFunctionBox1 = "Pour définir une fonction, tapez :"
|
EmptyFunctionBox1 = "Pour définir une fonction, tapez :"
|
||||||
EmptyExpressionBox2 = "Le nom de la variable peut"
|
EmptyExpressionBox2 = "Le nom de la variable peut"
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
Variables = "Variabili"
|
Variables = "Variabili"
|
||||||
Expressions = "Espressioni"
|
Expressions = "Espressioni"
|
||||||
Functions = "Funzioni"
|
Functions = "Funzioni"
|
||||||
|
Sequences = "Successioni"
|
||||||
EmptyExpressionBox0 = "Non avete definito nessuna variabile."
|
EmptyExpressionBox0 = "Non avete definito nessuna variabile."
|
||||||
EmptyFunctionBox0 = "Non avete definito nessuna funzione."
|
EmptyFunctionBox0 = "Non avete definito nessuna funzione."
|
||||||
|
EmptySequenceBox0 = "Non avete definito nessuna successione."
|
||||||
EmptyExpressionBox1 = "Per definire una variabile, digitare :"
|
EmptyExpressionBox1 = "Per definire una variabile, digitare :"
|
||||||
EmptyFunctionBox1 = "Per definire una funzione, digitare :"
|
EmptyFunctionBox1 = "Per definire una funzione, digitare :"
|
||||||
EmptyExpressionBox2 = "Il nome della variabile può"
|
EmptyExpressionBox2 = "Il nome della variabile può"
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
Variables = "Variabelen"
|
Variables = "Variabelen"
|
||||||
Expressions = "Uitdrukkingen"
|
Expressions = "Uitdrukkingen"
|
||||||
Functions = "Functies"
|
Functions = "Functies"
|
||||||
|
Sequences = "Rijen"
|
||||||
EmptyExpressionBox0 = "Je hebt geen variabelen gedefinieerd."
|
EmptyExpressionBox0 = "Je hebt geen variabelen gedefinieerd."
|
||||||
EmptyFunctionBox0 = "Je hebt geen functies gedefinieerd."
|
EmptyFunctionBox0 = "Je hebt geen functies gedefinieerd."
|
||||||
|
EmptySequenceBox0 = "Je hebt geen rij gedefinieerd."
|
||||||
EmptyExpressionBox1 = "Om een variabele to definiëren, typ:"
|
EmptyExpressionBox1 = "Om een variabele to definiëren, typ:"
|
||||||
EmptyFunctionBox1 = "Om een functie to definiëren, typ:"
|
EmptyFunctionBox1 = "Om een functie to definiëren, typ:"
|
||||||
EmptyExpressionBox2 = "De naam van de variabele kan bevatten:"
|
EmptyExpressionBox2 = "De naam van de variabele kan bevatten:"
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
Variables = "Variáveis"
|
Variables = "Variáveis"
|
||||||
Expressions = "Expressões"
|
Expressions = "Expressões"
|
||||||
Functions = "Funções"
|
Functions = "Funções"
|
||||||
|
Sequences = "Sequências"
|
||||||
EmptyExpressionBox0 = "Nenhuma variável definida."
|
EmptyExpressionBox0 = "Nenhuma variável definida."
|
||||||
EmptyFunctionBox0 = "Nenhuma função definida."
|
EmptyFunctionBox0 = "Nenhuma função definida."
|
||||||
|
EmptySequenceBox0 = "Nenhuma sequência definida."
|
||||||
EmptyExpressionBox1 = "Para definir uma, digite :"
|
EmptyExpressionBox1 = "Para definir uma, digite :"
|
||||||
EmptyFunctionBox1 = "Para definir uma, digite :"
|
EmptyFunctionBox1 = "Para definir uma, digite :"
|
||||||
EmptyExpressionBox2 = "O nome da variável pode conter:"
|
EmptyExpressionBox2 = "O nome da variável pode conter:"
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public:
|
|||||||
class Snapshot {
|
class Snapshot {
|
||||||
public:
|
public:
|
||||||
virtual App * unpack(Container * container) = 0;
|
virtual App * unpack(Container * container) = 0;
|
||||||
void pack(App * app);
|
virtual void pack(App * app);
|
||||||
/* reset all instances to their initial values */
|
/* reset all instances to their initial values */
|
||||||
virtual void reset() {}
|
virtual void reset() {}
|
||||||
virtual void storageDidChangeForRecord(Ion::Storage::Record) {}
|
virtual void storageDidChangeForRecord(Ion::Storage::Record) {}
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ class Expression : public TreeHandle {
|
|||||||
friend class SubtractionNode;
|
friend class SubtractionNode;
|
||||||
friend class Sum;
|
friend class Sum;
|
||||||
friend class SumAndProduct;
|
friend class SumAndProduct;
|
||||||
|
friend class SumAndProductNode;
|
||||||
friend class Symbol;
|
friend class Symbol;
|
||||||
friend class SymbolAbstractNode;
|
friend class SymbolAbstractNode;
|
||||||
friend class Tangent;
|
friend class Tangent;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ public:
|
|||||||
|
|
||||||
Type type() const override { return Type::Sequence; }
|
Type type() const override { return Type::Sequence; }
|
||||||
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;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char m_name[0];
|
char m_name[0];
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ class SymbolAbstract : public Expression {
|
|||||||
friend class Symbol;
|
friend class Symbol;
|
||||||
friend class SymbolNode;
|
friend class SymbolNode;
|
||||||
friend class SymbolAbstractNode;
|
friend class SymbolAbstractNode;
|
||||||
|
friend class SumAndProductNode;
|
||||||
public:
|
public:
|
||||||
const char * name() const { return node()->name(); }
|
const char * name() const { return node()->name(); }
|
||||||
bool hasSameNameAs(const SymbolAbstract & other) const;
|
bool hasSameNameAs(const SymbolAbstract & other) const;
|
||||||
|
|||||||
@@ -416,13 +416,9 @@ void Parser::parseSequence(Expression & leftHandSide, const char name, Token::Ty
|
|||||||
Expression rank = parseUntil(rightDelimiter);
|
Expression rank = parseUntil(rightDelimiter);
|
||||||
if (m_status != Status::Progress) {
|
if (m_status != Status::Progress) {
|
||||||
} else if (!popTokenIfType(rightDelimiter)) {
|
} else if (!popTokenIfType(rightDelimiter)) {
|
||||||
m_status = Status::Error; // Right delimiter missing.
|
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);
|
|
||||||
} else {
|
} 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);
|
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 {
|
Layout SequenceNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const {
|
||||||
assert(name()[0] >= 'u' && name()[0] <= 'w');
|
assert(name()[0] >= 'u' && name()[0] <= 'w');
|
||||||
Layout rank;
|
Layout rank = childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits);
|
||||||
for (char sequenceName = 'u'; sequenceName <= 'w'; sequenceName++) {
|
return HorizontalLayout::Builder(
|
||||||
if (name()[0] == sequenceName) {
|
CodePointLayout::Builder(name()[0]),
|
||||||
// Checking for the sequence children
|
VerticalOffsetLayout::Builder(rank, VerticalOffsetLayoutNode::Position::Subscript));
|
||||||
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()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SequenceNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const {
|
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) {
|
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 {
|
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;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Those two functions will be updated in a comming commit
|
|
||||||
Expression Sequence::shallowReduce(ExpressionNode::ReductionContext reductionContext) {
|
Expression Sequence::shallowReduce(ExpressionNode::ReductionContext reductionContext) {
|
||||||
|
if (reductionContext.symbolicComputation() == ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithUndefined
|
||||||
|
|| childAtIndex(0).isUndefined())
|
||||||
|
{
|
||||||
|
return replaceWithUndefinedInPlace();
|
||||||
|
}
|
||||||
return *this;
|
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) {
|
if (std::isnan(start) || std::isnan(end) || start != (int)start || end != (int)end || end - start > k_maxNumberOfSteps) {
|
||||||
return Complex<T>::Undefined();
|
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());
|
Evaluation<T> result = Complex<T>::Builder((T)emptySumAndProductValue());
|
||||||
for (int i = (int)start; i <= (int)end; i++) {
|
for (int i = (int)start; i <= (int)end; i++) {
|
||||||
if (Expression::ShouldStopProcessing()) {
|
if (Expression::ShouldStopProcessing()) {
|
||||||
return Complex<T>::Undefined();
|
return Complex<T>::Undefined();
|
||||||
}
|
}
|
||||||
nContext.setApproximationForVariable<T>((T)i);
|
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()) {
|
if (result.isUndefined()) {
|
||||||
return Complex<T>::Undefined();
|
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 {
|
int SymbolAbstractNode::simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted, bool ignoreParentheses) const {
|
||||||
assert(type() == e->type());
|
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());
|
return strcmp(name(), static_cast<const SymbolAbstractNode *>(e)->name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
#include <poincare/preferences.h>
|
#include <poincare/preferences.h>
|
||||||
#include <poincare/symbol.h>
|
#include <poincare/symbol.h>
|
||||||
#include <poincare/undefined.h>
|
#include <poincare/undefined.h>
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
namespace Poincare {
|
namespace Poincare {
|
||||||
|
|||||||
Reference in New Issue
Block a user