From 1c306658ceeceecae412ffe2606f5f899be7673b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 Jan 2019 16:00:44 +0100 Subject: [PATCH 001/373] [apps/code] Fix Python environment loading order --- apps/code/menu_controller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/code/menu_controller.cpp b/apps/code/menu_controller.cpp index 73c81f01d..8a159fa3f 100644 --- a/apps/code/menu_controller.cpp +++ b/apps/code/menu_controller.cpp @@ -69,7 +69,7 @@ void MenuController::didBecomeFirstResponder() { assert(m_selectableTableView.selectedRow() < m_scriptStore->numberOfScripts() + 1); app()->setFirstResponder(&m_selectableTableView); #if EPSILON_GETOPT - if (consoleController()->locked() && consoleController()->loadPythonEnvironment()) { + if (consoleController()->locked()) { stackViewController()->push(consoleController()); return; } From 17e7d360097d083b8cafea4c027b610c2548852f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 Jan 2019 16:01:11 +0100 Subject: [PATCH 002/373] [apps/code] If EPSILON_GETOPT, auto import scripts --- apps/code/menu_controller.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/code/menu_controller.cpp b/apps/code/menu_controller.cpp index 8a159fa3f..289fd2947 100644 --- a/apps/code/menu_controller.cpp +++ b/apps/code/menu_controller.cpp @@ -70,6 +70,7 @@ void MenuController::didBecomeFirstResponder() { app()->setFirstResponder(&m_selectableTableView); #if EPSILON_GETOPT if (consoleController()->locked()) { + consoleController()->setAutoImport(true); stackViewController()->push(consoleController()); return; } From f470a990818ac0dea02788a5f3405eee0c6db5d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 26 Nov 2018 17:03:52 +0100 Subject: [PATCH 003/373] [poincare] Multiplications are collapsed in fractions For instance, typing 3*2 the '/' creates the fraction (3*2)/ Before, it would only divide the '2' --- poincare/include/poincare/char_layout.h | 2 ++ poincare/src/char_layout.cpp | 18 ++++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/poincare/include/poincare/char_layout.h b/poincare/include/poincare/char_layout.h index 8d1290d18..aa183db36 100644 --- a/poincare/include/poincare/char_layout.h +++ b/poincare/include/poincare/char_layout.h @@ -28,6 +28,7 @@ public: int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; bool isChar() const override { return true; } bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const override; + bool canBeOmittedMultiplicationLeftFactor() const override; bool canBeOmittedMultiplicationRightFactor() const override; // TreeNode @@ -53,6 +54,7 @@ protected: private: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; + bool isMultiplicationChar() const; char m_char; const KDFont * m_font; }; diff --git a/poincare/src/char_layout.cpp b/poincare/src/char_layout.cpp index b6d42f81d..b49a0d0b9 100644 --- a/poincare/src/char_layout.cpp +++ b/poincare/src/char_layout.cpp @@ -34,9 +34,6 @@ int CharLayoutNode::serialize(char * buffer, int bufferSize, Preferences::PrintF bool CharLayoutNode::isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { if (*numberOfOpenParenthesis <= 0) { if (m_char == '+' - || m_char == '*' - || m_char == Ion::Charset::MultiplicationSign - || m_char == Ion::Charset::MiddleDot || m_char == Ion::Charset::Sto || m_char == '=' || m_char == ',') @@ -65,8 +62,15 @@ bool CharLayoutNode::isCollapsable(int * numberOfOpenParenthesis, bool goingLeft return true; } +bool CharLayoutNode::canBeOmittedMultiplicationLeftFactor() const { + if (isMultiplicationChar()) { + return false; + } + return LayoutNode::canBeOmittedMultiplicationRightFactor(); +} + bool CharLayoutNode::canBeOmittedMultiplicationRightFactor() const { - if (m_char == '!') { + if (m_char == '!' || isMultiplicationChar()) { return false; } return LayoutNode::canBeOmittedMultiplicationRightFactor(); @@ -86,6 +90,12 @@ void CharLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionColor, ctx->drawString(string, p, m_font, expressionColor, backgroundColor); } +bool CharLayoutNode::isMultiplicationChar() const { + return m_char == '*' + || m_char == Ion::Charset::MultiplicationSign + || m_char == Ion::Charset::MiddleDot; +} + CharLayout::CharLayout(char c, const KDFont * font) : Layout(TreePool::sharedPool()->createTreeNode()) { From 55de9ab1111a6c77eda98678ed852a8306b919f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 27 Nov 2018 14:48:12 +0100 Subject: [PATCH 004/373] [apps/sequence] Add '=' after sequence titles --- apps/sequence/sequence.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/apps/sequence/sequence.cpp b/apps/sequence/sequence.cpp index d7bedbfef..d082cfbd9 100644 --- a/apps/sequence/sequence.cpp +++ b/apps/sequence/sequence.cpp @@ -159,19 +159,22 @@ Poincare::Layout Sequence::definitionName() { if (m_type == Type::Explicit) { m_definitionName = HorizontalLayout( CharLayout(name()[0], KDFont::LargeFont), - VerticalOffsetLayout(LayoutHelper::String("n", 1, KDFont::LargeFont), VerticalOffsetLayoutNode::Type::Subscript) + VerticalOffsetLayout(LayoutHelper::String("n", 1, KDFont::LargeFont), VerticalOffsetLayoutNode::Type::Subscript), + CharLayout('=', KDFont::LargeFont) ); } if (m_type == Type::SingleRecurrence) { m_definitionName = HorizontalLayout( CharLayout(name()[0], KDFont::LargeFont), - VerticalOffsetLayout(LayoutHelper::String("n+1", 3, KDFont::LargeFont), VerticalOffsetLayoutNode::Type::Subscript) + VerticalOffsetLayout(LayoutHelper::String("n+1", 3, KDFont::LargeFont), VerticalOffsetLayoutNode::Type::Subscript), + CharLayout('=', KDFont::LargeFont) ); } if (m_type == Type::DoubleRecurrence) { m_definitionName = HorizontalLayout( CharLayout(name()[0], KDFont::LargeFont), - VerticalOffsetLayout(LayoutHelper::String("n+2", 3, KDFont::LargeFont), VerticalOffsetLayoutNode::Type::Subscript) + VerticalOffsetLayout(LayoutHelper::String("n+2", 3, KDFont::LargeFont), VerticalOffsetLayoutNode::Type::Subscript), + CharLayout('=', KDFont::LargeFont) ); } } @@ -188,7 +191,8 @@ Poincare::Layout Sequence::firstInitialConditionName() { Layout indexLayout = LayoutHelper::String(buffer, strlen(buffer), KDFont::LargeFont); m_firstInitialConditionName = HorizontalLayout( CharLayout(name()[0], KDFont::LargeFont), - VerticalOffsetLayout(indexLayout, VerticalOffsetLayoutNode::Type::Subscript) + VerticalOffsetLayout(indexLayout, VerticalOffsetLayoutNode::Type::Subscript), + CharLayout('=', KDFont::LargeFont) ); } return m_firstInitialConditionName; @@ -202,7 +206,8 @@ Poincare::Layout Sequence::secondInitialConditionName() { Layout indexLayout = LayoutHelper::String(buffer, strlen(buffer), KDFont::LargeFont); m_secondInitialConditionName = HorizontalLayout( CharLayout(name()[0], KDFont::LargeFont), - VerticalOffsetLayout(indexLayout, VerticalOffsetLayoutNode::Type::Subscript) + VerticalOffsetLayout(indexLayout, VerticalOffsetLayoutNode::Type::Subscript), + CharLayout('=', KDFont::LargeFont) ); } } From 3b2eaa5dea19ffa331616c99fc30b93f2a86c6de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 28 Nov 2018 11:34:09 +0100 Subject: [PATCH 005/373] [apps/sequence] Sequence title cells are aligned to the right --- apps/sequence/sequence_title_cell.cpp | 10 ++++++++-- apps/sequence/sequence_title_cell.h | 3 +++ apps/shared/function_title_cell.h | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/apps/sequence/sequence_title_cell.cpp b/apps/sequence/sequence_title_cell.cpp index 0bb1d9bb9..9386b0a96 100644 --- a/apps/sequence/sequence_title_cell.cpp +++ b/apps/sequence/sequence_title_cell.cpp @@ -7,11 +7,17 @@ using namespace Poincare; namespace Sequence { SequenceTitleCell::SequenceTitleCell() : - Shared::FunctionTitleCell(), - m_titleTextView(0.5f, 0.5f) + Shared::FunctionTitleCell(Orientation::VerticalIndicator), + m_titleTextView(k_verticalOrientationHorizontalAlignment, 0.5f) { } +void SequenceTitleCell::setOrientation(Orientation orientation) { + float horizontalAlignment = orientation == Orientation::VerticalIndicator ? k_verticalOrientationHorizontalAlignment : k_horizontalOrientationHorizontalAlignment; + m_titleTextView.setAlignment(horizontalAlignment, 0.5f); + FunctionTitleCell::setOrientation(orientation); +} + void SequenceTitleCell::setLayout(Poincare::Layout layout) { m_titleTextView.setLayout(layout); } diff --git a/apps/sequence/sequence_title_cell.h b/apps/sequence/sequence_title_cell.h index ae719a297..262aa8715 100644 --- a/apps/sequence/sequence_title_cell.h +++ b/apps/sequence/sequence_title_cell.h @@ -13,6 +13,7 @@ public: void setEven(bool even) override; void setHighlighted(bool highlight) override; void setColor(KDColor color) override; + void setOrientation(Orientation orientation) override; const KDFont * font() const override { return Poincare::CharLayoutNode::k_defaultFont; } @@ -20,6 +21,8 @@ public: return m_titleTextView.layout(); } private: + static constexpr float k_horizontalOrientationHorizontalAlignment = 0.5f; + static constexpr float k_verticalOrientationHorizontalAlignment = 1.0f; int numberOfSubviews() const override; View * subviewAtIndex(int index) override; void layoutSubviews() override; diff --git a/apps/shared/function_title_cell.h b/apps/shared/function_title_cell.h index 604d44fbc..74ca4d439 100644 --- a/apps/shared/function_title_cell.h +++ b/apps/shared/function_title_cell.h @@ -12,7 +12,7 @@ public: VerticalIndicator }; FunctionTitleCell(Orientation orientation = Orientation::VerticalIndicator); - void setOrientation(Orientation orientation); + virtual void setOrientation(Orientation orientation); virtual void setColor(KDColor color); void drawRect(KDContext * ctx, KDRect rect) const override; virtual const KDFont * font() const = 0; From 17da615a54aa07189df985410894434cc0d5c90d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 28 Nov 2018 11:38:34 +0100 Subject: [PATCH 006/373] [apps/sequence] Don't draw a separator between sequence name and value --- apps/sequence/sequence_title_cell.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sequence/sequence_title_cell.cpp b/apps/sequence/sequence_title_cell.cpp index 9386b0a96..5c2eed39f 100644 --- a/apps/sequence/sequence_title_cell.cpp +++ b/apps/sequence/sequence_title_cell.cpp @@ -49,7 +49,7 @@ View * SequenceTitleCell::subviewAtIndex(int index) { void SequenceTitleCell::layoutSubviews() { KDRect textFrame(0, k_colorIndicatorThickness, bounds().width(), bounds().height() - k_colorIndicatorThickness); if (m_orientation == Orientation::VerticalIndicator){ - textFrame = KDRect(k_colorIndicatorThickness, 0, bounds().width() - k_colorIndicatorThickness-k_separatorThickness, bounds().height()-k_separatorThickness); + textFrame = KDRect(k_colorIndicatorThickness, 0, bounds().width() - k_colorIndicatorThickness, bounds().height()-k_separatorThickness); } m_titleTextView.setFrame(textFrame); } From d3cae9d1aae0c9519a221c838fb810452dff996c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 28 Nov 2018 14:17:58 +0100 Subject: [PATCH 007/373] [apps/sequence] Harmonize row height in sequence list --- apps/sequence/list/list_controller.cpp | 5 +++-- apps/sequence/list/list_controller.h | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/sequence/list/list_controller.cpp b/apps/sequence/list/list_controller.cpp index 83e3c88b9..d73ddf45e 100644 --- a/apps/sequence/list/list_controller.cpp +++ b/apps/sequence/list/list_controller.cpp @@ -57,11 +57,12 @@ int ListController::numberOfExpressionRows() { }; KDCoordinate ListController::expressionRowHeight(int j) { + KDCoordinate defaultHeight = Metric::StoreRowHeight; if (m_sequenceStore->numberOfModels() < m_sequenceStore->maxNumberOfModels() && j == numberOfRows() - 1) { - return Metric::StoreRowHeight; + // Add sequence row + return defaultHeight; } Sequence * sequence = m_sequenceStore->modelAtIndex(modelIndexForRow(j)); - KDCoordinate defaultHeight = 2*k_expressionCellVerticalMargin + (sequence->type() == Sequence::Type::Explicit ? Metric::StoreRowHeight : k_emptySubRowHeight); Layout layout = sequence->layout(); if (sequenceDefinitionForRow(j) == 1) { layout = sequence->firstInitialConditionLayout(); diff --git a/apps/sequence/list/list_controller.h b/apps/sequence/list/list_controller.h index 0b8453a19..316dbc14a 100644 --- a/apps/sequence/list/list_controller.h +++ b/apps/sequence/list/list_controller.h @@ -44,7 +44,6 @@ private: void reinitExpression(Shared::ExpressionModel * model) override; void editExpression(Shared::ExpressionModel * model, Ion::Events::Event event) override; bool removeModelRow(Shared::ExpressionModel * model) override; - static constexpr KDCoordinate k_emptySubRowHeight = 30; constexpr static int k_maxNumberOfRows = 3*MaxNumberOfSequences; SequenceStore * m_sequenceStore; SequenceTitleCell m_sequenceTitleCells[k_maxNumberOfRows]; From 11db7d52579930799aa6c63ad478f6ad66353661 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 28 Nov 2018 14:19:01 +0100 Subject: [PATCH 008/373] [apps/sequence] Remove equal char in sequence parameters --- apps/sequence/list/list_controller.cpp | 2 +- apps/sequence/sequence.cpp | 58 +++++++++++++++----------- apps/sequence/sequence.h | 3 +- 3 files changed, 36 insertions(+), 27 deletions(-) diff --git a/apps/sequence/list/list_controller.cpp b/apps/sequence/list/list_controller.cpp index d73ddf45e..81f7888c7 100644 --- a/apps/sequence/list/list_controller.cpp +++ b/apps/sequence/list/list_controller.cpp @@ -195,7 +195,7 @@ void ListController::willDisplayTitleCellAtIndex(HighlightCell * cell, int j) { SequenceTitleCell * myCell = (SequenceTitleCell *)cell; Sequence * sequence = m_sequenceStore->modelAtIndex(modelIndexForRow(j)); if (sequenceDefinitionForRow(j) == 0) { - myCell->setLayout(sequence->definitionName()); + myCell->setLayout(sequence->definitionNameWithEqual()); } if (sequenceDefinitionForRow(j) == 1) { myCell->setLayout(sequence->firstInitialConditionName()); diff --git a/apps/sequence/sequence.cpp b/apps/sequence/sequence.cpp index d082cfbd9..675e9bad9 100644 --- a/apps/sequence/sequence.cpp +++ b/apps/sequence/sequence.cpp @@ -24,7 +24,7 @@ Sequence::Sequence(const char * text, KDColor color) : m_firstInitialConditionLayout(), m_secondInitialConditionLayout(), m_nameLayout(), - m_definitionName(), + m_definitionNameWithEqual(), m_firstInitialConditionName(), m_secondInitialConditionName(), m_initialRank(0) @@ -155,30 +155,38 @@ Poincare::Layout Sequence::nameLayout() { } Poincare::Layout Sequence::definitionName() { - if (m_definitionName.isUninitialized()) { - if (m_type == Type::Explicit) { - m_definitionName = HorizontalLayout( - CharLayout(name()[0], KDFont::LargeFont), - VerticalOffsetLayout(LayoutHelper::String("n", 1, KDFont::LargeFont), VerticalOffsetLayoutNode::Type::Subscript), - CharLayout('=', KDFont::LargeFont) - ); - } - if (m_type == Type::SingleRecurrence) { - m_definitionName = HorizontalLayout( - CharLayout(name()[0], KDFont::LargeFont), - VerticalOffsetLayout(LayoutHelper::String("n+1", 3, KDFont::LargeFont), VerticalOffsetLayoutNode::Type::Subscript), - CharLayout('=', KDFont::LargeFont) - ); - } - if (m_type == Type::DoubleRecurrence) { - m_definitionName = HorizontalLayout( - CharLayout(name()[0], KDFont::LargeFont), - VerticalOffsetLayout(LayoutHelper::String("n+2", 3, KDFont::LargeFont), VerticalOffsetLayoutNode::Type::Subscript), - CharLayout('=', KDFont::LargeFont) - ); - } + if (m_type == Type::Explicit) { + return HorizontalLayout( + CharLayout(name()[0], k_layoutFont), + VerticalOffsetLayout(LayoutHelper::String("n", 1, k_layoutFont), VerticalOffsetLayoutNode::Type::Subscript)); } - return m_definitionName; + if (m_type == Type::SingleRecurrence) { + return HorizontalLayout( + CharLayout(name()[0], k_layoutFont), + VerticalOffsetLayout(LayoutHelper::String("n+1", 3, k_layoutFont), VerticalOffsetLayoutNode::Type::Subscript)); + } + assert(m_type == Type::DoubleRecurrence); + return HorizontalLayout( + CharLayout(name()[0], k_layoutFont), + VerticalOffsetLayout(LayoutHelper::String("n+2", 3, k_layoutFont), VerticalOffsetLayoutNode::Type::Subscript)); +} + +Poincare::Layout Sequence::definitionNameWithEqual() { + if (m_definitionNameWithEqual.isUninitialized()) { + m_definitionNameWithEqual = definitionName(); + assert(m_definitionNameWithEqual.isHorizontal()); + static_cast(m_definitionNameWithEqual).addChildAtIndex( + CharLayout(' ', KDFont::SmallFont), // Cheat margin + m_definitionNameWithEqual.numberOfChildren(), + m_definitionNameWithEqual.numberOfChildren(), + nullptr); + static_cast(m_definitionNameWithEqual).addChildAtIndex( + CharLayout('=', k_layoutFont), + m_definitionNameWithEqual.numberOfChildren(), + m_definitionNameWithEqual.numberOfChildren(), + nullptr); + } + return m_definitionNameWithEqual; } Poincare::Layout Sequence::firstInitialConditionName() { @@ -321,7 +329,7 @@ void Sequence::tidy() { m_firstInitialConditionExpression = Expression(); m_secondInitialConditionExpression = Expression(); m_nameLayout = Layout(); - m_definitionName = Layout(); + m_definitionNameWithEqual = Layout(); m_firstInitialConditionName = Layout(); m_secondInitialConditionName = Layout(); } diff --git a/apps/sequence/sequence.h b/apps/sequence/sequence.h index 54209258b..7e2f9aefb 100644 --- a/apps/sequence/sequence.h +++ b/apps/sequence/sequence.h @@ -36,6 +36,7 @@ public: int numberOfElements(); Poincare::Layout nameLayout(); Poincare::Layout definitionName(); + Poincare::Layout definitionNameWithEqual(); Poincare::Layout firstInitialConditionName(); Poincare::Layout secondInitialConditionName(); bool isDefined() override; @@ -64,7 +65,7 @@ private: Poincare::Layout m_firstInitialConditionLayout; Poincare::Layout m_secondInitialConditionLayout; Poincare::Layout m_nameLayout; - Poincare::Layout m_definitionName; + Poincare::Layout m_definitionNameWithEqual; Poincare::Layout m_firstInitialConditionName; Poincare::Layout m_secondInitialConditionName; int m_initialRank; From 0a9edf8a434ee3e40084e4051a82fefc306eff31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 28 Nov 2018 14:20:06 +0100 Subject: [PATCH 009/373] [apps/sequence] Add cheat margin between sequence title and equal --- apps/sequence/sequence.cpp | 14 ++++++++------ apps/sequence/sequence.h | 1 + 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/apps/sequence/sequence.cpp b/apps/sequence/sequence.cpp index 675e9bad9..6f47aac39 100644 --- a/apps/sequence/sequence.cpp +++ b/apps/sequence/sequence.cpp @@ -196,11 +196,12 @@ Poincare::Layout Sequence::firstInitialConditionName() { && (m_type == Type::SingleRecurrence || m_type == Type::DoubleRecurrence)) { - Layout indexLayout = LayoutHelper::String(buffer, strlen(buffer), KDFont::LargeFont); + Layout indexLayout = LayoutHelper::String(buffer, strlen(buffer), k_layoutFont); m_firstInitialConditionName = HorizontalLayout( - CharLayout(name()[0], KDFont::LargeFont), + CharLayout(name()[0], k_layoutFont), VerticalOffsetLayout(indexLayout, VerticalOffsetLayoutNode::Type::Subscript), - CharLayout('=', KDFont::LargeFont) + CharLayout(' ', KDFont::SmallFont), // Cheat margin + CharLayout('=', k_layoutFont) ); } return m_firstInitialConditionName; @@ -211,11 +212,12 @@ Poincare::Layout Sequence::secondInitialConditionName() { Integer(m_initialRank+1).serialize(buffer, k_initialRankNumberOfDigits+1); if (m_secondInitialConditionName.isUninitialized()) { if (m_type == Type::DoubleRecurrence) { - Layout indexLayout = LayoutHelper::String(buffer, strlen(buffer), KDFont::LargeFont); + Layout indexLayout = LayoutHelper::String(buffer, strlen(buffer), k_layoutFont); m_secondInitialConditionName = HorizontalLayout( - CharLayout(name()[0], KDFont::LargeFont), + CharLayout(name()[0], k_layoutFont), VerticalOffsetLayout(indexLayout, VerticalOffsetLayoutNode::Type::Subscript), - CharLayout('=', KDFont::LargeFont) + CharLayout(' ', KDFont::SmallFont), // Cheat margin + CharLayout('=', k_layoutFont) ); } } diff --git a/apps/sequence/sequence.h b/apps/sequence/sequence.h index 7e2f9aefb..c99072854 100644 --- a/apps/sequence/sequence.h +++ b/apps/sequence/sequence.h @@ -52,6 +52,7 @@ public: void tidy() override; constexpr static int k_initialRankNumberOfDigits = 3; // m_initialRank is capped by 999 private: + constexpr static const KDFont * k_layoutFont = KDFont::LargeFont; constexpr static double k_maxNumberOfTermsInSum = 100000.0; constexpr static size_t k_dataLengthInBytes = (3*TextField::maxBufferSize()+3)*sizeof(char)+sizeof(int)+1; static_assert((k_dataLengthInBytes & 0x3) == 0, "The sequence data size is not a multiple of 4 bytes (cannot compute crc)"); // Assert that dataLengthInBytes is a multiple of 4 From d87c0669cbf14749b4265ea8f17319aa24912674 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 28 Nov 2018 14:21:41 +0100 Subject: [PATCH 010/373] [apps/sequence] Fix title cell alignments Add margin right of "un=" Align the text vertically so that the equal is vertically centered in the cell. This makes the left and right cell baselines be approximately at the same level for basic sequences definition (un = 1, un=1/2, ...) --- apps/sequence/sequence_title_cell.cpp | 22 +++++++++++++++++----- apps/sequence/sequence_title_cell.h | 4 ++-- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/apps/sequence/sequence_title_cell.cpp b/apps/sequence/sequence_title_cell.cpp index 5c2eed39f..e7e3c6853 100644 --- a/apps/sequence/sequence_title_cell.cpp +++ b/apps/sequence/sequence_title_cell.cpp @@ -8,13 +8,18 @@ namespace Sequence { SequenceTitleCell::SequenceTitleCell() : Shared::FunctionTitleCell(Orientation::VerticalIndicator), - m_titleTextView(k_verticalOrientationHorizontalAlignment, 0.5f) + m_titleTextView(k_verticalOrientationHorizontalAlignment, k_horizontalOrientationAlignment) { } void SequenceTitleCell::setOrientation(Orientation orientation) { - float horizontalAlignment = orientation == Orientation::VerticalIndicator ? k_verticalOrientationHorizontalAlignment : k_horizontalOrientationHorizontalAlignment; - m_titleTextView.setAlignment(horizontalAlignment, 0.5f); + if (orientation == Orientation::VerticalIndicator) { + /* We do not care here about the vertical alignment, it will be set properly + * in layoutSubviews */ + m_titleTextView.setAlignment(k_verticalOrientationHorizontalAlignment, k_verticalOrientationHorizontalAlignment); + } else { + m_titleTextView.setAlignment(k_horizontalOrientationAlignment, k_horizontalOrientationAlignment); + } FunctionTitleCell::setOrientation(orientation); } @@ -48,8 +53,15 @@ View * SequenceTitleCell::subviewAtIndex(int index) { void SequenceTitleCell::layoutSubviews() { KDRect textFrame(0, k_colorIndicatorThickness, bounds().width(), bounds().height() - k_colorIndicatorThickness); - if (m_orientation == Orientation::VerticalIndicator){ - textFrame = KDRect(k_colorIndicatorThickness, 0, bounds().width() - k_colorIndicatorThickness, bounds().height()-k_separatorThickness); + if (m_orientation == Orientation::VerticalIndicator) { + KDCoordinate h = bounds().height()-k_separatorThickness; + textFrame = KDRect(k_colorIndicatorThickness, 0, bounds().width() - k_colorIndicatorThickness, h); + /* We try to align the text so that the equal is vertically centered in the + * cell. This makes the title cell and the definition cell baselines be + * approximately at the same level for basic sequences definitions (un = 1, + * un=1/2, ...). */ + float verticalAlignment = 0.5f + 20.0f/((float)h); // 20.0f is a magic value + m_titleTextView.setAlignment(k_verticalOrientationHorizontalAlignment, verticalAlignment); } m_titleTextView.setFrame(textFrame); } diff --git a/apps/sequence/sequence_title_cell.h b/apps/sequence/sequence_title_cell.h index 262aa8715..db787b793 100644 --- a/apps/sequence/sequence_title_cell.h +++ b/apps/sequence/sequence_title_cell.h @@ -21,8 +21,8 @@ public: return m_titleTextView.layout(); } private: - static constexpr float k_horizontalOrientationHorizontalAlignment = 0.5f; - static constexpr float k_verticalOrientationHorizontalAlignment = 1.0f; + static constexpr float k_horizontalOrientationAlignment = 0.5f; + static constexpr float k_verticalOrientationHorizontalAlignment = 0.9f; int numberOfSubviews() const override; View * subviewAtIndex(int index) override; void layoutSubviews() override; From b8b4d481b521c060a810713a8eeaa80f061496cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 28 Nov 2018 14:29:14 +0100 Subject: [PATCH 011/373] [escher] Use the vertical alignment in ExpressionView --- escher/src/expression_view.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/escher/src/expression_view.cpp b/escher/src/expression_view.cpp index 8203333b5..cb81588bf 100644 --- a/escher/src/expression_view.cpp +++ b/escher/src/expression_view.cpp @@ -51,7 +51,7 @@ KDSize ExpressionView::minimalSizeForOptimalDisplay() const { KDPoint ExpressionView::drawingOrigin() const { KDSize expressionSize = m_layout.layoutSize(); - return KDPoint(m_horizontalMargin + m_horizontalAlignment*(m_frame.width() - 2*m_horizontalMargin - expressionSize.width()), max(0, (m_frame.height() - expressionSize.height())/2)); + return KDPoint(m_horizontalMargin + m_horizontalAlignment*(m_frame.width() - 2*m_horizontalMargin - expressionSize.width()), max(0, m_verticalAlignment*(m_frame.height() - expressionSize.height()))); } KDPoint ExpressionView::absoluteDrawingOrigin() const { From ff1c137fe19123da129e35bff356c0f1dc532df2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 28 Nov 2018 14:53:07 +0100 Subject: [PATCH 012/373] [apps/sequence] Add scroll indicators in sequence list --- apps/shared/function_list_controller.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/shared/function_list_controller.cpp b/apps/shared/function_list_controller.cpp index cc295e35d..bc0790dee 100644 --- a/apps/shared/function_list_controller.cpp +++ b/apps/shared/function_list_controller.cpp @@ -24,7 +24,6 @@ FunctionListController::FunctionListController(Responder * parentResponder, Func { m_selectableTableView.setMargins(0); m_selectableTableView.setVerticalCellOverlap(0); - m_selectableTableView.setShowsIndicators(false); } int FunctionListController::numberOfColumns() { @@ -36,7 +35,7 @@ KDCoordinate FunctionListController::columnWidth(int i) { case 0: return k_functionNameWidth; case 1: - return selectableTableView()->bounds().width()-k_functionNameWidth; + return selectableTableView()->bounds().width() - k_functionNameWidth; default: assert(false); return 0; From 348c5c0dae837b04a288ee6c8fed7adb6f78aa1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 27 Nov 2018 13:28:00 +0100 Subject: [PATCH 013/373] [apps/graph] Add equal after function name --- apps/graph/list/storage_list_controller.cpp | 8 +++++--- apps/graph/list/text_field_function_title_cell.cpp | 2 +- apps/graph/list/text_field_function_title_cell.h | 2 +- apps/shared/storage_function.cpp | 11 +++++++++-- apps/shared/storage_function.h | 4 ++++ 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/apps/graph/list/storage_list_controller.cpp b/apps/graph/list/storage_list_controller.cpp index 6a4f94827..83b4bcd5a 100644 --- a/apps/graph/list/storage_list_controller.cpp +++ b/apps/graph/list/storage_list_controller.cpp @@ -42,14 +42,16 @@ void StorageListController::renameSelectedFunction() { bool StorageListController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) { // Compute the new name size_t textLength = strlen(text); - size_t argumentLength = StorageFunction::k_parenthesedArgumentLength; - constexpr int maxBaseNameSize = StorageFunction::k_maxNameWithArgumentSize; + size_t argumentLength = StorageFunction::k_parenthesedArgumentWithEqualLength; + constexpr int maxBaseNameSize = StorageFunction::k_maxNameWithArgumentAndEqualSize; char baseName[maxBaseNameSize]; if (textLength <= argumentLength) { // The user entered an empty name. Use a default function name. StorageCartesianFunction::DefaultName(baseName, maxBaseNameSize); size_t defaultNameLength = strlen(baseName); + assert(defaultNameLength + Shared::StorageCartesianFunction::k_maxNameWithArgumentAndEqualSize < maxBaseNameSize); strlcpy(baseName + defaultNameLength, StorageFunction::k_parenthesedArgument, maxBaseNameSize - defaultNameLength); + strlcpy(baseName + defaultNameLength + StorageFunction::k_parenthesedArgumentLength, StorageFunction::k_equal, maxBaseNameSize - defaultNameLength - StorageFunction::k_parenthesedArgumentLength); textField->setText(baseName); baseName[defaultNameLength] = 0; } else { @@ -164,7 +166,7 @@ void StorageListController::willDisplayExpressionCellAtIndex(HighlightCell * cel void StorageListController::setFunctionNameInTextField(ExpiringPointer function, TextField * textField) { char bufferName[BufferTextView::k_maxNumberOfChar]; - function->nameWithArgument(bufferName, BufferTextView::k_maxNumberOfChar, modelStore()->symbol()); + function->nameWithArgumentAndEqual(bufferName, BufferTextView::k_maxNumberOfChar, modelStore()->symbol()); textField->setText(bufferName); } diff --git a/apps/graph/list/text_field_function_title_cell.cpp b/apps/graph/list/text_field_function_title_cell.cpp index 4cd6dd5b7..081e921a4 100644 --- a/apps/graph/list/text_field_function_title_cell.cpp +++ b/apps/graph/list/text_field_function_title_cell.cpp @@ -7,7 +7,7 @@ namespace Graph { TextFieldFunctionTitleCell::TextFieldFunctionTitleCell(StorageListController * listController, Orientation orientation, const KDFont * font) : Shared::FunctionTitleCell(orientation), Responder(listController), - m_textField(Shared::StorageFunction::k_parenthesedArgumentLength, this, m_textFieldBuffer, m_textFieldBuffer, k_textFieldBufferSize, nullptr, listController, false, font, 0.5f, 0.5f) + m_textField(Shared::StorageFunction::k_parenthesedArgumentWithEqualLength, this, m_textFieldBuffer, m_textFieldBuffer, k_textFieldBufferSize, nullptr, listController, false, font, 0.5f, 0.5f) {} void TextFieldFunctionTitleCell::setHighlighted(bool highlight) { diff --git a/apps/graph/list/text_field_function_title_cell.h b/apps/graph/list/text_field_function_title_cell.h index f719668d6..29cb36a44 100644 --- a/apps/graph/list/text_field_function_title_cell.h +++ b/apps/graph/list/text_field_function_title_cell.h @@ -41,7 +41,7 @@ public: protected: KDRect textFieldFrame() const; private: - constexpr static int k_textFieldBufferSize = Shared::StorageFunction::k_maxNameWithArgumentSize; + constexpr static int k_textFieldBufferSize = Shared::StorageFunction::k_maxNameWithArgumentAndEqualSize; Shared::TextFieldWithExtension m_textField; char m_textFieldBuffer[k_textFieldBufferSize]; }; diff --git a/apps/shared/storage_function.cpp b/apps/shared/storage_function.cpp index afb572634..80f21dc4d 100644 --- a/apps/shared/storage_function.cpp +++ b/apps/shared/storage_function.cpp @@ -10,6 +10,7 @@ using namespace Poincare; namespace Shared { constexpr char StorageFunction::k_parenthesedArgument[]; +constexpr char StorageFunction::k_equal[]; bool StorageFunction::BaseNameCompliant(const char * baseName, NameNotCompliantError * error) { assert(baseName[0] != 0); @@ -63,11 +64,17 @@ void StorageFunction::setActive(bool active) { int StorageFunction::nameWithArgument(char * buffer, size_t bufferSize, char arg) { const char * functionName = fullName(); size_t baseNameLength = SymbolAbstract::TruncateExtension(buffer, functionName, bufferSize - k_parenthesedArgumentLength); - int result = baseNameLength + strlcpy(&buffer[baseNameLength], k_parenthesedArgument, bufferSize-baseNameLength); + strlcpy(&buffer[baseNameLength], k_parenthesedArgument, bufferSize-baseNameLength); if (baseNameLength+1 < bufferSize - 1) { buffer[baseNameLength+1] = arg; } - return result; + return strlen(buffer); +} + +int StorageFunction::nameWithArgumentAndEqual(char * buffer, size_t bufferSize, char arg) { + int numberOfChars = nameWithArgument(buffer, bufferSize, arg); + strlcpy(&buffer[numberOfChars], k_equal, bufferSize-numberOfChars); + return strlen(buffer); } template diff --git a/apps/shared/storage_function.h b/apps/shared/storage_function.h index 853f2a804..834106071 100644 --- a/apps/shared/storage_function.h +++ b/apps/shared/storage_function.h @@ -17,6 +17,9 @@ public: constexpr static int k_parenthesedArgumentLength = 3; static constexpr char k_parenthesedArgument[k_parenthesedArgumentLength+1] = "(x)"; constexpr static int k_maxNameWithArgumentSize = Poincare::SymbolAbstract::k_maxNameSize + k_parenthesedArgumentLength; /* Function name and null-terminating char + "(x)" */; + constexpr static int k_parenthesedArgumentWithEqualLength = k_parenthesedArgumentLength + 1; + static constexpr char k_equal[] = "="; + constexpr static int k_maxNameWithArgumentAndEqualSize = k_maxNameWithArgumentSize + 1; static bool BaseNameCompliant(const char * baseName, NameNotCompliantError * error = nullptr); // Constructors @@ -29,6 +32,7 @@ public: // Name int nameWithArgument(char * buffer, size_t bufferSize, char arg); + int nameWithArgumentAndEqual(char * buffer, size_t bufferSize, char arg); // Evaluation virtual float evaluateAtAbscissa(float x, Poincare::Context * context) const { From c7e04195c317a70bc6a632f9a83cdce6b721847d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 28 Nov 2018 17:31:34 +0100 Subject: [PATCH 014/373] [apps/graph] Don't draw a separator between function name and value --- apps/graph/list/text_field_function_title_cell.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/apps/graph/list/text_field_function_title_cell.cpp b/apps/graph/list/text_field_function_title_cell.cpp index 081e921a4..dfb60f1bb 100644 --- a/apps/graph/list/text_field_function_title_cell.cpp +++ b/apps/graph/list/text_field_function_title_cell.cpp @@ -55,11 +55,8 @@ void TextFieldFunctionTitleCell::didBecomeFirstResponder() { } KDRect TextFieldFunctionTitleCell::textFieldFrame() const { - KDRect textFrame(0, k_colorIndicatorThickness, bounds().width(), bounds().height() - k_colorIndicatorThickness); - if (m_orientation == Orientation::VerticalIndicator){ - textFrame = KDRect(k_colorIndicatorThickness, 0, bounds().width() - k_colorIndicatorThickness-k_separatorThickness, bounds().height()-k_separatorThickness); - } - return textFrame; + assert(m_orientation == Orientation::VerticalIndicator); + return KDRect(k_colorIndicatorThickness, 0, bounds().width() - k_colorIndicatorThickness, bounds().height()-k_separatorThickness); } } From 9f6ca489ce9c7533f5bf0514300e80588b2f19e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 28 Nov 2018 17:42:37 +0100 Subject: [PATCH 015/373] [apps/graph] Align the function name right --- apps/graph/list/text_field_function_title_cell.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/graph/list/text_field_function_title_cell.cpp b/apps/graph/list/text_field_function_title_cell.cpp index dfb60f1bb..4699c7784 100644 --- a/apps/graph/list/text_field_function_title_cell.cpp +++ b/apps/graph/list/text_field_function_title_cell.cpp @@ -7,7 +7,7 @@ namespace Graph { TextFieldFunctionTitleCell::TextFieldFunctionTitleCell(StorageListController * listController, Orientation orientation, const KDFont * font) : Shared::FunctionTitleCell(orientation), Responder(listController), - m_textField(Shared::StorageFunction::k_parenthesedArgumentWithEqualLength, this, m_textFieldBuffer, m_textFieldBuffer, k_textFieldBufferSize, nullptr, listController, false, font, 0.5f, 0.5f) + m_textField(Shared::StorageFunction::k_parenthesedArgumentWithEqualLength, this, m_textFieldBuffer, m_textFieldBuffer, k_textFieldBufferSize, nullptr, listController, false, font, 1.0f, 0.5f) {} void TextFieldFunctionTitleCell::setHighlighted(bool highlight) { From 8e8d99e8e976884da726ba00d3db3ea126cc93c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 29 Nov 2018 10:33:15 +0100 Subject: [PATCH 016/373] [apps/graph] Do not draw the vertical separator in functions list --- apps/shared/function_title_cell.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/shared/function_title_cell.cpp b/apps/shared/function_title_cell.cpp index a4917d237..f730ad2c9 100644 --- a/apps/shared/function_title_cell.cpp +++ b/apps/shared/function_title_cell.cpp @@ -22,11 +22,9 @@ void FunctionTitleCell::setColor(KDColor color) { void FunctionTitleCell::drawRect(KDContext * ctx, KDRect rect) const { if (m_orientation == Orientation::VerticalIndicator){ ctx->fillRect(KDRect(0, 0, k_colorIndicatorThickness, bounds().height()), m_functionColor); - // Color the vertical separator - ctx->fillRect(KDRect(bounds().width()-k_separatorThickness, 0, k_separatorThickness, bounds().height()), Palette::GreyBright); KDColor separatorColor = m_even ? Palette::WallScreen : KDColorWhite; // Color the horizontal separator - ctx->fillRect(KDRect(k_colorIndicatorThickness, bounds().height()-k_separatorThickness, bounds().width()-k_colorIndicatorThickness-k_separatorThickness, k_separatorThickness), separatorColor); + ctx->fillRect(KDRect(k_colorIndicatorThickness, bounds().height()-k_separatorThickness, bounds().width()-k_colorIndicatorThickness, k_separatorThickness), separatorColor); } else { ctx->fillRect(KDRect(0, 0, bounds().width(), k_colorIndicatorThickness), m_functionColor); } From 9b9a0aa0091e9f1f1341d10aecbcb463202b1066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 29 Nov 2018 10:34:07 +0100 Subject: [PATCH 017/373] [apps/graph] Add scroll indicators in funcitons list --- apps/shared/storage_function_list_controller.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/shared/storage_function_list_controller.cpp b/apps/shared/storage_function_list_controller.cpp index d15d10f8f..188159d1f 100644 --- a/apps/shared/storage_function_list_controller.cpp +++ b/apps/shared/storage_function_list_controller.cpp @@ -27,7 +27,6 @@ StorageFunctionListController::StorageFunctionListController(Responder * parentR { m_selectableTableView.setMargins(0); m_selectableTableView.setVerticalCellOverlap(0); - m_selectableTableView.setShowsIndicators(false); } /* TableViewDataSource */ From 569e0e884e93d4c2a12026aa01eb10e11ecbb0d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 29 Nov 2018 14:58:41 +0100 Subject: [PATCH 018/373] [apps/graph] Memoize baselines in functions list --- apps/graph/list/storage_list_controller.cpp | 11 +++++ apps/graph/list/storage_list_controller.h | 1 + apps/shared/function_title_cell.cpp | 13 +++--- apps/shared/function_title_cell.h | 9 +++- ...orage_expression_model_list_controller.cpp | 43 +++++++++++------- ...storage_expression_model_list_controller.h | 12 ++--- .../storage_function_list_controller.cpp | 45 ++++++++++++++++++- .../shared/storage_function_list_controller.h | 5 +++ 8 files changed, 110 insertions(+), 29 deletions(-) diff --git a/apps/graph/list/storage_list_controller.cpp b/apps/graph/list/storage_list_controller.cpp index 83b4bcd5a..1ccfcaaaa 100644 --- a/apps/graph/list/storage_list_controller.cpp +++ b/apps/graph/list/storage_list_controller.cpp @@ -170,4 +170,15 @@ void StorageListController::setFunctionNameInTextField(ExpiringPointersetText(bufferName); } +KDCoordinate StorageListController::privateBaseline(int j) const { + assert(j>=0 && j((const_cast(&m_selectableTableView))->cellAtLocation(1, j)); + Poincare::Layout layout = cell->layout(); + if (layout.isUninitialized()) { + return -1; + } + return 0.5*(const_cast(this)->rowHeight(j)-layout.layoutSize().height())+layout.baseline(); + +} + } diff --git a/apps/graph/list/storage_list_controller.h b/apps/graph/list/storage_list_controller.h index eabe0c52f..a8c65d9fa 100644 --- a/apps/graph/list/storage_list_controller.h +++ b/apps/graph/list/storage_list_controller.h @@ -33,6 +33,7 @@ private: return static_cast(app()); } void setFunctionNameInTextField(Shared::ExpiringPointer function, TextField * textField); + KDCoordinate privateBaseline(int j) const override; TextFieldFunctionTitleCell m_functionTitleCells[k_maxNumberOfDisplayableRows]; Shared::FunctionExpressionCell m_expressionCells[k_maxNumberOfDisplayableRows]; ListParameterController m_parameterController; diff --git a/apps/shared/function_title_cell.cpp b/apps/shared/function_title_cell.cpp index f730ad2c9..4a94c8649 100644 --- a/apps/shared/function_title_cell.cpp +++ b/apps/shared/function_title_cell.cpp @@ -3,12 +3,6 @@ namespace Shared { -FunctionTitleCell::FunctionTitleCell(Orientation orientation) : - EvenOddCell(), - m_orientation(orientation) -{ -} - void FunctionTitleCell::setOrientation(Orientation orientation) { m_orientation = orientation; reloadCell(); @@ -19,6 +13,13 @@ void FunctionTitleCell::setColor(KDColor color) { reloadCell(); } +void FunctionTitleCell::setBaseline(KDCoordinate baseline) { + if (m_baseline != baseline) { + m_baseline = baseline; + reloadCell(); + } +} + void FunctionTitleCell::drawRect(KDContext * ctx, KDRect rect) const { if (m_orientation == Orientation::VerticalIndicator){ ctx->fillRect(KDRect(0, 0, k_colorIndicatorThickness, bounds().height()), m_functionColor); diff --git a/apps/shared/function_title_cell.h b/apps/shared/function_title_cell.h index 74ca4d439..8fbadb0d5 100644 --- a/apps/shared/function_title_cell.h +++ b/apps/shared/function_title_cell.h @@ -11,15 +11,22 @@ public: HorizontalIndicator, VerticalIndicator }; - FunctionTitleCell(Orientation orientation = Orientation::VerticalIndicator); + FunctionTitleCell(Orientation orientation = Orientation::VerticalIndicator) : + EvenOddCell(), + m_orientation(orientation), + m_baseline(-1), + m_functionColor(KDColorBlack) + {} virtual void setOrientation(Orientation orientation); virtual void setColor(KDColor color); void drawRect(KDContext * ctx, KDRect rect) const override; + void setBaseline(KDCoordinate baseline); virtual const KDFont * font() const = 0; protected: constexpr static KDCoordinate k_separatorThickness = 1; constexpr static KDCoordinate k_colorIndicatorThickness = 2; Orientation m_orientation; + KDCoordinate m_baseline; private: KDColor m_functionColor; }; diff --git a/apps/shared/storage_expression_model_list_controller.cpp b/apps/shared/storage_expression_model_list_controller.cpp index d11522dd1..ff4945be8 100644 --- a/apps/shared/storage_expression_model_list_controller.cpp +++ b/apps/shared/storage_expression_model_list_controller.cpp @@ -15,20 +15,18 @@ StorageExpressionModelListController::StorageExpressionModelListController(Respo } void StorageExpressionModelListController::tableSelectionDidChange(int previousSelectedRow) { - constexpr int currentSelectedMemoizedIndex = k_memoizedCellHeightsCount/2 + 1; // Needs k_memoizedCellHeightsCount to be odd, which is static asserted in the header file + constexpr int currentSelectedMemoizedIndex = k_memoizedCellsCount/2 + 1; // Needs k_memoizedCellsCount to be odd, which is static asserted in the header file int currentSelectedRow = selectedRow(); // The previously selected cell's height might have changed. - m_memoizedCellHeight[currentSelectedMemoizedIndex] = k_resetedMemoizedValue; + resetMemoizationForIndex(currentSelectedMemoizedIndex); // Update m_cumulatedHeightForSelectedIndex if we scrolled one cell up/down if (currentSelectedRow == previousSelectedRow + 1) { /* We selected the cell under the previous cell. Shift the memoized cell * heights. */ - for (int i = 0; i < k_memoizedCellHeightsCount - 1; i++) { - m_memoizedCellHeight[i] = m_memoizedCellHeight[i+1]; - } - m_memoizedCellHeight[k_memoizedCellHeightsCount-1] = k_resetedMemoizedValue; + shiftMemoization(true); + resetMemoizationForIndex(k_memoizedCellsCount-1); // Update m_cumulatedHeightForSelectedIndex if (previousSelectedRow >= 0) { m_cumulatedHeightForSelectedIndex+= memoizedRowHeight(previousSelectedRow); @@ -39,10 +37,8 @@ void StorageExpressionModelListController::tableSelectionDidChange(int previousS } else if (currentSelectedRow == previousSelectedRow - 1) { /* We selected the cell above the previous cell. Shift the memoized cell * heights. */ - for (int i = k_memoizedCellHeightsCount - 1; i > 0; i--) { - m_memoizedCellHeight[i] = m_memoizedCellHeight[i-1]; - } - m_memoizedCellHeight[0] = k_resetedMemoizedValue; + shiftMemoization(false); + resetMemoizationForIndex(0); // Update m_cumulatedHeightForSelectedIndex if (currentSelectedRow >= 0) { m_cumulatedHeightForSelectedIndex-= memoizedRowHeight(currentSelectedRow); @@ -59,7 +55,7 @@ KDCoordinate StorageExpressionModelListController::memoizedRowHeight(int j) { return 0; } int currentSelectedRow = selectedRow(); - constexpr int halfMemoizationCount = k_memoizedCellHeightsCount/2; + constexpr int halfMemoizationCount = k_memoizedCellsCount/2; if (j >= currentSelectedRow - halfMemoizationCount && j <= currentSelectedRow + halfMemoizationCount) { int memoizedIndex = j - (currentSelectedRow - halfMemoizationCount); if (m_memoizedCellHeight[memoizedIndex] == k_resetedMemoizedValue) { @@ -75,7 +71,7 @@ KDCoordinate StorageExpressionModelListController::memoizedCumulatedHeightFromIn return 0; } int currentSelectedRow = selectedRow(); - constexpr int halfMemoizationCount = k_memoizedCellHeightsCount/2; + constexpr int halfMemoizationCount = k_memoizedCellsCount/2; /* If j is not easily computable from the memoized values, compute it the hard * way. */ if (j < currentSelectedRow - halfMemoizationCount || j > currentSelectedRow + halfMemoizationCount) { @@ -210,7 +206,7 @@ void StorageExpressionModelListController::editExpression(Ion::Events::Event eve bool StorageExpressionModelListController::editSelectedRecordWithText(const char * text) { Ion::Storage::Record record = modelStore()->recordAtIndex(modelIndexForRow(selectedRow())); - ExpiringPointer model = modelStore()->modelForRecord(record); + ExpiringPointer model = modelStore()->modelForRecord(record); return (model->setContent(text) == Ion::Storage::Record::ErrorStatus::None); } @@ -224,10 +220,27 @@ bool StorageExpressionModelListController::isAddEmptyRow(int j) { return j == modelStore()->numberOfModels(); } +void StorageExpressionModelListController::resetMemoizationForIndex(int index) { + assert(index >= 0 && index < k_memoizedCellsCount); + m_memoizedCellHeight[index] = k_resetedMemoizedValue; +} + +void StorageExpressionModelListController::shiftMemoization(bool newCellIsUnder) { + if (newCellIsUnder) { + for (int i = 0; i < k_memoizedCellsCount - 1; i++) { + m_memoizedCellHeight[i] = m_memoizedCellHeight[i+1]; + } + } else { + for (int i = k_memoizedCellsCount - 1; i > 0; i--) { + m_memoizedCellHeight[i] = m_memoizedCellHeight[i-1]; + } + } +} + void StorageExpressionModelListController::resetMemoization() { m_cumulatedHeightForSelectedIndex = k_resetedMemoizedValue; - for (int i = 0; i < k_memoizedCellHeightsCount; i++) { - m_memoizedCellHeight[i] = k_resetedMemoizedValue; + for (int i = 0; i < k_memoizedCellsCount; i++) { + resetMemoizationForIndex(i); } } diff --git a/apps/shared/storage_expression_model_list_controller.h b/apps/shared/storage_expression_model_list_controller.h index 1d5b2961b..577b5a930 100644 --- a/apps/shared/storage_expression_model_list_controller.h +++ b/apps/shared/storage_expression_model_list_controller.h @@ -37,7 +37,7 @@ protected: EvenOddMessageTextCell m_addNewModel; protected: // Memoization - static constexpr int k_memoizedCellHeightsCount = 7; + static constexpr int k_memoizedCellsCount = 7; /* We use memoization to speed up indexFromHeight(offset) in the children * classes: if offset is "around" the memoized cumulatedHeightForIndex, we can * compute its value easily by adding/substracting memoized row heights. We @@ -48,18 +48,20 @@ protected: * (ScreenHeight - Metric::TitleBarHeight - Metric::TabHeight - ButtonRowHeight * - currentSelectedRowHeight) / Metric::StoreRowHeight * = (240-18-27-20-50)/50 = 2.5 */ - static_assert(StorageExpressionModelListController::k_memoizedCellHeightsCount % 2 == 1, "StorageExpressionModelListController::k_memoizedCellHeightsCount should be odd."); + static_assert(StorageExpressionModelListController::k_memoizedCellsCount % 2 == 1, "StorageExpressionModelListController::k_memoizedCellsCount should be odd."); /* We memoize values for indexes around the selectedRow index. - * k_memoizedCellHeightsCount needs to be odd to compute things such as: - * constexpr int halfMemoizationCount = k_memoizedCellHeightsCount/2; + * k_memoizedCellsCount needs to be odd to compute things such as: + * constexpr int halfMemoizationCount = k_memoizedCellsCount/2; * if (j < selectedRow - halfMemoizationCount * || j > selectedRow + halfMemoizationCount) { ... } */ + virtual void resetMemoizationForIndex(int index); + virtual void shiftMemoization(bool newCellIsUnder); private: // Memoization static constexpr int k_resetedMemoizedValue = -1; void resetMemoization(); virtual KDCoordinate notMemoizedCumulatedHeightFromIndex(int j) = 0; - KDCoordinate m_memoizedCellHeight[k_memoizedCellHeightsCount]; + KDCoordinate m_memoizedCellHeight[k_memoizedCellsCount]; KDCoordinate m_cumulatedHeightForSelectedIndex; }; diff --git a/apps/shared/storage_function_list_controller.cpp b/apps/shared/storage_function_list_controller.cpp index 188159d1f..bf91cff67 100644 --- a/apps/shared/storage_function_list_controller.cpp +++ b/apps/shared/storage_function_list_controller.cpp @@ -25,6 +25,12 @@ StorageFunctionListController::StorageFunctionListController(Responder * parentR }, this), KDFont::SmallFont, Palette::PurpleBright), m_titlesColumnWidth(k_minTitleColumnWidth) { + /* m_memoizedCellBaseline is not initialized by the call to + * resetMemoizationForIndex in StorageExpressionModelListController's + * constructor, because it is a virtual method in a constructor. */ + for (int i = 0; i < k_memoizedCellsCount; i++) { + m_memoizedCellBaseline[i] = -1; + } m_selectableTableView.setMargins(0); m_selectableTableView.setVerticalCellOverlap(0); } @@ -98,7 +104,7 @@ int StorageFunctionListController::indexFromCumulatedHeight(KDCoordinate offsetY KDCoordinate currentCumulatedHeight = cumulatedHeightFromIndex(currentSelectedRow); if (offsetY > currentCumulatedHeight) { - int iMax = min(k_memoizedCellHeightsCount/2 + 1, rowsCount - currentSelectedRow); + int iMax = min(k_memoizedCellsCount/2 + 1, rowsCount - currentSelectedRow); for (int i = 0; i < iMax; i++) { currentCumulatedHeight+= rowHeight(currentSelectedRow + i); if (offsetY <= currentCumulatedHeight) { @@ -106,7 +112,7 @@ int StorageFunctionListController::indexFromCumulatedHeight(KDCoordinate offsetY } } } else { - int iMax = min(k_memoizedCellHeightsCount/2, currentSelectedRow); + int iMax = min(k_memoizedCellsCount/2, currentSelectedRow); for (int i = 1; i <= iMax; i++) { currentCumulatedHeight-= rowHeight(currentSelectedRow-i); if (offsetY > currentCumulatedHeight) { @@ -313,4 +319,39 @@ KDCoordinate StorageFunctionListController::notMemoizedCumulatedHeightFromIndex( return TableViewDataSource::cumulatedHeightFromIndex(j); } +KDCoordinate StorageFunctionListController::baseline(int j) { + if (j < 0) { + return -1; + } + int currentSelectedRow = selectedRow(); + constexpr int halfMemoizationCount = k_memoizedCellsCount/2; + if (j >= currentSelectedRow - halfMemoizationCount && j <= currentSelectedRow + halfMemoizationCount) { + int memoizedIndex = j - (currentSelectedRow - halfMemoizationCount); + if (m_memoizedCellBaseline[memoizedIndex] < 0) { + m_memoizedCellBaseline[memoizedIndex] = privateBaseline(j); + } + return m_memoizedCellBaseline[memoizedIndex]; + } + return privateBaseline(j); +} + +void StorageFunctionListController::resetMemoizationForIndex(int index) { + assert(index >= 0 && index < k_memoizedCellsCount); + m_memoizedCellBaseline[index] = -1; + StorageExpressionModelListController::resetMemoizationForIndex(index); +} + +void StorageFunctionListController::shiftMemoization(bool newCellIsUnder) { + if (newCellIsUnder) { + for (int i = 0; i < k_memoizedCellsCount - 1; i++) { + m_memoizedCellBaseline[i] = m_memoizedCellBaseline[i+1]; + } + } else { + for (int i = k_memoizedCellsCount - 1; i > 0; i--) { + m_memoizedCellBaseline[i] = m_memoizedCellBaseline[i-1]; + } + } + StorageExpressionModelListController::shiftMemoization(newCellIsUnder); +} + } diff --git a/apps/shared/storage_function_list_controller.h b/apps/shared/storage_function_list_controller.h index c8e21fb30..433be3b12 100644 --- a/apps/shared/storage_function_list_controller.h +++ b/apps/shared/storage_function_list_controller.h @@ -55,6 +55,9 @@ protected: void configureFunction(Ion::Storage::Record record); void computeTitlesColumnWidth(); StorageFunctionStore * modelStore() override; + KDCoordinate baseline(int j); + void resetMemoizationForIndex(int index) override; + void shiftMemoization(bool newCellIsUnder) override; SelectableTableView m_selectableTableView; private: static constexpr KDCoordinate k_minTitleColumnWidth = 65; @@ -69,10 +72,12 @@ private: virtual FunctionTitleCell * titleCells(int index) = 0; virtual HighlightCell * expressionCells(int index) = 0; virtual void willDisplayTitleCellAtIndex(HighlightCell * cell, int j) = 0; + virtual KDCoordinate privateBaseline(int j) const = 0; EvenOddCell m_emptyCell; Button m_plotButton; Button m_valuesButton; KDCoordinate m_titlesColumnWidth; + KDCoordinate m_memoizedCellBaseline[k_memoizedCellsCount]; }; } From 738d21cc2b0157f42d0021a7fce921e4fde246ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 29 Nov 2018 15:02:46 +0100 Subject: [PATCH 019/373] [apps/graph] Align function name and expresion baselines --- apps/graph/list/storage_list_controller.cpp | 2 ++ apps/graph/list/text_field_function_title_cell.cpp | 11 +++++++++-- apps/graph/list/text_field_function_title_cell.h | 1 + apps/shared/function_expression_cell.cpp | 5 ----- apps/shared/function_expression_cell.h | 2 +- escher/include/escher/even_odd_expression_cell.h | 1 + 6 files changed, 14 insertions(+), 8 deletions(-) diff --git a/apps/graph/list/storage_list_controller.cpp b/apps/graph/list/storage_list_controller.cpp index 1ccfcaaaa..60048321c 100644 --- a/apps/graph/list/storage_list_controller.cpp +++ b/apps/graph/list/storage_list_controller.cpp @@ -148,6 +148,8 @@ HighlightCell * StorageListController::expressionCells(int index) { void StorageListController::willDisplayTitleCellAtIndex(HighlightCell * cell, int j) { TextFieldFunctionTitleCell * titleCell = static_cast(cell); + StorageExpressionModelListController::willDisplayExpressionCellAtIndex(m_selectableTableView.cellAtLocation(1, j), j); + titleCell->setBaseline(baseline(j)); if (!titleCell->isEditing()) { ExpiringPointer function = modelStore()->modelForRecord(modelStore()->recordAtIndex(j)); setFunctionNameInTextField(function, titleCell->textField()); diff --git a/apps/graph/list/text_field_function_title_cell.cpp b/apps/graph/list/text_field_function_title_cell.cpp index 4699c7784..061a3e35a 100644 --- a/apps/graph/list/text_field_function_title_cell.cpp +++ b/apps/graph/list/text_field_function_title_cell.cpp @@ -4,10 +4,13 @@ namespace Graph { +static inline float min(float x, float y) { return (xy ? x : y); } + TextFieldFunctionTitleCell::TextFieldFunctionTitleCell(StorageListController * listController, Orientation orientation, const KDFont * font) : Shared::FunctionTitleCell(orientation), Responder(listController), - m_textField(Shared::StorageFunction::k_parenthesedArgumentWithEqualLength, this, m_textFieldBuffer, m_textFieldBuffer, k_textFieldBufferSize, nullptr, listController, false, font, 1.0f, 0.5f) + m_textField(Shared::StorageFunction::k_parenthesedArgumentWithEqualLength, this, m_textFieldBuffer, m_textFieldBuffer, k_textFieldBufferSize, nullptr, listController, false, font, k_horizontalAlignment, 0.5f) {} void TextFieldFunctionTitleCell::setHighlighted(bool highlight) { @@ -45,7 +48,11 @@ void TextFieldFunctionTitleCell::setText(const char * title) { } void TextFieldFunctionTitleCell::layoutSubviews() { - m_textField.setFrame(textFieldFrame()); + KDRect frame = textFieldFrame(); + m_textField.setFrame(frame); + KDCoordinate glyphHeight = font()->glyphSize().height(); + float verticalAlignment = max(0.0f, min(1.0f, m_baseline < 0 ? 0.5f : ((float)(m_baseline - glyphHeight/2))/((float)frame.height()+1-glyphHeight))); + m_textField.setAlignment(k_horizontalAlignment, verticalAlignment); } void TextFieldFunctionTitleCell::didBecomeFirstResponder() { diff --git a/apps/graph/list/text_field_function_title_cell.h b/apps/graph/list/text_field_function_title_cell.h index 29cb36a44..18fa43648 100644 --- a/apps/graph/list/text_field_function_title_cell.h +++ b/apps/graph/list/text_field_function_title_cell.h @@ -41,6 +41,7 @@ public: protected: KDRect textFieldFrame() const; private: + constexpr static float k_horizontalAlignment = 1.0f; constexpr static int k_textFieldBufferSize = Shared::StorageFunction::k_maxNameWithArgumentAndEqualSize; Shared::TextFieldWithExtension m_textField; char m_textFieldBuffer[k_textFieldBufferSize]; diff --git a/apps/shared/function_expression_cell.cpp b/apps/shared/function_expression_cell.cpp index 8b7df31a5..950ccc2a3 100644 --- a/apps/shared/function_expression_cell.cpp +++ b/apps/shared/function_expression_cell.cpp @@ -2,11 +2,6 @@ namespace Shared { -FunctionExpressionCell::FunctionExpressionCell() : - EvenOddExpressionCell() -{ -} - KDSize FunctionExpressionCell::minimalSizeForOptimalDisplay() const { KDSize expressionSize = m_expressionView.minimalSizeForOptimalDisplay(); return KDSize(m_leftMargin + expressionSize.width() + m_rightMargin, expressionSize.height()+k_separatorThickness); diff --git a/apps/shared/function_expression_cell.h b/apps/shared/function_expression_cell.h index 203e3cb82..b35b418f4 100644 --- a/apps/shared/function_expression_cell.h +++ b/apps/shared/function_expression_cell.h @@ -7,7 +7,7 @@ namespace Shared { class FunctionExpressionCell : public EvenOddExpressionCell { public: - FunctionExpressionCell(); + FunctionExpressionCell() : EvenOddExpressionCell() {} KDSize minimalSizeForOptimalDisplay() const override; void drawRect(KDContext * ctx, KDRect rect) const override; void layoutSubviews() override; diff --git a/escher/include/escher/even_odd_expression_cell.h b/escher/include/escher/even_odd_expression_cell.h index 5978cfca8..5a63bfc36 100644 --- a/escher/include/escher/even_odd_expression_cell.h +++ b/escher/include/escher/even_odd_expression_cell.h @@ -17,6 +17,7 @@ public: void setAlignment(float horizontalAlignment, float verticalAlignment) { m_expressionView.setAlignment(horizontalAlignment, verticalAlignment); } void setLeftMargin(KDCoordinate margin); void setRightMargin(KDCoordinate margin); + KDPoint drawingOrigin() const { return m_expressionView.drawingOrigin(); } Poincare::Layout layout() const override { return m_expressionView.layout(); } void drawRect(KDContext * ctx, KDRect rect) const override; protected: From ff33ad3ad1b8f6410235faff2e6ac884421ba1c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 29 Nov 2018 15:41:34 +0100 Subject: [PATCH 020/373] [apps] In FunctionTitleCell, draw the equal separately This way, we can better manage the margins around the equal --- .../list/text_field_function_title_cell.cpp | 7 +------ .../list/text_field_function_title_cell.h | 2 -- apps/shared/function_title_cell.cpp | 20 +++++++++++++++++-- apps/shared/function_title_cell.h | 2 ++ 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/apps/graph/list/text_field_function_title_cell.cpp b/apps/graph/list/text_field_function_title_cell.cpp index 061a3e35a..017f7b762 100644 --- a/apps/graph/list/text_field_function_title_cell.cpp +++ b/apps/graph/list/text_field_function_title_cell.cpp @@ -48,7 +48,7 @@ void TextFieldFunctionTitleCell::setText(const char * title) { } void TextFieldFunctionTitleCell::layoutSubviews() { - KDRect frame = textFieldFrame(); + KDRect frame = subviewFrame(); m_textField.setFrame(frame); KDCoordinate glyphHeight = font()->glyphSize().height(); float verticalAlignment = max(0.0f, min(1.0f, m_baseline < 0 ? 0.5f : ((float)(m_baseline - glyphHeight/2))/((float)frame.height()+1-glyphHeight))); @@ -61,9 +61,4 @@ void TextFieldFunctionTitleCell::didBecomeFirstResponder() { } } -KDRect TextFieldFunctionTitleCell::textFieldFrame() const { - assert(m_orientation == Orientation::VerticalIndicator); - return KDRect(k_colorIndicatorThickness, 0, bounds().width() - k_colorIndicatorThickness, bounds().height()-k_separatorThickness); -} - } diff --git a/apps/graph/list/text_field_function_title_cell.h b/apps/graph/list/text_field_function_title_cell.h index 18fa43648..7dd0ebdbe 100644 --- a/apps/graph/list/text_field_function_title_cell.h +++ b/apps/graph/list/text_field_function_title_cell.h @@ -38,8 +38,6 @@ public: // Responder void didBecomeFirstResponder() override; -protected: - KDRect textFieldFrame() const; private: constexpr static float k_horizontalAlignment = 1.0f; constexpr static int k_textFieldBufferSize = Shared::StorageFunction::k_maxNameWithArgumentAndEqualSize; diff --git a/apps/shared/function_title_cell.cpp b/apps/shared/function_title_cell.cpp index 4a94c8649..b6147c7f5 100644 --- a/apps/shared/function_title_cell.cpp +++ b/apps/shared/function_title_cell.cpp @@ -22,13 +22,29 @@ void FunctionTitleCell::setBaseline(KDCoordinate baseline) { void FunctionTitleCell::drawRect(KDContext * ctx, KDRect rect) const { if (m_orientation == Orientation::VerticalIndicator){ - ctx->fillRect(KDRect(0, 0, k_colorIndicatorThickness, bounds().height()), m_functionColor); KDColor separatorColor = m_even ? Palette::WallScreen : KDColorWhite; - // Color the horizontal separator + KDColor backgroundColor = m_even ? KDColorWhite : Palette::WallScreen; + // Draw the color indicator + ctx->fillRect(KDRect(0, 0, k_colorIndicatorThickness, bounds().height()), m_functionColor); + // Draw the horizontal separator ctx->fillRect(KDRect(k_colorIndicatorThickness, bounds().height()-k_separatorThickness, bounds().width()-k_colorIndicatorThickness, k_separatorThickness), separatorColor); + // Draw some background + ctx->fillRect(KDRect(bounds().width() - k_equalWidthWithMargins, 0, k_equalWidthWithMargins, bounds().height()-k_separatorThickness), backgroundColor); + // Draw '=' + KDPoint p = KDPoint(bounds().width() - k_equalWidthWithMargins, m_baseline - font()->glyphSize().height()/2 - 1); // -1 is visually needed + ctx->drawString("=", p, font(), m_functionColor, backgroundColor); } else { + // Draw the color indicator ctx->fillRect(KDRect(0, 0, bounds().width(), k_colorIndicatorThickness), m_functionColor); } } +KDRect FunctionTitleCell::subviewFrame() const { + if (m_orientation == Orientation::VerticalIndicator) { + return KDRect(k_colorIndicatorThickness, 0, bounds().width() - k_colorIndicatorThickness - k_equalWidthWithMargins, bounds().height()-k_separatorThickness); + } + return KDRect(0, k_colorIndicatorThickness, bounds().width(), bounds().height()-k_colorIndicatorThickness); + +} + } diff --git a/apps/shared/function_title_cell.h b/apps/shared/function_title_cell.h index 8fbadb0d5..4a400e67e 100644 --- a/apps/shared/function_title_cell.h +++ b/apps/shared/function_title_cell.h @@ -25,9 +25,11 @@ public: protected: constexpr static KDCoordinate k_separatorThickness = 1; constexpr static KDCoordinate k_colorIndicatorThickness = 2; + KDRect subviewFrame() const; Orientation m_orientation; KDCoordinate m_baseline; private: + constexpr static KDCoordinate k_equalWidthWithMargins = 10; // Ad hoc value KDColor m_functionColor; }; From 6e77bb412301237a59c0f858c81cb2bec6696488 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 29 Nov 2018 15:43:54 +0100 Subject: [PATCH 021/373] [apps] Revert Equal after function name --- apps/graph/list/storage_list_controller.cpp | 8 +++----- apps/graph/list/text_field_function_title_cell.cpp | 2 +- apps/graph/list/text_field_function_title_cell.h | 2 +- apps/shared/storage_function.cpp | 11 ++--------- apps/shared/storage_function.h | 4 ---- 5 files changed, 7 insertions(+), 20 deletions(-) diff --git a/apps/graph/list/storage_list_controller.cpp b/apps/graph/list/storage_list_controller.cpp index 60048321c..034c5afa0 100644 --- a/apps/graph/list/storage_list_controller.cpp +++ b/apps/graph/list/storage_list_controller.cpp @@ -42,16 +42,14 @@ void StorageListController::renameSelectedFunction() { bool StorageListController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) { // Compute the new name size_t textLength = strlen(text); - size_t argumentLength = StorageFunction::k_parenthesedArgumentWithEqualLength; - constexpr int maxBaseNameSize = StorageFunction::k_maxNameWithArgumentAndEqualSize; + size_t argumentLength = StorageFunction::k_parenthesedArgumentLength; + constexpr int maxBaseNameSize = StorageFunction::k_maxNameWithArgumentSize; char baseName[maxBaseNameSize]; if (textLength <= argumentLength) { // The user entered an empty name. Use a default function name. StorageCartesianFunction::DefaultName(baseName, maxBaseNameSize); size_t defaultNameLength = strlen(baseName); - assert(defaultNameLength + Shared::StorageCartesianFunction::k_maxNameWithArgumentAndEqualSize < maxBaseNameSize); strlcpy(baseName + defaultNameLength, StorageFunction::k_parenthesedArgument, maxBaseNameSize - defaultNameLength); - strlcpy(baseName + defaultNameLength + StorageFunction::k_parenthesedArgumentLength, StorageFunction::k_equal, maxBaseNameSize - defaultNameLength - StorageFunction::k_parenthesedArgumentLength); textField->setText(baseName); baseName[defaultNameLength] = 0; } else { @@ -168,7 +166,7 @@ void StorageListController::willDisplayExpressionCellAtIndex(HighlightCell * cel void StorageListController::setFunctionNameInTextField(ExpiringPointer function, TextField * textField) { char bufferName[BufferTextView::k_maxNumberOfChar]; - function->nameWithArgumentAndEqual(bufferName, BufferTextView::k_maxNumberOfChar, modelStore()->symbol()); + function->nameWithArgument(bufferName, BufferTextView::k_maxNumberOfChar, modelStore()->symbol()); textField->setText(bufferName); } diff --git a/apps/graph/list/text_field_function_title_cell.cpp b/apps/graph/list/text_field_function_title_cell.cpp index 017f7b762..accc916ff 100644 --- a/apps/graph/list/text_field_function_title_cell.cpp +++ b/apps/graph/list/text_field_function_title_cell.cpp @@ -10,7 +10,7 @@ static inline float max(float x, float y) { return (x>y ? x : y); } TextFieldFunctionTitleCell::TextFieldFunctionTitleCell(StorageListController * listController, Orientation orientation, const KDFont * font) : Shared::FunctionTitleCell(orientation), Responder(listController), - m_textField(Shared::StorageFunction::k_parenthesedArgumentWithEqualLength, this, m_textFieldBuffer, m_textFieldBuffer, k_textFieldBufferSize, nullptr, listController, false, font, k_horizontalAlignment, 0.5f) + m_textField(Shared::StorageFunction::k_parenthesedArgumentLength, this, m_textFieldBuffer, m_textFieldBuffer, k_textFieldBufferSize, nullptr, listController, false, font, k_horizontalAlignment, 0.5f) {} void TextFieldFunctionTitleCell::setHighlighted(bool highlight) { diff --git a/apps/graph/list/text_field_function_title_cell.h b/apps/graph/list/text_field_function_title_cell.h index 7dd0ebdbe..f74819086 100644 --- a/apps/graph/list/text_field_function_title_cell.h +++ b/apps/graph/list/text_field_function_title_cell.h @@ -40,7 +40,7 @@ public: void didBecomeFirstResponder() override; private: constexpr static float k_horizontalAlignment = 1.0f; - constexpr static int k_textFieldBufferSize = Shared::StorageFunction::k_maxNameWithArgumentAndEqualSize; + constexpr static int k_textFieldBufferSize = Shared::StorageFunction::k_maxNameWithArgumentSize; Shared::TextFieldWithExtension m_textField; char m_textFieldBuffer[k_textFieldBufferSize]; }; diff --git a/apps/shared/storage_function.cpp b/apps/shared/storage_function.cpp index 80f21dc4d..afb572634 100644 --- a/apps/shared/storage_function.cpp +++ b/apps/shared/storage_function.cpp @@ -10,7 +10,6 @@ using namespace Poincare; namespace Shared { constexpr char StorageFunction::k_parenthesedArgument[]; -constexpr char StorageFunction::k_equal[]; bool StorageFunction::BaseNameCompliant(const char * baseName, NameNotCompliantError * error) { assert(baseName[0] != 0); @@ -64,17 +63,11 @@ void StorageFunction::setActive(bool active) { int StorageFunction::nameWithArgument(char * buffer, size_t bufferSize, char arg) { const char * functionName = fullName(); size_t baseNameLength = SymbolAbstract::TruncateExtension(buffer, functionName, bufferSize - k_parenthesedArgumentLength); - strlcpy(&buffer[baseNameLength], k_parenthesedArgument, bufferSize-baseNameLength); + int result = baseNameLength + strlcpy(&buffer[baseNameLength], k_parenthesedArgument, bufferSize-baseNameLength); if (baseNameLength+1 < bufferSize - 1) { buffer[baseNameLength+1] = arg; } - return strlen(buffer); -} - -int StorageFunction::nameWithArgumentAndEqual(char * buffer, size_t bufferSize, char arg) { - int numberOfChars = nameWithArgument(buffer, bufferSize, arg); - strlcpy(&buffer[numberOfChars], k_equal, bufferSize-numberOfChars); - return strlen(buffer); + return result; } template diff --git a/apps/shared/storage_function.h b/apps/shared/storage_function.h index 834106071..853f2a804 100644 --- a/apps/shared/storage_function.h +++ b/apps/shared/storage_function.h @@ -17,9 +17,6 @@ public: constexpr static int k_parenthesedArgumentLength = 3; static constexpr char k_parenthesedArgument[k_parenthesedArgumentLength+1] = "(x)"; constexpr static int k_maxNameWithArgumentSize = Poincare::SymbolAbstract::k_maxNameSize + k_parenthesedArgumentLength; /* Function name and null-terminating char + "(x)" */; - constexpr static int k_parenthesedArgumentWithEqualLength = k_parenthesedArgumentLength + 1; - static constexpr char k_equal[] = "="; - constexpr static int k_maxNameWithArgumentAndEqualSize = k_maxNameWithArgumentSize + 1; static bool BaseNameCompliant(const char * baseName, NameNotCompliantError * error = nullptr); // Constructors @@ -32,7 +29,6 @@ public: // Name int nameWithArgument(char * buffer, size_t bufferSize, char arg); - int nameWithArgumentAndEqual(char * buffer, size_t bufferSize, char arg); // Evaluation virtual float evaluateAtAbscissa(float x, Poincare::Context * context) const { From 37401a5e59721a299c890dd095131bca05f5a315 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 29 Nov 2018 16:40:02 +0100 Subject: [PATCH 022/373] [apps/graph] Add margin between function name and equal --- .../list/text_field_function_title_cell.cpp | 19 +++++++++++++++---- .../list/text_field_function_title_cell.h | 2 +- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/apps/graph/list/text_field_function_title_cell.cpp b/apps/graph/list/text_field_function_title_cell.cpp index accc916ff..75279d44f 100644 --- a/apps/graph/list/text_field_function_title_cell.cpp +++ b/apps/graph/list/text_field_function_title_cell.cpp @@ -10,8 +10,9 @@ static inline float max(float x, float y) { return (x>y ? x : y); } TextFieldFunctionTitleCell::TextFieldFunctionTitleCell(StorageListController * listController, Orientation orientation, const KDFont * font) : Shared::FunctionTitleCell(orientation), Responder(listController), - m_textField(Shared::StorageFunction::k_parenthesedArgumentLength, this, m_textFieldBuffer, m_textFieldBuffer, k_textFieldBufferSize, nullptr, listController, false, font, k_horizontalAlignment, 0.5f) - {} + m_textField(Shared::StorageFunction::k_parenthesedArgumentLength, this, m_textFieldBuffer, m_textFieldBuffer, k_textFieldBufferSize, nullptr, listController, false, font, 1.0f, 0.5f) +{ +} void TextFieldFunctionTitleCell::setHighlighted(bool highlight) { EvenOddCell::setHighlighted(highlight); @@ -50,9 +51,19 @@ void TextFieldFunctionTitleCell::setText(const char * title) { void TextFieldFunctionTitleCell::layoutSubviews() { KDRect frame = subviewFrame(); m_textField.setFrame(frame); + KDCoordinate maxTextFieldX = frame.width() - m_textField.minimalSizeForOptimalDisplay().width(); + float horizontalAlignment = max( + 0.0f, + min( + 1.0f, + ((float)(maxTextFieldX - k_textFieldRightMargin))/((float)maxTextFieldX))); KDCoordinate glyphHeight = font()->glyphSize().height(); - float verticalAlignment = max(0.0f, min(1.0f, m_baseline < 0 ? 0.5f : ((float)(m_baseline - glyphHeight/2))/((float)frame.height()+1-glyphHeight))); - m_textField.setAlignment(k_horizontalAlignment, verticalAlignment); + float verticalAlignment = max( + 0.0f, + min( + 1.0f, + m_baseline < 0 ? 0.5f : ((float)(m_baseline - glyphHeight/2))/((float)frame.height()+1-glyphHeight))); + m_textField.setAlignment(horizontalAlignment, verticalAlignment); } void TextFieldFunctionTitleCell::didBecomeFirstResponder() { diff --git a/apps/graph/list/text_field_function_title_cell.h b/apps/graph/list/text_field_function_title_cell.h index f74819086..bb2164ebf 100644 --- a/apps/graph/list/text_field_function_title_cell.h +++ b/apps/graph/list/text_field_function_title_cell.h @@ -39,7 +39,7 @@ public: // Responder void didBecomeFirstResponder() override; private: - constexpr static float k_horizontalAlignment = 1.0f; + constexpr static KDCoordinate k_textFieldRightMargin = 4; constexpr static int k_textFieldBufferSize = Shared::StorageFunction::k_maxNameWithArgumentSize; Shared::TextFieldWithExtension m_textField; char m_textFieldBuffer[k_textFieldBufferSize]; From 6ba70c332bfed26e914335654ff8ea8758963805 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 29 Nov 2018 16:40:27 +0100 Subject: [PATCH 023/373] [apps/graph] Fix redrawing bugs due to missing memoization reset --- apps/shared/storage_expression_model_list_controller.cpp | 2 ++ apps/shared/storage_expression_model_list_controller.h | 2 +- apps/shared/storage_function_list_controller.cpp | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/shared/storage_expression_model_list_controller.cpp b/apps/shared/storage_expression_model_list_controller.cpp index ff4945be8..1569b3881 100644 --- a/apps/shared/storage_expression_model_list_controller.cpp +++ b/apps/shared/storage_expression_model_list_controller.cpp @@ -172,6 +172,7 @@ void StorageExpressionModelListController::addEmptyModel() { void StorageExpressionModelListController::reinitExpression(ExpiringPointer model) { model->setContent(""); + resetMemoization(); selectableTableView()->reloadData(); } @@ -197,6 +198,7 @@ void StorageExpressionModelListController::editExpression(Ion::Events::Event eve StorageExpressionModelListController * myController = static_cast(context); InputViewController * myInputViewController = (InputViewController *)sender; const char * textBody = myInputViewController->textBody(); + myController->resetMemoization(); return myController->editSelectedRecordWithText(textBody); }, [](void * context, void * sender){ diff --git a/apps/shared/storage_expression_model_list_controller.h b/apps/shared/storage_expression_model_list_controller.h index 577b5a930..47d225b55 100644 --- a/apps/shared/storage_expression_model_list_controller.h +++ b/apps/shared/storage_expression_model_list_controller.h @@ -23,7 +23,7 @@ protected: // Responder bool handleEventOnExpression(Ion::Events::Event event); virtual void addEmptyModel(); - virtual void didChangeModelsList() {} + virtual void didChangeModelsList() { resetMemoization(); } virtual void reinitExpression(ExpiringPointer model); virtual void editExpression(Ion::Events::Event event); virtual bool editSelectedRecordWithText(const char * text); diff --git a/apps/shared/storage_function_list_controller.cpp b/apps/shared/storage_function_list_controller.cpp index bf91cff67..c81b0cc8e 100644 --- a/apps/shared/storage_function_list_controller.cpp +++ b/apps/shared/storage_function_list_controller.cpp @@ -312,6 +312,7 @@ KDCoordinate StorageFunctionListController::maxFunctionNameWidth() { } void StorageFunctionListController::didChangeModelsList() { + StorageExpressionModelListController::didChangeModelsList(); computeTitlesColumnWidth(); } From 964703bb03aa0bebf7cc2c03ffd7854f876dc604 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 29 Nov 2018 17:07:57 +0100 Subject: [PATCH 024/373] [apps/graph] Increase name column width to max when editing function name --- apps/graph/list/storage_list_controller.cpp | 8 ++++++++ apps/shared/storage_function_list_controller.cpp | 15 ++++++++++++--- apps/shared/storage_function_list_controller.h | 5 +++-- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/apps/graph/list/storage_list_controller.cpp b/apps/graph/list/storage_list_controller.cpp index 034c5afa0..3142d175e 100644 --- a/apps/graph/list/storage_list_controller.cpp +++ b/apps/graph/list/storage_list_controller.cpp @@ -33,6 +33,11 @@ const char * StorageListController::title() { void StorageListController::renameSelectedFunction() { assert(selectedColumn() == 0); assert(selectedRow() >= 0 && selectedRow() < numberOfRows()-1); // TODO change if sometimes the addFunction row is not displayed + + // Increase the size of the name column + computeTitlesColumnWidth(true); + selectableTableView()->reloadData(); + static_cast(const_cast(app()->container()))->setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::AlphaLock); TextFieldFunctionTitleCell * selectedTitleCell = (TextFieldFunctionTitleCell *)(selectableTableView()->selectedCell()); app()->setFirstResponder(selectedTitleCell); @@ -107,6 +112,9 @@ bool StorageListController::textFieldDidFinishEditing(TextField * textField, con } bool StorageListController::textFieldDidAbortEditing(TextField * textField) { + // Put the name column back to normal size + computeTitlesColumnWidth(); + selectableTableView()->reloadData(); ExpiringPointer function = modelStore()->modelForRecord(modelStore()->recordAtIndex(selectedRow())); setFunctionNameInTextField(function, textField); m_selectableTableView.selectedCell()->setHighlighted(true); diff --git a/apps/shared/storage_function_list_controller.cpp b/apps/shared/storage_function_list_controller.cpp index c81b0cc8e..da9c3ef31 100644 --- a/apps/shared/storage_function_list_controller.cpp +++ b/apps/shared/storage_function_list_controller.cpp @@ -279,9 +279,13 @@ void StorageFunctionListController::configureFunction(Ion::Storage::Record recor stack->push(parameterController()); } -void StorageFunctionListController::computeTitlesColumnWidth() { +void StorageFunctionListController::computeTitlesColumnWidth(bool forceMax) { + if (forceMax) { + m_titlesColumnWidth = nameWidth(StorageFunction::k_maxNameWithArgumentSize - 1)+k_functionTitleSumOfMargins; + return; + } KDCoordinate maxTitleWidth = maxFunctionNameWidth()+k_functionTitleSumOfMargins; - m_titlesColumnWidth = maxTitleWidth < k_minTitleColumnWidth ? k_minTitleColumnWidth : maxTitleWidth; + m_titlesColumnWidth = max(maxTitleWidth, k_minTitleColumnWidth); } TabViewController * StorageFunctionListController::tabController() const { @@ -308,7 +312,7 @@ KDCoordinate StorageFunctionListController::maxFunctionNameWidth() { assert(dotPosition != nullptr); maxNameLength = max(maxNameLength, dotPosition-functionName); } - return (maxNameLength + StorageFunction::k_parenthesedArgumentLength) * titleCells(0)->font()->glyphSize().width(); + return nameWidth(maxNameLength + StorageFunction::k_parenthesedArgumentLength); } void StorageFunctionListController::didChangeModelsList() { @@ -355,4 +359,9 @@ void StorageFunctionListController::shiftMemoization(bool newCellIsUnder) { StorageExpressionModelListController::shiftMemoization(newCellIsUnder); } +KDCoordinate StorageFunctionListController::nameWidth(int nameLength) const { + assert(nameLength >= 0); + return nameLength * const_cast(this)->titleCells(0)->font()->glyphSize().width(); +} + } diff --git a/apps/shared/storage_function_list_controller.h b/apps/shared/storage_function_list_controller.h index 433be3b12..38cfbc0a6 100644 --- a/apps/shared/storage_function_list_controller.h +++ b/apps/shared/storage_function_list_controller.h @@ -53,7 +53,7 @@ public: protected: StackViewController * stackController() const; void configureFunction(Ion::Storage::Record record); - void computeTitlesColumnWidth(); + void computeTitlesColumnWidth(bool forceMax = false); StorageFunctionStore * modelStore() override; KDCoordinate baseline(int j); void resetMemoizationForIndex(int index) override; @@ -61,7 +61,7 @@ protected: SelectableTableView m_selectableTableView; private: static constexpr KDCoordinate k_minTitleColumnWidth = 65; - static constexpr KDCoordinate k_functionTitleSumOfMargins = 2*Metric::HistoryHorizontalMargin; + static constexpr KDCoordinate k_functionTitleSumOfMargins = 15; TabViewController * tabController() const; InputViewController * inputController() override; KDCoordinate maxFunctionNameWidth(); @@ -73,6 +73,7 @@ private: virtual HighlightCell * expressionCells(int index) = 0; virtual void willDisplayTitleCellAtIndex(HighlightCell * cell, int j) = 0; virtual KDCoordinate privateBaseline(int j) const = 0; + KDCoordinate nameWidth(int nameLength) const; EvenOddCell m_emptyCell; Button m_plotButton; Button m_valuesButton; From 0a43cdda7e42f7a5fe820a0c3538dc9f1718381a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 29 Nov 2018 17:48:28 +0100 Subject: [PATCH 025/373] [apps/graph] Horizontal alignment is 1.0f when editing function name --- apps/graph/list/storage_list_controller.cpp | 1 + .../list/text_field_function_title_cell.cpp | 23 +++++++++++++------ .../list/text_field_function_title_cell.h | 2 ++ 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/apps/graph/list/storage_list_controller.cpp b/apps/graph/list/storage_list_controller.cpp index 3142d175e..4824efdb5 100644 --- a/apps/graph/list/storage_list_controller.cpp +++ b/apps/graph/list/storage_list_controller.cpp @@ -40,6 +40,7 @@ void StorageListController::renameSelectedFunction() { static_cast(const_cast(app()->container()))->setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::AlphaLock); TextFieldFunctionTitleCell * selectedTitleCell = (TextFieldFunctionTitleCell *)(selectableTableView()->selectedCell()); + selectedTitleCell->setHorizontalAlignment(1.0f); app()->setFirstResponder(selectedTitleCell); selectedTitleCell->setEditing(true); } diff --git a/apps/graph/list/text_field_function_title_cell.cpp b/apps/graph/list/text_field_function_title_cell.cpp index 75279d44f..d4694df7d 100644 --- a/apps/graph/list/text_field_function_title_cell.cpp +++ b/apps/graph/list/text_field_function_title_cell.cpp @@ -48,6 +48,11 @@ void TextFieldFunctionTitleCell::setText(const char * title) { m_textField.setText(title); } +void TextFieldFunctionTitleCell::setHorizontalAlignment(float alignment) { + assert(alignment >= 0.0f && alignment <= 1.0f); + m_textField.setAlignment(alignment, verticalAlignment()); +} + void TextFieldFunctionTitleCell::layoutSubviews() { KDRect frame = subviewFrame(); m_textField.setFrame(frame); @@ -57,13 +62,7 @@ void TextFieldFunctionTitleCell::layoutSubviews() { min( 1.0f, ((float)(maxTextFieldX - k_textFieldRightMargin))/((float)maxTextFieldX))); - KDCoordinate glyphHeight = font()->glyphSize().height(); - float verticalAlignment = max( - 0.0f, - min( - 1.0f, - m_baseline < 0 ? 0.5f : ((float)(m_baseline - glyphHeight/2))/((float)frame.height()+1-glyphHeight))); - m_textField.setAlignment(horizontalAlignment, verticalAlignment); + m_textField.setAlignment(horizontalAlignment, verticalAlignment()); } void TextFieldFunctionTitleCell::didBecomeFirstResponder() { @@ -72,4 +71,14 @@ void TextFieldFunctionTitleCell::didBecomeFirstResponder() { } } +float TextFieldFunctionTitleCell::verticalAlignment() const { + KDCoordinate glyphHeight = font()->glyphSize().height(); + return max( + 0.0f, + min( + 1.0f, + m_baseline < 0 ? 0.5f : ((float)(m_baseline - glyphHeight/2))/((float)subviewFrame().height()+1-glyphHeight))); + +} + } diff --git a/apps/graph/list/text_field_function_title_cell.h b/apps/graph/list/text_field_function_title_cell.h index bb2164ebf..7ee79d2da 100644 --- a/apps/graph/list/text_field_function_title_cell.h +++ b/apps/graph/list/text_field_function_title_cell.h @@ -16,6 +16,7 @@ public: void setEditing(bool editing); bool isEditing() const; void setText(const char * textContent); + void setHorizontalAlignment(float alignment); // FunctionTitleCell void setColor(KDColor color) override; @@ -41,6 +42,7 @@ public: private: constexpr static KDCoordinate k_textFieldRightMargin = 4; constexpr static int k_textFieldBufferSize = Shared::StorageFunction::k_maxNameWithArgumentSize; + float verticalAlignment() const; Shared::TextFieldWithExtension m_textField; char m_textFieldBuffer[k_textFieldBufferSize]; }; From 64446f24e6993b21b44f543a55935aa55da768dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 30 Nov 2018 09:55:05 +0100 Subject: [PATCH 026/373] [apps/graph] Increae horizontal margin of function name in list --- apps/shared/storage_function_list_controller.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/shared/storage_function_list_controller.h b/apps/shared/storage_function_list_controller.h index 38cfbc0a6..2e48ed3a9 100644 --- a/apps/shared/storage_function_list_controller.h +++ b/apps/shared/storage_function_list_controller.h @@ -61,7 +61,7 @@ protected: SelectableTableView m_selectableTableView; private: static constexpr KDCoordinate k_minTitleColumnWidth = 65; - static constexpr KDCoordinate k_functionTitleSumOfMargins = 15; + static constexpr KDCoordinate k_functionTitleSumOfMargins = 25; TabViewController * tabController() const; InputViewController * inputController() override; KDCoordinate maxFunctionNameWidth(); From 3595a8e62844b989b610b8c09e59244844fbf808 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 30 Nov 2018 11:16:04 +0100 Subject: [PATCH 027/373] [apps/sequence] Align sequence title and expression baselines --- apps/graph/list/storage_list_controller.cpp | 3 +- .../list/text_field_function_title_cell.cpp | 10 +-- .../list/text_field_function_title_cell.h | 2 +- apps/sequence/list/list_controller.cpp | 19 +++++- apps/sequence/list/list_controller.h | 1 + apps/sequence/sequence.cpp | 61 ++++++------------- apps/sequence/sequence.h | 3 +- apps/sequence/sequence_title_cell.cpp | 18 +++--- apps/sequence/sequence_title_cell.h | 1 + .../expression_model_list_controller.cpp | 4 +- apps/shared/function_list_controller.h | 2 +- apps/shared/function_title_cell.cpp | 11 ++++ apps/shared/function_title_cell.h | 2 + 13 files changed, 72 insertions(+), 65 deletions(-) diff --git a/apps/graph/list/storage_list_controller.cpp b/apps/graph/list/storage_list_controller.cpp index 4824efdb5..adaab3ddb 100644 --- a/apps/graph/list/storage_list_controller.cpp +++ b/apps/graph/list/storage_list_controller.cpp @@ -155,9 +155,11 @@ HighlightCell * StorageListController::expressionCells(int index) { void StorageListController::willDisplayTitleCellAtIndex(HighlightCell * cell, int j) { TextFieldFunctionTitleCell * titleCell = static_cast(cell); + // Update the corresponding expression cell in order to geet the baseline StorageExpressionModelListController::willDisplayExpressionCellAtIndex(m_selectableTableView.cellAtLocation(1, j), j); titleCell->setBaseline(baseline(j)); if (!titleCell->isEditing()) { + // Set name and color if the name is not being edited ExpiringPointer function = modelStore()->modelForRecord(modelStore()->recordAtIndex(j)); setFunctionNameInTextField(function, titleCell->textField()); KDColor functionNameColor = function->isActive() ? function->color() : Palette::GreyDark; @@ -187,7 +189,6 @@ KDCoordinate StorageListController::privateBaseline(int j) const { return -1; } return 0.5*(const_cast(this)->rowHeight(j)-layout.layoutSize().height())+layout.baseline(); - } } diff --git a/apps/graph/list/text_field_function_title_cell.cpp b/apps/graph/list/text_field_function_title_cell.cpp index d4694df7d..405053675 100644 --- a/apps/graph/list/text_field_function_title_cell.cpp +++ b/apps/graph/list/text_field_function_title_cell.cpp @@ -71,14 +71,10 @@ void TextFieldFunctionTitleCell::didBecomeFirstResponder() { } } -float TextFieldFunctionTitleCell::verticalAlignment() const { +float TextFieldFunctionTitleCell::verticalAlignmentGivenExpressionBaselineAndRowHeight(KDCoordinate expressionBaseline, KDCoordinate rowHeight) const { + assert(m_orientation == Orientation::VerticalIndicator); KDCoordinate glyphHeight = font()->glyphSize().height(); - return max( - 0.0f, - min( - 1.0f, - m_baseline < 0 ? 0.5f : ((float)(m_baseline - glyphHeight/2))/((float)subviewFrame().height()+1-glyphHeight))); - + return ((float)(expressionBaseline - glyphHeight/2))/((float)rowHeight+1-glyphHeight); } } diff --git a/apps/graph/list/text_field_function_title_cell.h b/apps/graph/list/text_field_function_title_cell.h index 7ee79d2da..3a8771ba2 100644 --- a/apps/graph/list/text_field_function_title_cell.h +++ b/apps/graph/list/text_field_function_title_cell.h @@ -42,7 +42,7 @@ public: private: constexpr static KDCoordinate k_textFieldRightMargin = 4; constexpr static int k_textFieldBufferSize = Shared::StorageFunction::k_maxNameWithArgumentSize; - float verticalAlignment() const; + float verticalAlignmentGivenExpressionBaselineAndRowHeight(KDCoordinate expressionBaseline, KDCoordinate rowHeight) const override; Shared::TextFieldWithExtension m_textField; char m_textFieldBuffer[k_textFieldBufferSize]; }; diff --git a/apps/sequence/list/list_controller.cpp b/apps/sequence/list/list_controller.cpp index 81f7888c7..0348a4c00 100644 --- a/apps/sequence/list/list_controller.cpp +++ b/apps/sequence/list/list_controller.cpp @@ -192,10 +192,15 @@ HighlightCell * ListController::expressionCells(int index) { } void ListController::willDisplayTitleCellAtIndex(HighlightCell * cell, int j) { + assert(j>=0 && j < k_maxNumberOfRows); SequenceTitleCell * myCell = (SequenceTitleCell *)cell; + // Update the corresponding expression cell to get its baseline + willDisplayExpressionCellAtIndex(m_selectableTableView.cellAtLocation(1, j), j); + myCell->setBaseline(baseline(j)); + // Set the layout Sequence * sequence = m_sequenceStore->modelAtIndex(modelIndexForRow(j)); if (sequenceDefinitionForRow(j) == 0) { - myCell->setLayout(sequence->definitionNameWithEqual()); + myCell->setLayout(sequence->definitionName()); } if (sequenceDefinitionForRow(j) == 1) { myCell->setLayout(sequence->firstInitialConditionName()); @@ -203,6 +208,7 @@ void ListController::willDisplayTitleCellAtIndex(HighlightCell * cell, int j) { if (sequenceDefinitionForRow(j) == 2) { myCell->setLayout(sequence->secondInitialConditionName()); } + // Set the color KDColor nameColor = sequence->isActive() ? sequence->color() : Palette::GreyDark; myCell->setColor(nameColor); } @@ -299,4 +305,15 @@ void ListController::reinitExpression(Shared::ExpressionModel * model) { selectableTableView()->reloadData(); } +KDCoordinate ListController::baseline(int j) const { + //TODO copied from Graph::StorageListController, will be refactored when Sequence is a StorageApp + assert(j>=0 && j((const_cast(&m_selectableTableView))->cellAtLocation(1, j)); + Poincare::Layout layout = cell->layout(); + if (layout.isUninitialized()) { + return 0.5*const_cast(this)->rowHeight(j); + } + return 0.5*(const_cast(this)->rowHeight(j)-layout.layoutSize().height())+layout.baseline(); +} + } diff --git a/apps/sequence/list/list_controller.h b/apps/sequence/list/list_controller.h index 316dbc14a..969fa3d7e 100644 --- a/apps/sequence/list/list_controller.h +++ b/apps/sequence/list/list_controller.h @@ -44,6 +44,7 @@ private: void reinitExpression(Shared::ExpressionModel * model) override; void editExpression(Shared::ExpressionModel * model, Ion::Events::Event event) override; bool removeModelRow(Shared::ExpressionModel * model) override; + KDCoordinate baseline(int j) const; constexpr static int k_maxNumberOfRows = 3*MaxNumberOfSequences; SequenceStore * m_sequenceStore; SequenceTitleCell m_sequenceTitleCells[k_maxNumberOfRows]; diff --git a/apps/sequence/sequence.cpp b/apps/sequence/sequence.cpp index 6f47aac39..e0fb7f8ab 100644 --- a/apps/sequence/sequence.cpp +++ b/apps/sequence/sequence.cpp @@ -24,7 +24,7 @@ Sequence::Sequence(const char * text, KDColor color) : m_firstInitialConditionLayout(), m_secondInitialConditionLayout(), m_nameLayout(), - m_definitionNameWithEqual(), + m_definitionName(), m_firstInitialConditionName(), m_secondInitialConditionName(), m_initialRank(0) @@ -155,38 +155,23 @@ Poincare::Layout Sequence::nameLayout() { } Poincare::Layout Sequence::definitionName() { - if (m_type == Type::Explicit) { - return HorizontalLayout( - CharLayout(name()[0], k_layoutFont), - VerticalOffsetLayout(LayoutHelper::String("n", 1, k_layoutFont), VerticalOffsetLayoutNode::Type::Subscript)); + if (m_definitionName.isUninitialized()) { + if (m_type == Type::Explicit) { + m_definitionName = HorizontalLayout( + CharLayout(name()[0], k_layoutFont), + VerticalOffsetLayout(LayoutHelper::String("n", 1, k_layoutFont), VerticalOffsetLayoutNode::Type::Subscript)); + } else if (m_type == Type::SingleRecurrence) { + m_definitionName = HorizontalLayout( + CharLayout(name()[0], k_layoutFont), + VerticalOffsetLayout(LayoutHelper::String("n+1", 3, k_layoutFont), VerticalOffsetLayoutNode::Type::Subscript)); + } else { + assert(m_type == Type::DoubleRecurrence); + m_definitionName = HorizontalLayout( + CharLayout(name()[0], k_layoutFont), + VerticalOffsetLayout(LayoutHelper::String("n+2", 3, k_layoutFont), VerticalOffsetLayoutNode::Type::Subscript)); + } } - if (m_type == Type::SingleRecurrence) { - return HorizontalLayout( - CharLayout(name()[0], k_layoutFont), - VerticalOffsetLayout(LayoutHelper::String("n+1", 3, k_layoutFont), VerticalOffsetLayoutNode::Type::Subscript)); - } - assert(m_type == Type::DoubleRecurrence); - return HorizontalLayout( - CharLayout(name()[0], k_layoutFont), - VerticalOffsetLayout(LayoutHelper::String("n+2", 3, k_layoutFont), VerticalOffsetLayoutNode::Type::Subscript)); -} - -Poincare::Layout Sequence::definitionNameWithEqual() { - if (m_definitionNameWithEqual.isUninitialized()) { - m_definitionNameWithEqual = definitionName(); - assert(m_definitionNameWithEqual.isHorizontal()); - static_cast(m_definitionNameWithEqual).addChildAtIndex( - CharLayout(' ', KDFont::SmallFont), // Cheat margin - m_definitionNameWithEqual.numberOfChildren(), - m_definitionNameWithEqual.numberOfChildren(), - nullptr); - static_cast(m_definitionNameWithEqual).addChildAtIndex( - CharLayout('=', k_layoutFont), - m_definitionNameWithEqual.numberOfChildren(), - m_definitionNameWithEqual.numberOfChildren(), - nullptr); - } - return m_definitionNameWithEqual; + return m_definitionName; } Poincare::Layout Sequence::firstInitialConditionName() { @@ -199,10 +184,7 @@ Poincare::Layout Sequence::firstInitialConditionName() { Layout indexLayout = LayoutHelper::String(buffer, strlen(buffer), k_layoutFont); m_firstInitialConditionName = HorizontalLayout( CharLayout(name()[0], k_layoutFont), - VerticalOffsetLayout(indexLayout, VerticalOffsetLayoutNode::Type::Subscript), - CharLayout(' ', KDFont::SmallFont), // Cheat margin - CharLayout('=', k_layoutFont) - ); + VerticalOffsetLayout(indexLayout, VerticalOffsetLayoutNode::Type::Subscript)); } return m_firstInitialConditionName; } @@ -215,10 +197,7 @@ Poincare::Layout Sequence::secondInitialConditionName() { Layout indexLayout = LayoutHelper::String(buffer, strlen(buffer), k_layoutFont); m_secondInitialConditionName = HorizontalLayout( CharLayout(name()[0], k_layoutFont), - VerticalOffsetLayout(indexLayout, VerticalOffsetLayoutNode::Type::Subscript), - CharLayout(' ', KDFont::SmallFont), // Cheat margin - CharLayout('=', k_layoutFont) - ); + VerticalOffsetLayout(indexLayout, VerticalOffsetLayoutNode::Type::Subscript)); } } return m_secondInitialConditionName; @@ -331,7 +310,7 @@ void Sequence::tidy() { m_firstInitialConditionExpression = Expression(); m_secondInitialConditionExpression = Expression(); m_nameLayout = Layout(); - m_definitionNameWithEqual = Layout(); + m_definitionName = Layout(); m_firstInitialConditionName = Layout(); m_secondInitialConditionName = Layout(); } diff --git a/apps/sequence/sequence.h b/apps/sequence/sequence.h index c99072854..bd9deb493 100644 --- a/apps/sequence/sequence.h +++ b/apps/sequence/sequence.h @@ -36,7 +36,6 @@ public: int numberOfElements(); Poincare::Layout nameLayout(); Poincare::Layout definitionName(); - Poincare::Layout definitionNameWithEqual(); Poincare::Layout firstInitialConditionName(); Poincare::Layout secondInitialConditionName(); bool isDefined() override; @@ -66,7 +65,7 @@ private: Poincare::Layout m_firstInitialConditionLayout; Poincare::Layout m_secondInitialConditionLayout; Poincare::Layout m_nameLayout; - Poincare::Layout m_definitionNameWithEqual; + Poincare::Layout m_definitionName; Poincare::Layout m_firstInitialConditionName; Poincare::Layout m_secondInitialConditionName; int m_initialRank; diff --git a/apps/sequence/sequence_title_cell.cpp b/apps/sequence/sequence_title_cell.cpp index e7e3c6853..7e2f08a90 100644 --- a/apps/sequence/sequence_title_cell.cpp +++ b/apps/sequence/sequence_title_cell.cpp @@ -52,18 +52,16 @@ View * SequenceTitleCell::subviewAtIndex(int index) { } void SequenceTitleCell::layoutSubviews() { - KDRect textFrame(0, k_colorIndicatorThickness, bounds().width(), bounds().height() - k_colorIndicatorThickness); if (m_orientation == Orientation::VerticalIndicator) { - KDCoordinate h = bounds().height()-k_separatorThickness; - textFrame = KDRect(k_colorIndicatorThickness, 0, bounds().width() - k_colorIndicatorThickness, h); - /* We try to align the text so that the equal is vertically centered in the - * cell. This makes the title cell and the definition cell baselines be - * approximately at the same level for basic sequences definitions (un = 1, - * un=1/2, ...). */ - float verticalAlignment = 0.5f + 20.0f/((float)h); // 20.0f is a magic value - m_titleTextView.setAlignment(k_verticalOrientationHorizontalAlignment, verticalAlignment); + m_titleTextView.setAlignment(k_verticalOrientationHorizontalAlignment, verticalAlignment()); } - m_titleTextView.setFrame(textFrame); + m_titleTextView.setFrame(subviewFrame()); +} + +float SequenceTitleCell::verticalAlignmentGivenExpressionBaselineAndRowHeight(KDCoordinate expressionBaseline, KDCoordinate rowHeight) const { + assert(m_orientation == Orientation::VerticalIndicator); + Layout l = layout(); + return ((float)(expressionBaseline - l.baseline()))/((float)rowHeight-l.layoutSize().height()); } } diff --git a/apps/sequence/sequence_title_cell.h b/apps/sequence/sequence_title_cell.h index db787b793..1f6b92c67 100644 --- a/apps/sequence/sequence_title_cell.h +++ b/apps/sequence/sequence_title_cell.h @@ -26,6 +26,7 @@ private: int numberOfSubviews() const override; View * subviewAtIndex(int index) override; void layoutSubviews() override; + float verticalAlignmentGivenExpressionBaselineAndRowHeight(KDCoordinate expressionBaseline, KDCoordinate rowHeight) const override; EvenOddExpressionCell m_titleTextView; }; diff --git a/apps/shared/expression_model_list_controller.cpp b/apps/shared/expression_model_list_controller.cpp index 327a5ac3b..02a52ec4f 100644 --- a/apps/shared/expression_model_list_controller.cpp +++ b/apps/shared/expression_model_list_controller.cpp @@ -45,6 +45,7 @@ bool ExpressionModelListController::handleEventOnExpression(Ion::Events::Event e if (event == Ion::Events::OK || event == Ion::Events::EXE) { if (isAddEmptyRow(selectedRow())) { addEmptyModel(); + selectableTableView()->reloadCellAtLocation(selectedColumn(), selectedRow()); return true; } ExpressionModel * model = modelStore()->modelAtIndex(modelIndexForRow(selectedRow())); @@ -55,10 +56,12 @@ bool ExpressionModelListController::handleEventOnExpression(Ion::Events::Event e ExpressionModel * model = modelStore()->modelAtIndex(modelIndexForRow(selectedRow())); if (model->shouldBeClearedBeforeRemove()) { reinitExpression(model); + selectableTableView()->reloadCellAtLocation(selectedColumn(), selectedRow()); } else { if (removeModelRow(model)) { int newSelectedRow = selectedRow() >= numberOfExpressionRows() ? numberOfExpressionRows()-1 : selectedRow(); selectCellAtLocation(selectedColumn(), newSelectedRow); + selectableTableView()->reloadCellAtLocation(selectedColumn(), selectedRow()); selectableTableView()->reloadData(); } } @@ -84,7 +87,6 @@ void ExpressionModelListController::reinitExpression(ExpressionModel * model) { selectableTableView()->reloadData(); } - void ExpressionModelListController::editExpression(ExpressionModel * model, Ion::Events::Event event) { char * initialText = nullptr; char initialTextContent[TextField::maxBufferSize()]; diff --git a/apps/shared/function_list_controller.h b/apps/shared/function_list_controller.h index 4e5f659f3..24d1cf760 100644 --- a/apps/shared/function_list_controller.h +++ b/apps/shared/function_list_controller.h @@ -47,6 +47,7 @@ protected: StackViewController * stackController() const; void configureFunction(Function * function); FunctionStore * m_functionStore; + SelectableTableView m_selectableTableView; private: static constexpr KDCoordinate k_functionNameWidth = 65; TabViewController * tabController() const; @@ -60,7 +61,6 @@ private: virtual HighlightCell * titleCells(int index) = 0; virtual HighlightCell * expressionCells(int index) = 0; virtual void willDisplayTitleCellAtIndex(HighlightCell * cell, int j) = 0; - SelectableTableView m_selectableTableView; EvenOddCell m_emptyCell; Button m_plotButton; Button m_valuesButton; diff --git a/apps/shared/function_title_cell.cpp b/apps/shared/function_title_cell.cpp index b6147c7f5..b32a7b4ea 100644 --- a/apps/shared/function_title_cell.cpp +++ b/apps/shared/function_title_cell.cpp @@ -3,6 +3,9 @@ namespace Shared { +static inline float min(float x, float y) { return (xy ? x : y); } + void FunctionTitleCell::setOrientation(Orientation orientation) { m_orientation = orientation; reloadCell(); @@ -44,7 +47,15 @@ KDRect FunctionTitleCell::subviewFrame() const { return KDRect(k_colorIndicatorThickness, 0, bounds().width() - k_colorIndicatorThickness - k_equalWidthWithMargins, bounds().height()-k_separatorThickness); } return KDRect(0, k_colorIndicatorThickness, bounds().width(), bounds().height()-k_colorIndicatorThickness); +} +float FunctionTitleCell::verticalAlignment() const { + assert(m_orientation == Orientation::VerticalIndicator); + return max( + 0.0f, + min( + 1.0f, + m_baseline < 0 ? 0.5f : verticalAlignmentGivenExpressionBaselineAndRowHeight(m_baseline, subviewFrame().height()))); } } diff --git a/apps/shared/function_title_cell.h b/apps/shared/function_title_cell.h index 4a400e67e..45fc820d6 100644 --- a/apps/shared/function_title_cell.h +++ b/apps/shared/function_title_cell.h @@ -26,10 +26,12 @@ protected: constexpr static KDCoordinate k_separatorThickness = 1; constexpr static KDCoordinate k_colorIndicatorThickness = 2; KDRect subviewFrame() const; + float verticalAlignment() const; Orientation m_orientation; KDCoordinate m_baseline; private: constexpr static KDCoordinate k_equalWidthWithMargins = 10; // Ad hoc value + virtual float verticalAlignmentGivenExpressionBaselineAndRowHeight(KDCoordinate expressionBaseline, KDCoordinate rowHeight) const { assert(false); return 0; } KDColor m_functionColor; }; From e37a4167b9a3ea472f31e54a315503434f34c6c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 30 Nov 2018 11:31:20 +0100 Subject: [PATCH 028/373] [apps/sequence] Add margin to sequence name --- apps/sequence/sequence_title_cell.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/sequence/sequence_title_cell.cpp b/apps/sequence/sequence_title_cell.cpp index 7e2f08a90..e2357959d 100644 --- a/apps/sequence/sequence_title_cell.cpp +++ b/apps/sequence/sequence_title_cell.cpp @@ -10,6 +10,7 @@ SequenceTitleCell::SequenceTitleCell() : Shared::FunctionTitleCell(Orientation::VerticalIndicator), m_titleTextView(k_verticalOrientationHorizontalAlignment, k_horizontalOrientationAlignment) { + m_titleTextView.setRightMargin(3); } void SequenceTitleCell::setOrientation(Orientation orientation) { From 29ef8c6d23d2ca94b3e955536ef829059a0f7050 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 30 Nov 2018 11:54:42 +0100 Subject: [PATCH 029/373] [apps/solver] Solutions are indexed from 1, not 0 --- apps/solver/solutions_controller.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/solver/solutions_controller.cpp b/apps/solver/solutions_controller.cpp index bc28a6d47..a655efefd 100644 --- a/apps/solver/solutions_controller.cpp +++ b/apps/solver/solutions_controller.cpp @@ -165,9 +165,9 @@ void SolutionsController::willDisplayCellAtLocation(HighlightCell * cell, int i, break; default: /* The system has one variable but might have many solutions: the cell - * text is variableX, with X the row index. For instance, x0, x1,...*/ + * text is variableX, with X the row index + 1 (e.g. x1, x2,...) */ int length = strlcpy(bufferSymbol, m_equationStore->variableAtIndex(0), Poincare::SymbolAbstract::k_maxNameSize); - bufferSymbol[length++] = j+'0'; + bufferSymbol[length++] = j+'1'; bufferSymbol[length] = 0; break; } From 404db60a3d1ffae050a1e4b8d468df1a51d504ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 30 Nov 2018 16:40:30 +0100 Subject: [PATCH 030/373] [apps/shared] Code cleaning and inlining --- apps/shared/interactive_curve_view_range.cpp | 46 +++++-------------- apps/shared/interactive_curve_view_range.h | 20 +++++--- .../interactive_curve_view_range_delegate.cpp | 1 - 3 files changed, 26 insertions(+), 41 deletions(-) diff --git a/apps/shared/interactive_curve_view_range.cpp b/apps/shared/interactive_curve_view_range.cpp index 9c151d54a..adb83b87e 100644 --- a/apps/shared/interactive_curve_view_range.cpp +++ b/apps/shared/interactive_curve_view_range.cpp @@ -9,22 +9,6 @@ using namespace Poincare; namespace Shared { -InteractiveCurveViewRange::InteractiveCurveViewRange(CurveViewCursor * cursor, InteractiveCurveViewRangeDelegate * delegate) : - MemoizedCurveViewRange(), - m_yAuto(true), - m_delegate(delegate), - m_cursor(cursor) -{ -} - -void InteractiveCurveViewRange::setDelegate(InteractiveCurveViewRangeDelegate * delegate) { - m_delegate = delegate; -} - -void InteractiveCurveViewRange::setCursor(CurveViewCursor * cursor) { - m_cursor = cursor; -} - uint32_t InteractiveCurveViewRange::rangeChecksum() { float data[5] = {m_xMin, m_xMax, m_yMin, m_yMax, m_yAuto ? 1.0f : 0.0f}; size_t dataLengthInBytes = 5*sizeof(float); @@ -32,8 +16,9 @@ uint32_t InteractiveCurveViewRange::rangeChecksum() { return Ion::crc32((uint32_t *)data, dataLengthInBytes/sizeof(uint32_t)); } -bool InteractiveCurveViewRange::yAuto() { - return m_yAuto; +void InteractiveCurveViewRange::setYAuto(bool yAuto) { + m_yAuto = yAuto; + notifyRangeChange(); } void InteractiveCurveViewRange::setXMin(float xMin) { @@ -43,9 +28,7 @@ void InteractiveCurveViewRange::setXMin(float xMin) { newXMin = m_xMax - k_minFloat; MemoizedCurveViewRange::setXMin(clipped(newXMin, false)); } - if (m_delegate) { - m_delegate->didChangeRange(this); - } + notifyRangeChange(); } void InteractiveCurveViewRange::setXMax(float xMax) { @@ -55,9 +38,7 @@ void InteractiveCurveViewRange::setXMax(float xMax) { newXMax = m_xMin + k_minFloat; MemoizedCurveViewRange::setXMax(clipped(newXMax, true)); } - if (m_delegate) { - m_delegate->didChangeRange(this); - } + notifyRangeChange(); } void InteractiveCurveViewRange::setYMin(float yMin) { @@ -78,13 +59,6 @@ void InteractiveCurveViewRange::setYMax(float yMax) { } } -void InteractiveCurveViewRange::setYAuto(bool yAuto) { - m_yAuto = yAuto; - if (m_delegate) { - m_delegate->didChangeRange(this); - } -} - void InteractiveCurveViewRange::zoom(float ratio, float x, float y) { float xMin = m_xMin; float xMax = m_xMax; @@ -131,9 +105,7 @@ void InteractiveCurveViewRange::roundAbscissa() { } m_xMax = newXMax; MemoizedCurveViewRange::setXMin(newXMin); - if (m_delegate) { - m_delegate->didChangeRange(this); - } + notifyRangeChange(); } void InteractiveCurveViewRange::normalize() { @@ -240,4 +212,10 @@ float InteractiveCurveViewRange::clipped(float x, bool isMax) { return clippedX; } +void InteractiveCurveViewRange::notifyRangeChange() { + if (m_delegate) { + m_delegate->didChangeRange(this); + } +} + } diff --git a/apps/shared/interactive_curve_view_range.h b/apps/shared/interactive_curve_view_range.h index afe7b6c21..053b7c2b5 100644 --- a/apps/shared/interactive_curve_view_range.h +++ b/apps/shared/interactive_curve_view_range.h @@ -10,18 +10,25 @@ namespace Shared { class InteractiveCurveViewRange : public MemoizedCurveViewRange { public: - InteractiveCurveViewRange(CurveViewCursor * cursor, InteractiveCurveViewRangeDelegate * delegate = nullptr); - void setDelegate(InteractiveCurveViewRangeDelegate * delegate); - void setCursor(CurveViewCursor * cursor); + InteractiveCurveViewRange(CurveViewCursor * cursor, InteractiveCurveViewRangeDelegate * delegate = nullptr) : + MemoizedCurveViewRange(), + m_yAuto(true), + m_delegate(delegate), + m_cursor(cursor) + {} + + void setDelegate(InteractiveCurveViewRangeDelegate * delegate) { m_delegate = delegate; } + void setCursor(CurveViewCursor * cursor) { m_cursor = cursor; } uint32_t rangeChecksum() override; - //CurveViewWindow - bool yAuto(); + bool yAuto() const { return m_yAuto; } + void setYAuto(bool yAuto); + + // CurveViewWindow void setXMin(float f) override; void setXMax(float f) override; void setYMin(float f) override; void setYMax(float f) override; - void setYAuto(bool yAuto); // Window void zoom(float ratio, float x, float y); @@ -42,6 +49,7 @@ private: constexpr static float k_upperMaxFloat = 1E+8f; constexpr static float k_lowerMaxFloat = 9E+7f; constexpr static float k_maxRatioPositionRange = 1E5f; + void notifyRangeChange(); CurveViewCursor * m_cursor; }; diff --git a/apps/shared/interactive_curve_view_range_delegate.cpp b/apps/shared/interactive_curve_view_range_delegate.cpp index 017ed64bd..b2ad2efb2 100644 --- a/apps/shared/interactive_curve_view_range_delegate.cpp +++ b/apps/shared/interactive_curve_view_range_delegate.cpp @@ -5,7 +5,6 @@ namespace Shared { - bool InteractiveCurveViewRangeDelegate::didChangeRange(InteractiveCurveViewRange * interactiveCurveViewRange) { if (!interactiveCurveViewRange->yAuto()) { return false; From 19e8b2ee1cbeddb6e5ac5046530856eebdadffb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 30 Nov 2018 16:45:11 +0100 Subject: [PATCH 031/373] [apps] Fix InteractiveCurveViewController::addMargin --- .../interactive_curve_view_controller.cpp | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/apps/shared/interactive_curve_view_controller.cpp b/apps/shared/interactive_curve_view_controller.cpp index 73b36bf4e..87210bc06 100644 --- a/apps/shared/interactive_curve_view_controller.cpp +++ b/apps/shared/interactive_curve_view_controller.cpp @@ -37,7 +37,34 @@ InteractiveCurveViewController::InteractiveCurveViewController(Responder * paren } float InteractiveCurveViewController::addMargin(float x, float range, bool isMin) { + /* We are adding margins. Let's name: + * - The current range: rangeBefore + * - The next range: rangeAfter + * - The bottom margin ratio with which we will evaluate if a point is too + * low on the screen: bottomRatioAfter + * - The bottom margin ratio with which we will evaluate if a point is too + * high on the screen: topRatioAfter + * - The ratios we need to use to create the margins: bottomRatioBefore and + * topRatioBefore + * + * We want to add margins so that: + * bottomRatioAfter*rangeAfter == bottomRatioBefore * rangeBefore + * topRatioAfter*rangeAfter == topRatioBefore * rangeBefore + * Knowing that: + * rangeAfter = (1+bottomRatioBefore+topRatioBefore)*rangeBefore + * + * We thus have: + * bottomRatioBefore = bottomRatioAfter / (1-bottomRatioAfter-topRatioAfter) + * topRatioBefore = topRatioAfter / (1-bottomRatioAfter-topRatioAfter) + * + * If we just used bottomRatioBefore = bottomRatioAfter and + * topRatioBefore = topRatioAfter, we would create too small margins and the + * controller might need to pan right after a Y auto calibration. */ + + assert(displayBottomMarginRatio()+displayTopMarginRatio() < 1); // Assertion so that the formula is correct + float ratioDenominator = 1-displayBottomMarginRatio()-displayTopMarginRatio(); float ratio = isMin ? -displayBottomMarginRatio() : displayTopMarginRatio(); + ratio = ratio / ratioDenominator; return x+ratio*range; } From de3d200b8130a3d7076809c0a19ee8368a0f3464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 30 Nov 2018 17:01:17 +0100 Subject: [PATCH 032/373] [apps/graph/reg/seq] Do not switch on y auto each time graph appears --- apps/shared/interactive_curve_view_controller.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/shared/interactive_curve_view_controller.cpp b/apps/shared/interactive_curve_view_controller.cpp index 87210bc06..d9250f266 100644 --- a/apps/shared/interactive_curve_view_controller.cpp +++ b/apps/shared/interactive_curve_view_controller.cpp @@ -142,8 +142,11 @@ Responder * InteractiveCurveViewController::defaultController() { void InteractiveCurveViewController::viewWillAppear() { uint32_t newModelVersion = modelVersion(); if (*m_modelVersion != newModelVersion) { + if (*m_modelVersion == 0 || numberOfCurves() == 1) { + initRangeParameters(); + } *m_modelVersion = newModelVersion; - initRangeParameters(); + didChangeRange(interactiveCurveViewRange()); /* Warning: init cursor parameter before reloading banner view. Indeed, * reloading banner view needs an updated cursor to load the right data. */ initCursorParameters(); From 531b555949a33808bd8bcd59ba84648d697735f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 30 Nov 2018 17:33:39 +0100 Subject: [PATCH 033/373] [apps/sequence] Fix method that should be virtual pure The following scenaro crashed in DEBUG=1 and did not resize the window correctly in DEBUG=0. Got to sequence u(n)=n Go to sequence/graph Remove yAuto Go to sequence/list v(n) = cos(n) remove u(n) Go to sequence/graph --- apps/sequence/graph/graph_controller.cpp | 4 ++++ apps/sequence/graph/graph_controller.h | 2 ++ apps/shared/interactive_curve_view_controller.h | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/sequence/graph/graph_controller.cpp b/apps/sequence/graph/graph_controller.cpp index d5686e5ca..d16d68e9d 100644 --- a/apps/sequence/graph/graph_controller.cpp +++ b/apps/sequence/graph/graph_controller.cpp @@ -29,6 +29,10 @@ TermSumController * GraphController::termSumController() { return &m_termSumController; } +int GraphController::numberOfCurves() const { + return m_sequenceStore->numberOfModels(); +} + BannerView * GraphController::bannerView() { return &m_bannerView; } diff --git a/apps/sequence/graph/graph_controller.h b/apps/sequence/graph/graph_controller.h index 7c6916c0d..40e7f70d8 100644 --- a/apps/sequence/graph/graph_controller.h +++ b/apps/sequence/graph/graph_controller.h @@ -17,6 +17,8 @@ public: GraphController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, SequenceStore * sequenceStore, CurveViewRange * graphRange, Shared::CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * rangeVersion, Poincare::Preferences::AngleUnit * angleUnitVersion, ButtonRowController * header); I18n::Message emptyMessage() override; TermSumController * termSumController(); +protected: + int numberOfCurves() const override; private: BannerView * bannerView() override; bool handleEnter() override; diff --git a/apps/shared/interactive_curve_view_controller.h b/apps/shared/interactive_curve_view_controller.h index 27079c950..e455a6457 100644 --- a/apps/shared/interactive_curve_view_controller.h +++ b/apps/shared/interactive_curve_view_controller.h @@ -50,7 +50,7 @@ protected: virtual bool closestCurveIndexIsSuitable(int newIndex, int currentIndex) const { assert(false); return false; } virtual double yValue(int curveIndex, double x, Poincare::Context * context) const { assert(false); return 0; } virtual bool suitableYValue(double y) const { return true; } - virtual int numberOfCurves() const { assert(false); return 0; } + virtual int numberOfCurves() const = 0; OkView m_okView; private: From 37ac12b1da625e1acf0707f66ca34a0855485efc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 4 Dec 2018 09:40:07 +0100 Subject: [PATCH 034/373] [apps/graph] When changing the window manually, do not pan to cursor --- apps/shared/curve_view.cpp | 10 +++++----- apps/shared/storage_function_graph_controller.cpp | 4 +++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index 367c57763..186bfefb2 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -580,15 +580,15 @@ View * CurveView::subviewAtIndex(int index) { if (m_okView != nullptr) { return m_okView; } else { - if (m_bannerView != nullptr) { - return m_bannerView; + if (m_cursorView != nullptr) { + return m_cursorView; } } } - if (index == 1 && m_bannerView != nullptr && m_okView != nullptr) { - return m_bannerView; + if (index == 1 && m_cursorView != nullptr && m_okView != nullptr) { + return m_cursorView; } - return m_cursorView; + return m_bannerView; } } diff --git a/apps/shared/storage_function_graph_controller.cpp b/apps/shared/storage_function_graph_controller.cpp index 9d8c7efac..bc34ce043 100644 --- a/apps/shared/storage_function_graph_controller.cpp +++ b/apps/shared/storage_function_graph_controller.cpp @@ -136,7 +136,9 @@ void StorageFunctionGraphController::initCursorParameters() { m_cursor->moveTo(x, y); functionIndex = (std::isnan(y) || std::isinf(y)) ? 0 : functionIndex - 1; selectFunctionWithCursor(functionIndex); - interactiveCurveViewRange()->panToMakePointVisible(x, y, displayTopMarginRatio(), k_cursorRightMarginRatio, displayBottomMarginRatio(), k_cursorLeftMarginRatio); + if (interactiveCurveViewRange()->yAuto()) { + interactiveCurveViewRange()->panToMakePointVisible(x, y, displayTopMarginRatio(), k_cursorRightMarginRatio, displayBottomMarginRatio(), k_cursorLeftMarginRatio); + } } bool StorageFunctionGraphController::moveCursorVertically(int direction) { From 303ab7f009582b4f24e9323751ee56ed8490f40e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 4 Dec 2018 10:11:26 +0100 Subject: [PATCH 035/373] [apps/graph] Clean code in graph/graph_controller.cpp --- apps/graph/graph/graph_controller.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/graph/graph/graph_controller.cpp b/apps/graph/graph/graph_controller.cpp index 605dea77f..c0bb4e0fc 100644 --- a/apps/graph/graph/graph_controller.cpp +++ b/apps/graph/graph/graph_controller.cpp @@ -5,6 +5,8 @@ using namespace Shared; namespace Graph { +static inline float max(float x, float y) { return (x>y ? x : y); } + GraphController::GraphController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, StorageCartesianFunctionStore * functionStore, Shared::InteractiveCurveViewRange * curveViewRange, CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * rangeVersion, Poincare::Preferences::AngleUnit * angleUnitVersion, ButtonRowController * header) : StorageFunctionGraphController(parentResponder, inputEventHandlerDelegate, header, curveViewRange, &m_view, cursor, indexFunctionSelectedByCursor, modelVersion, rangeVersion, angleUnitVersion), m_bannerView(), @@ -44,10 +46,10 @@ float GraphController::interestingXRange() { ExpiringPointer f = functionStore()->modelForRecord(functionStore()->activeRecordAtIndex(i)); float fRange = f->expressionReduced(myApp->localContext()).characteristicXRange(*(myApp->localContext()), Poincare::Preferences::sharedPreferences()->angleUnit()); if (!std::isnan(fRange)) { - characteristicRange = fRange > characteristicRange ? fRange : characteristicRange; + characteristicRange = max(fRange, characteristicRange); } } - return (characteristicRange > 0.0f ? 1.6f*characteristicRange : 10.0f); + return (characteristicRange > 0.0f ? 1.6f*characteristicRange : InteractiveCurveViewRangeDelegate::interestingXRange()); } int GraphController::estimatedBannerNumberOfLines() const { From 18381fd33470761319c84fdee471873a2d7357e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 4 Dec 2018 10:12:01 +0100 Subject: [PATCH 036/373] [apps] Add FLT_EPSILON in float comparisons in interactive_curve_vw_rge This fixes the removal of yAuto when displaying the function f(x)=cos(x) --- apps/shared/interactive_curve_view_range.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/shared/interactive_curve_view_range.cpp b/apps/shared/interactive_curve_view_range.cpp index adb83b87e..dd15f78a9 100644 --- a/apps/shared/interactive_curve_view_range.cpp +++ b/apps/shared/interactive_curve_view_range.cpp @@ -1,6 +1,7 @@ #include "interactive_curve_view_range.h" #include #include +#include #include #include #include @@ -174,24 +175,24 @@ void InteractiveCurveViewRange::centerAxisAround(Axis axis, float position) { void InteractiveCurveViewRange::panToMakePointVisible(float x, float y, float topMarginRatio, float rightMarginRatio, float bottomMarginRation, float leftMarginRation) { float xRange = m_xMax - m_xMin; float yRange = m_yMax - m_yMin; - if (x < m_xMin + leftMarginRation*xRange && !std::isinf(x) && !std::isnan(x)) { + if (x < m_xMin + leftMarginRation*xRange - FLT_EPSILON && !std::isinf(x) && !std::isnan(x)) { float newXMin = clipped(x - leftMarginRation*xRange, false); m_xMax = clipped(newXMin + xRange, true); MemoizedCurveViewRange::setXMin(newXMin); m_yAuto = false; } - if (x > m_xMax - rightMarginRatio*xRange && !std::isinf(x) && !std::isnan(x)) { + if (x > m_xMax - rightMarginRatio*xRange + FLT_EPSILON && !std::isinf(x) && !std::isnan(x)) { m_xMax = clipped(x + rightMarginRatio*xRange, true); MemoizedCurveViewRange::setXMin(clipped(m_xMax - xRange, false)); m_yAuto = false; } - if (y < m_yMin + bottomMarginRation*yRange && !std::isinf(y) && !std::isnan(y)) { + if (y < m_yMin + bottomMarginRation*yRange - FLT_EPSILON && !std::isinf(y) && !std::isnan(y)) { float newYMin = clipped(y - bottomMarginRation*yRange, false); m_yMax = clipped(newYMin + yRange, true); MemoizedCurveViewRange::setYMin(newYMin); m_yAuto = false; } - if (y > m_yMax - topMarginRatio*yRange && !std::isinf(y) && !std::isnan(y)) { + if (y > m_yMax - topMarginRatio*yRange + FLT_EPSILON && !std::isinf(y) && !std::isnan(y)) { m_yMax = clipped(y + topMarginRatio*yRange, true); MemoizedCurveViewRange::setYMin(clipped(m_yMax - yRange, false)); m_yAuto = false; From 058b49a06329f6107a608ad37386c01f74acea02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 4 Dec 2018 10:26:05 +0100 Subject: [PATCH 037/373] [apps/Seq/Reg] Do not pan to cursor if no yAuto --- apps/regression/graph_controller.cpp | 4 +++- apps/shared/function_graph_controller.cpp | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/regression/graph_controller.cpp b/apps/regression/graph_controller.cpp index 9c3225105..be3298f72 100644 --- a/apps/regression/graph_controller.cpp +++ b/apps/regression/graph_controller.cpp @@ -276,7 +276,9 @@ void GraphController::initCursorParameters() { double x = m_store->meanOfColumn(*m_selectedSeriesIndex, 0); double y = m_store->meanOfColumn(*m_selectedSeriesIndex, 1); m_cursor->moveTo(x, y); - m_store->panToMakePointVisible(x, y, cursorTopMarginRatio(), k_cursorRightMarginRatio, cursorBottomMarginRatio(), k_cursorLeftMarginRatio); + if (m_store->yAuto()) { + m_store->panToMakePointVisible(x, y, cursorTopMarginRatio(), k_cursorRightMarginRatio, cursorBottomMarginRatio(), k_cursorLeftMarginRatio); + } *m_selectedDotIndex = m_store->numberOfPairsOfSeries(*m_selectedSeriesIndex); } diff --git a/apps/shared/function_graph_controller.cpp b/apps/shared/function_graph_controller.cpp index 9549a7c51..11d3b6a18 100644 --- a/apps/shared/function_graph_controller.cpp +++ b/apps/shared/function_graph_controller.cpp @@ -119,7 +119,9 @@ void FunctionGraphController::initCursorParameters() { m_cursor->moveTo(x, y); functionIndex = (std::isnan(y) || std::isinf(y)) ? 0 : functionIndex - 1; selectFunctionWithCursor(functionIndex); - interactiveCurveViewRange()->panToMakePointVisible(x, y, k_displayTopMarginRatio, k_cursorRightMarginRatio, k_displayBottomMarginRatio, k_cursorLeftMarginRatio); + if (interactiveCurveViewRange()->yAuto()) { + interactiveCurveViewRange()->panToMakePointVisible(x, y, k_displayTopMarginRatio, k_cursorRightMarginRatio, k_displayBottomMarginRatio, k_cursorLeftMarginRatio); + } } bool FunctionGraphController::moveCursorVertically(int direction) { From cf79795540d424a99a54b1df7b0f1d75e7e57875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 4 Dec 2018 11:32:02 +0100 Subject: [PATCH 038/373] [apps] Fix blob left of screen when drawing curves Try for instance f(x)=cos(x) in Graph --- apps/shared/curve_view.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index 186bfefb2..488fd6226 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -496,8 +496,12 @@ void CurveView::stampAtLocation(KDContext * ctx, KDRect rect, float pxf, float p if (pyf < -stampSize || pyf > pixelLength(Axis::Vertical)+stampSize) { return; } - KDCoordinate px = pxf; - KDCoordinate py = pyf; + /* When converting floats to KDCoordinate, we need to add -1 if the float is + * negative, otherwise all floats in ]-1.0;1.0[ are converted to 0 and there + * is a blob for x = 0. Try for instance f(x)=cos(x), the blob is at the + * intersection of the curve with the screen. */ + KDCoordinate px = pxf + (pxf > 0 ? 0 : -1); + KDCoordinate py = pyf + (pyf > 0 ? 0 : -1); KDRect stampRect(px-(circleDiameter-2)/2, py-(circleDiameter-2)/2, stampSize, stampSize); if (!rect.intersects(stampRect)) { return; From c50aba187336afaf650518d79ffbff5bb1d27fa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 4 Dec 2018 11:40:46 +0100 Subject: [PATCH 039/373] [apps] Clean shared/initialisation_parameter_controller.cpp --- .../initialisation_parameter_controller.cpp | 46 +++++++++---------- .../initialisation_parameter_controller.h | 6 ++- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/apps/shared/initialisation_parameter_controller.cpp b/apps/shared/initialisation_parameter_controller.cpp index 1cd9c1ca6..9c7cbe4fe 100644 --- a/apps/shared/initialisation_parameter_controller.cpp +++ b/apps/shared/initialisation_parameter_controller.cpp @@ -4,30 +4,21 @@ namespace Shared { -InitialisationParameterController::InitialisationParameterController(Responder * parentResponder, InteractiveCurveViewRange * graphRange) : - ViewController(parentResponder), - m_selectableTableView(this, this, this), - m_graphRange(graphRange) -{ +View * InitialisationParameterController::view() { + return &m_selectableTableView; } const char * InitialisationParameterController::title() { return I18n::translate(I18n::Message::Initialization); } -View * InitialisationParameterController::view() { - return &m_selectableTableView; -} - -void InitialisationParameterController::didBecomeFirstResponder() { - m_selectableTableView.selectCellAtLocation(0, 0); - app()->setFirstResponder(&m_selectableTableView); -} - bool InitialisationParameterController::handleEvent(Ion::Events::Event event) { if (event == Ion::Events::OK || event == Ion::Events::EXE) { - RangeMethodPointer rangeMethods[k_totalNumberOfCells] = {&InteractiveCurveViewRange::setTrigonometric, - &InteractiveCurveViewRange::roundAbscissa, &InteractiveCurveViewRange::normalize, &InteractiveCurveViewRange::setDefault}; + RangeMethodPointer rangeMethods[k_totalNumberOfCells] = { + &InteractiveCurveViewRange::setTrigonometric, + &InteractiveCurveViewRange::roundAbscissa, + &InteractiveCurveViewRange::normalize, + &InteractiveCurveViewRange::setDefault}; (m_graphRange->*rangeMethods[selectedRow()])(); StackViewController * stack = (StackViewController *)parentResponder(); stack->pop(); @@ -36,10 +27,18 @@ if (event == Ion::Events::OK || event == Ion::Events::EXE) { return false; } +void InitialisationParameterController::didBecomeFirstResponder() { + m_selectableTableView.selectCellAtLocation(0, 0); + app()->setFirstResponder(&m_selectableTableView); +} + int InitialisationParameterController::numberOfRows() { return k_totalNumberOfCells; -}; +} +KDCoordinate InitialisationParameterController::cellHeight() { + return Metric::ParameterCellHeight; +} HighlightCell * InitialisationParameterController::reusableCell(int index) { assert(index >= 0); @@ -51,14 +50,13 @@ int InitialisationParameterController::reusableCellCount() { return k_totalNumberOfCells; } -KDCoordinate InitialisationParameterController::cellHeight() { - return Metric::ParameterCellHeight; -} - void InitialisationParameterController::willDisplayCellForIndex(HighlightCell * cell, int index) { - MessageTableCell * myCell = (MessageTableCell *)cell; - I18n::Message titles[4] = {I18n::Message::Trigonometric, I18n::Message::RoundAbscissa, I18n::Message::Orthonormal, I18n::Message::DefaultSetting}; - myCell->setMessage(titles[index]); + I18n::Message titles[4] = { + I18n::Message::Trigonometric, + I18n::Message::RoundAbscissa, + I18n::Message::Orthonormal, + I18n::Message::DefaultSetting}; + ((MessageTableCell *)cell)->setMessage(titles[index]); } } diff --git a/apps/shared/initialisation_parameter_controller.h b/apps/shared/initialisation_parameter_controller.h index 46375df75..929040cfb 100644 --- a/apps/shared/initialisation_parameter_controller.h +++ b/apps/shared/initialisation_parameter_controller.h @@ -9,7 +9,11 @@ namespace Shared { class InitialisationParameterController : public ViewController, public SimpleListViewDataSource, public SelectableTableViewDataSource { public: - InitialisationParameterController(Responder * parentResponder, Shared::InteractiveCurveViewRange * graphRange); + InitialisationParameterController(Responder * parentResponder, Shared::InteractiveCurveViewRange * graphRange) : + ViewController(parentResponder), + m_selectableTableView(this, this, this), + m_graphRange(graphRange) + {} View * view() override; const char * title() override; bool handleEvent(Ion::Events::Event event) override; From 020e45937929f673d01b86d2869ed9168deb41c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 4 Dec 2018 11:57:17 +0100 Subject: [PATCH 040/373] [apps] Clean shared/interactive_curve_view_range.cpp --- apps/shared/interactive_curve_view_range.cpp | 59 +++++++++++--------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/apps/shared/interactive_curve_view_range.cpp b/apps/shared/interactive_curve_view_range.cpp index dd15f78a9..9c916fc44 100644 --- a/apps/shared/interactive_curve_view_range.cpp +++ b/apps/shared/interactive_curve_view_range.cpp @@ -10,6 +10,9 @@ using namespace Poincare; namespace Shared { +static inline float min(float x, float y) { return (xy ? x : y); } + uint32_t InteractiveCurveViewRange::rangeChecksum() { float data[5] = {m_xMin, m_xMax, m_yMin, m_yMax, m_yAuto ? 1.0f : 0.0f}; size_t dataLengthInBytes = 5*sizeof(float); @@ -76,7 +79,7 @@ void InteractiveCurveViewRange::zoom(float ratio, float x, float y) { m_xMax = newXMax; MemoizedCurveViewRange::setXMin(newXMin); } - m_yAuto = false; + setYAuto(false); float newYMin = clipped(centerY*(1.0f-ratio)+ratio*yMin, false); float newYMax = clipped(centerY*(1.0f-ratio)+ratio*yMax, true); if (!std::isnan(newYMin) && !std::isnan(newYMax)) { @@ -86,7 +89,7 @@ void InteractiveCurveViewRange::zoom(float ratio, float x, float y) { } void InteractiveCurveViewRange::panWithVector(float x, float y) { - m_yAuto = false; + setYAuto(false); if (clipped(m_xMin + x, false) != m_xMin + x || clipped(m_xMax + x, true) != m_xMax + x || clipped(m_yMin + y, false) != m_yMin + y || clipped(m_yMax + y, true) != m_yMax + y || std::isnan(clipped(m_xMin + x, false)) || std::isnan(clipped(m_xMax + x, true)) || std::isnan(clipped(m_yMin + y, false)) || std::isnan(clipped(m_yMax + y, true))) { return; } @@ -97,6 +100,7 @@ void InteractiveCurveViewRange::panWithVector(float x, float y) { } void InteractiveCurveViewRange::roundAbscissa() { + // Set x range float xMin = m_xMin; float xMax = m_xMax; float newXMin = clipped(std::round((xMin+xMax)/2) - (float)Ion::Display::Width/2.0f, false); @@ -106,6 +110,7 @@ void InteractiveCurveViewRange::roundAbscissa() { } m_xMax = newXMax; MemoizedCurveViewRange::setXMin(newXMin); + // Set y range notifyRangeChange(); } @@ -114,15 +119,19 @@ void InteractiveCurveViewRange::normalize() { float xMax = m_xMax; float yMin = m_yMin; float yMax = m_yMax; - float newXMin = clipped((xMin+xMax)/2 - 5.3f, false); - float newXMax = clipped((xMin+xMax)/2 + 5.3f, true); + // Set x range + float xMargin = 5.3f; + float newXMin = clipped((xMin+xMax)/2 - xMargin, false); + float newXMax = clipped((xMin+xMax)/2 + xMargin, true); if (!std::isnan(newXMin) && !std::isnan(newXMax)) { m_xMax = newXMax; MemoizedCurveViewRange::setXMin(newXMin); } - m_yAuto = false; - float newYMin = clipped((yMin+yMax)/2 - 3.1f, false); - float newYMax = clipped((yMin+yMax)/2 + 3.1f, true); + // Set y range + setYAuto(false); + float yMargin = 3.1f; + float newYMin = clipped((yMin+yMax)/2 - yMargin, false); + float newYMax = clipped((yMin+yMax)/2 + yMargin, true); if (!std::isnan(newYMin) && !std::isnan(newYMax)) { m_yMax = newYMax; MemoizedCurveViewRange::setYMin(newYMin); @@ -130,15 +139,15 @@ void InteractiveCurveViewRange::normalize() { } void InteractiveCurveViewRange::setTrigonometric() { - m_xMax = 10.5f; - MemoizedCurveViewRange::setXMin(-10.5f); - if (Preferences::sharedPreferences()->angleUnit() == Preferences::AngleUnit::Degree) { - m_xMax = 600.0f; - MemoizedCurveViewRange::setXMin(-600.0f); - } - m_yAuto = false; - m_yMax = 1.6f; - MemoizedCurveViewRange::setYMin(-1.6f); + // Set x range + float x = (Preferences::sharedPreferences()->angleUnit() == Preferences::AngleUnit::Degree) ? 600.0f : 10.5f; + m_xMax = x; + MemoizedCurveViewRange::setXMin(-x); + // Set y range + setYAuto(false); + float y = 1.6f; + m_yMax = y; + MemoizedCurveViewRange::setYMin(-y); } void InteractiveCurveViewRange::setDefault() { @@ -162,7 +171,7 @@ void InteractiveCurveViewRange::centerAxisAround(Axis axis, float position) { m_xMax = clipped(position + range/2.0f, true); MemoizedCurveViewRange::setXMin(clipped(position - range/2.0f, false)); } else { - m_yAuto = false; + setYAuto(false); float range = m_yMax - m_yMin; if (std::fabs(position/range) > k_maxRatioPositionRange) { range = std::pow(10.0f, std::floor(std::log10(std::fabs(position)))-1.0f); @@ -179,23 +188,23 @@ void InteractiveCurveViewRange::panToMakePointVisible(float x, float y, float to float newXMin = clipped(x - leftMarginRation*xRange, false); m_xMax = clipped(newXMin + xRange, true); MemoizedCurveViewRange::setXMin(newXMin); - m_yAuto = false; + setYAuto(false); } if (x > m_xMax - rightMarginRatio*xRange + FLT_EPSILON && !std::isinf(x) && !std::isnan(x)) { m_xMax = clipped(x + rightMarginRatio*xRange, true); MemoizedCurveViewRange::setXMin(clipped(m_xMax - xRange, false)); - m_yAuto = false; + setYAuto(false); } if (y < m_yMin + bottomMarginRation*yRange - FLT_EPSILON && !std::isinf(y) && !std::isnan(y)) { float newYMin = clipped(y - bottomMarginRation*yRange, false); m_yMax = clipped(newYMin + yRange, true); MemoizedCurveViewRange::setYMin(newYMin); - m_yAuto = false; + setYAuto(false); } if (y > m_yMax - topMarginRatio*yRange + FLT_EPSILON && !std::isinf(y) && !std::isnan(y)) { m_yMax = clipped(y + topMarginRatio*yRange, true); MemoizedCurveViewRange::setYMin(clipped(m_yMax - yRange, false)); - m_yAuto = false; + setYAuto(false); } } @@ -206,11 +215,9 @@ bool InteractiveCurveViewRange::isCursorVisible(float topMarginRatio, float righ } float InteractiveCurveViewRange::clipped(float x, bool isMax) { - float max = isMax ? k_upperMaxFloat : k_lowerMaxFloat; - float min = isMax ? -k_lowerMaxFloat : -k_upperMaxFloat; - float clippedX = x > max ? max : x; - clippedX = clippedX < min ? min : clippedX; - return clippedX; + float maxF = isMax ? k_upperMaxFloat : k_lowerMaxFloat; + float minF = isMax ? -k_lowerMaxFloat : -k_upperMaxFloat; + return max(minF, min(x, maxF)); } void InteractiveCurveViewRange::notifyRangeChange() { From cea413e91dca2e82ee43dc1dd80344d0f682ad4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 4 Dec 2018 14:12:54 +0100 Subject: [PATCH 041/373] [apps] Fix Orthonormal setting in graphs It was not perfectly orthormal. --- apps/sequence/graph/curve_view_range.cpp | 12 ++++++------ apps/shared/interactive_curve_view_range.cpp | 12 ++++++------ apps/shared/interactive_curve_view_range.h | 16 ++++++++++++++++ ion/include/ion/display.h | 2 ++ 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/apps/sequence/graph/curve_view_range.cpp b/apps/sequence/graph/curve_view_range.cpp index e9609669a..08aeed280 100644 --- a/apps/sequence/graph/curve_view_range.cpp +++ b/apps/sequence/graph/curve_view_range.cpp @@ -39,20 +39,20 @@ void CurveViewRange::normalize() { float xMax = m_xMax; float yMin = m_yMin; float yMax = m_yMax; - float newXMin = clipped((xMin+xMax)/2 - 5.3f, false); - float newXMax = clipped((xMin+xMax)/2 + 5.3f, true); + float newXMin = clipped((xMin+xMax)/2 - NormalizedXHalfRange(), false); + float newXMax = clipped((xMin+xMax)/2 + NormalizedXHalfRange(), true); if (!std::isnan(newXMin) && !std::isnan(newXMax)) { m_xMin = newXMin; m_xMax = newXMax; m_xGridUnit = computeGridUnit(Axis::X, m_xMin, m_xMax); } if (m_xMin < 0.0f) { - m_xMin = -k_displayLeftMarginRatio*2.0f*5.3f; - m_xMax = m_xMin + 2.0f*5.3f; + m_xMin = -k_displayLeftMarginRatio*2.0f*NormalizedXHalfRange(); + m_xMax = m_xMin + 2.0f*NormalizedXHalfRange(); } m_yAuto = false; - float newYMin = clipped((yMin+yMax)/2 - 3.1f, false); - float newYMax = clipped((yMin+yMax)/2 + 3.1f, true); + float newYMin = clipped((yMin+yMax)/2 - NormalizedYHalfRange(), false); + float newYMax = clipped((yMin+yMax)/2 + NormalizedYHalfRange(), true); if (!std::isnan(newYMin) && !std::isnan(newYMax)) { m_yMin = newYMin; m_yMax = newYMax; diff --git a/apps/shared/interactive_curve_view_range.cpp b/apps/shared/interactive_curve_view_range.cpp index 9c916fc44..82e1642f5 100644 --- a/apps/shared/interactive_curve_view_range.cpp +++ b/apps/shared/interactive_curve_view_range.cpp @@ -115,23 +115,23 @@ void InteractiveCurveViewRange::roundAbscissa() { } void InteractiveCurveViewRange::normalize() { + /* We center the ranges on the current range center, and put each axis so that + * 1cm = 2 units. */ float xMin = m_xMin; float xMax = m_xMax; float yMin = m_yMin; float yMax = m_yMax; // Set x range - float xMargin = 5.3f; - float newXMin = clipped((xMin+xMax)/2 - xMargin, false); - float newXMax = clipped((xMin+xMax)/2 + xMargin, true); + float newXMin = clipped((xMin+xMax)/2 - NormalizedXHalfRange(), false); + float newXMax = clipped((xMin+xMax)/2 + NormalizedXHalfRange(), true); if (!std::isnan(newXMin) && !std::isnan(newXMax)) { m_xMax = newXMax; MemoizedCurveViewRange::setXMin(newXMin); } // Set y range setYAuto(false); - float yMargin = 3.1f; - float newYMin = clipped((yMin+yMax)/2 - yMargin, false); - float newYMax = clipped((yMin+yMax)/2 + yMargin, true); + float newYMin = clipped((yMin+yMax)/2 - NormalizedYHalfRange(), false); + float newYMax = clipped((yMin+yMax)/2 + NormalizedYHalfRange(), true); if (!std::isnan(newYMin) && !std::isnan(newYMax)) { m_yMax = newYMax; MemoizedCurveViewRange::setYMin(newYMin); diff --git a/apps/shared/interactive_curve_view_range.h b/apps/shared/interactive_curve_view_range.h index 053b7c2b5..9d6e3abb4 100644 --- a/apps/shared/interactive_curve_view_range.h +++ b/apps/shared/interactive_curve_view_range.h @@ -5,6 +5,7 @@ #include "memoized_curve_view_range.h" #include "curve_view_cursor.h" #include "interactive_curve_view_range_delegate.h" +#include namespace Shared { @@ -42,6 +43,18 @@ public: bool isCursorVisible(float topMarginRatio, float rightMarginRatio, float bottomMarginRation, float leftMarginRation); protected: bool m_yAuto; + /* In normalized settings, we put each axis so that 1cm = 2 units. For now, + * the screen has size 43.2mm * 57.6mm. + * We want: + * 2*NormalizedXHalfRange -> 57.6mm + * 2*1 -> 10.0mm + * So NormalizedXHalfRange = 5.76 + * We want: + * 2*NormalizedYHalfRange -> 43.2mm * 170/240 + * 2*1 -> 10.0mm + * So NormalizedYHalfRange = 3.06 */ + constexpr static float NormalizedXHalfRange() { return 5.76f; } + constexpr static float NormalizedYHalfRange() { return 3.06f; } static float clipped(float f, bool isMax); InteractiveCurveViewRangeDelegate * m_delegate; private: @@ -53,6 +66,9 @@ private: CurveViewCursor * m_cursor; }; +static_assert(Ion::Display::WidthInTenthOfMillimeter == 576, "Use the new screen width to compute Shared::InteractiveCurveViewRange::NormalizedXHalfRange"); +static_assert(Ion::Display::HeightInTenthOfMillimeter == 432, "Use the new screen height to compute Shared::InteractiveCurveViewRange::NormalizedYHalfRange"); + typedef void (InteractiveCurveViewRange::*ParameterSetterPointer)(float); typedef float (InteractiveCurveViewRange::*ParameterGetterPointer)(); typedef void (InteractiveCurveViewRange::*RangeMethodPointer)(); diff --git a/ion/include/ion/display.h b/ion/include/ion/display.h index 4db471ba7..a43c830cc 100644 --- a/ion/include/ion/display.h +++ b/ion/include/ion/display.h @@ -25,6 +25,8 @@ void waitForVBlank(); constexpr int Width = 320; constexpr int Height = 240; +constexpr int WidthInTenthOfMillimeter = 576; +constexpr int HeightInTenthOfMillimeter = 432; } } From 4c6a5c9819af9dc70b957c66bc15b06fc19fe215 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 4 Dec 2018 16:47:36 +0100 Subject: [PATCH 042/373] [apps] When zooming on a curve, do not change the yRange It changed because of the zoom banner --- apps/shared/curve_view_range.cpp | 19 +++++++++---------- apps/shared/zoom_parameter_controller.cpp | 22 ++++++++++++++++++++++ apps/shared/zoom_parameter_controller.h | 5 ++++- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/apps/shared/curve_view_range.cpp b/apps/shared/curve_view_range.cpp index 06c16ad46..031830fd7 100644 --- a/apps/shared/curve_view_range.cpp +++ b/apps/shared/curve_view_range.cpp @@ -22,17 +22,16 @@ float CurveViewRange::computeGridUnit(Axis axis, float min, float max) { int a = 0; int b = 0; float d = max - min; - float maxNumberOfUnits = k_maxNumberOfXGridUnits; - float minNumberOfUnits = k_minNumberOfXGridUnits; - if (axis == Axis::Y) { - maxNumberOfUnits = k_maxNumberOfYGridUnits; - minNumberOfUnits = k_minNumberOfYGridUnits; - } - float units[3] = {k_smallGridUnitMantissa, k_mediumGridUnitMantissa, k_largeGridUnitMantissa}; - for (int k = 0; k < 3; k++) { + float maxNumberOfUnits = (axis == Axis::X) ? k_maxNumberOfXGridUnits : k_maxNumberOfYGridUnits; + float minNumberOfUnits = (axis == Axis::X) ? k_minNumberOfXGridUnits : k_minNumberOfYGridUnits; + constexpr int unitsCount = 3; + float units[unitsCount] = {k_smallGridUnitMantissa, k_mediumGridUnitMantissa, k_largeGridUnitMantissa}; + for (int k = 0; k < unitsCount; k++) { float unit = units[k]; - if (std::floor(std::log10(d/(unit*maxNumberOfUnits))) != std::floor(std::log10(d/(unit*minNumberOfUnits)))) { - b = std::floor(std::log10(d/(unit*minNumberOfUnits))); + int b1 = std::floor(std::log10(d/(unit*maxNumberOfUnits))); + int b2 = std::floor(std::log10(d/(unit*minNumberOfUnits))); + if (b1 != b2) { + b = b2; a = unit; } } diff --git a/apps/shared/zoom_parameter_controller.cpp b/apps/shared/zoom_parameter_controller.cpp index 92a9aa179..d47e81251 100644 --- a/apps/shared/zoom_parameter_controller.cpp +++ b/apps/shared/zoom_parameter_controller.cpp @@ -60,12 +60,33 @@ bool ZoomParameterController::handleEvent(Ion::Events::Event event) { void ZoomParameterController::viewWillAppear() { m_contentView.curveView()->setOkView(nullptr); + /* We need to change the curve range to keep the same visual aspect of the + * view. */ + adaptCurveRange(true); +} + +void ZoomParameterController::viewDidDisappear() { + // Restore the curve range + adaptCurveRange(false); } void ZoomParameterController::didBecomeFirstResponder() { m_contentView.layoutSubviews(); } +void ZoomParameterController::adaptCurveRange(bool viewWillAppear) { + float currentYMin = m_interactiveRange->yMin(); + float currentRange = m_interactiveRange->yMax() - m_interactiveRange->yMin(); + float newYMin = 0; + if (viewWillAppear) { + newYMin = currentYMin + ((float)ContentView::k_legendHeight)/((float)k_standardViewHeight)*currentRange; + } else { + newYMin = m_interactiveRange->yMax() - currentRange*((float)k_standardViewHeight)/(((float)k_standardViewHeight)-((float)ContentView::k_legendHeight)); + } + m_interactiveRange->setYMin(newYMin); + m_contentView.curveView()->reload(); +} + /* Content View */ ZoomParameterController::ContentView::ContentView(CurveView * curveView) : @@ -86,6 +107,7 @@ View * ZoomParameterController::ContentView::subviewAtIndex(int index) { } void ZoomParameterController::ContentView::layoutSubviews() { + assert(bounds().height() == ZoomParameterController::k_standardViewHeight); m_curveView->setFrame(KDRect(0, 0, bounds().width(), bounds().height() - k_legendHeight)); m_legendView.setFrame(KDRect(0, bounds().height() - k_legendHeight, bounds().width(), k_legendHeight)); } diff --git a/apps/shared/zoom_parameter_controller.h b/apps/shared/zoom_parameter_controller.h index 6ff2f7b19..186d9a468 100644 --- a/apps/shared/zoom_parameter_controller.h +++ b/apps/shared/zoom_parameter_controller.h @@ -15,10 +15,13 @@ public: View * view() override; bool handleEvent(Ion::Events::Event event) override; void viewWillAppear() override; + void viewDidDisappear() override; void didBecomeFirstResponder() override; private: + constexpr static KDCoordinate k_standardViewHeight = 175; class ContentView : public View { public: + constexpr static KDCoordinate k_legendHeight = 30; ContentView(CurveView * curveView); void layoutSubviews() override; CurveView * curveView(); @@ -41,8 +44,8 @@ private: View * subviewAtIndex(int index) override; CurveView * m_curveView; LegendView m_legendView; - constexpr static KDCoordinate k_legendHeight = 30; }; + void adaptCurveRange(bool viewWillAppear); ContentView m_contentView; InteractiveCurveViewRange * m_interactiveRange; }; From 8de74f4158c505534594aa53d4df7df73e0b1e41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 5 Dec 2018 11:12:01 +0100 Subject: [PATCH 043/373] [apps] Fix one pixel in CurveView::stampAtLocation --- apps/shared/curve_view.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index 488fd6226..54d887293 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -493,15 +493,15 @@ void CurveView::straightJoinDots(KDContext * ctx, KDRect rect, float pxf, float void CurveView::stampAtLocation(KDContext * ctx, KDRect rect, float pxf, float pyf, KDColor color) const { // We avoid drawing when no part of the stamp is visible - if (pyf < -stampSize || pyf > pixelLength(Axis::Vertical)+stampSize) { + if (pyf < -stampSize - FLT_EPSILON || pyf > pixelLength(Axis::Vertical)+stampSize + FLT_EPSILON) { return; } /* When converting floats to KDCoordinate, we need to add -1 if the float is * negative, otherwise all floats in ]-1.0;1.0[ are converted to 0 and there * is a blob for x = 0. Try for instance f(x)=cos(x), the blob is at the - * intersection of the curve with the screen. */ - KDCoordinate px = pxf + (pxf > 0 ? 0 : -1); - KDCoordinate py = pyf + (pyf > 0 ? 0 : -1); + * intersection of the curve with the left of the screen. */ + KDCoordinate px = pxf + (pxf >= 0 ? 0 : -1); + KDCoordinate py = pyf + (pyf >= 0 ? 0 : -1); KDRect stampRect(px-(circleDiameter-2)/2, py-(circleDiameter-2)/2, stampSize, stampSize); if (!rect.intersects(stampRect)) { return; From 36faebab3d51745e0a0a6757bcfdfc5391060eff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 5 Dec 2018 11:13:51 +0100 Subject: [PATCH 044/373] [apps] Fix some KDCoordinate to float conversions --- apps/shared/curve_view.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index 54d887293..adc10f3d9 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -112,7 +112,7 @@ KDCoordinate CurveView::pixelLength(Axis axis) const { float CurveView::pixelToFloat(Axis axis, KDCoordinate p) const { KDCoordinate pixels = axis == Axis::Horizontal ? p : pixelLength(axis)-p; - return min(axis) + pixels*((max(axis)-min(axis))/pixelLength(axis)); + return min(axis) + pixels*((float)(max(axis)-min(axis)))/((float)pixelLength(axis)); } float CurveView::floatToPixel(Axis axis, float f) const { @@ -270,7 +270,7 @@ void CurveView::drawGridLines(KDContext * ctx, KDRect rect, Axis axis, float ste } float start = step*((int)(min(axis)/step)); Axis otherAxis = (axis == Axis::Horizontal) ? Axis::Vertical : Axis::Horizontal; - for (float x =start; x < max(axis); x += step) { + for (float x = start; x < max(axis); x+= step) { /* When |start| >> step, start + step = start. In that case, quit the * infinite loop. */ if (x == x-step || x == x+step) { @@ -453,7 +453,7 @@ void CurveView::jointDots(KDContext * ctx, KDRect rect, EvaluateModelWithParamet if (std::isinf(pvf)) { pvf = pvf > 0 ? pixelLength(Axis::Vertical)+stampSize : -stampSize; } - if (pyf - (float)circleDiameter/2.0f < pvf && pvf < pyf + (float)circleDiameter/2.0f) { + if (pyf - ((float)circleDiameter)/2.0f < pvf && pvf < pyf + ((float)circleDiameter)/2.0f) { // the dots are already joined return; } From d76c77f32385534483120bb6c84cf2da83beaca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 5 Dec 2018 11:18:54 +0100 Subject: [PATCH 045/373] [apps] Prevent too much zooming on curve views This removes curve drawings that are ugly because of float imprecision, such as cos(x)^2+sin(x)^2 --- apps/shared/interactive_curve_view_range.h | 4 +++- apps/shared/interactive_curve_view_range_delegate.cpp | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/shared/interactive_curve_view_range.h b/apps/shared/interactive_curve_view_range.h index 9d6e3abb4..6ea5cb4ef 100644 --- a/apps/shared/interactive_curve_view_range.h +++ b/apps/shared/interactive_curve_view_range.h @@ -6,11 +6,13 @@ #include "curve_view_cursor.h" #include "interactive_curve_view_range_delegate.h" #include +#include namespace Shared { class InteractiveCurveViewRange : public MemoizedCurveViewRange { public: + constexpr static float k_minFloat = 1E-4f; InteractiveCurveViewRange(CurveViewCursor * cursor, InteractiveCurveViewRangeDelegate * delegate = nullptr) : MemoizedCurveViewRange(), m_yAuto(true), @@ -58,7 +60,6 @@ protected: static float clipped(float f, bool isMax); InteractiveCurveViewRangeDelegate * m_delegate; private: - constexpr static float k_minFloat = 1E-8f; constexpr static float k_upperMaxFloat = 1E+8f; constexpr static float k_lowerMaxFloat = 9E+7f; constexpr static float k_maxRatioPositionRange = 1E5f; @@ -66,6 +67,7 @@ private: CurveViewCursor * m_cursor; }; +static_assert(InteractiveCurveViewRange::k_minFloat >= FLT_EPSILON, "InteractiveCurveViewRange's minimal float range is lower than float precision, it might draw uglily curves such as cos(x)^2+sin(x)^2"); static_assert(Ion::Display::WidthInTenthOfMillimeter == 576, "Use the new screen width to compute Shared::InteractiveCurveViewRange::NormalizedXHalfRange"); static_assert(Ion::Display::HeightInTenthOfMillimeter == 432, "Use the new screen height to compute Shared::InteractiveCurveViewRange::NormalizedYHalfRange"); diff --git a/apps/shared/interactive_curve_view_range_delegate.cpp b/apps/shared/interactive_curve_view_range_delegate.cpp index b2ad2efb2..45546fdd4 100644 --- a/apps/shared/interactive_curve_view_range_delegate.cpp +++ b/apps/shared/interactive_curve_view_range_delegate.cpp @@ -37,6 +37,10 @@ bool InteractiveCurveViewRangeDelegate::didChangeRange(InteractiveCurveViewRange max = min+step; } range = max - min; + if (range < InteractiveCurveViewRange::k_minFloat) { + max += InteractiveCurveViewRange::k_minFloat; + min -= InteractiveCurveViewRange::k_minFloat; + } interactiveCurveViewRange->setYMin(addMargin(min, range, true)); interactiveCurveViewRange->setYMax(addMargin(max, range, false)); if (std::isinf(interactiveCurveViewRange->xMin())) { From a65bdb1dfc8c94a59764450a1717a752a5fa1f04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 5 Dec 2018 11:57:54 +0100 Subject: [PATCH 046/373] [apps] Increase the Y axis label buffer sizes in curve views --- apps/probability/law_curve_view.h | 2 +- apps/regression/graph_view.h | 4 ++-- apps/shared/curve_view.cpp | 8 ++++++-- apps/shared/curve_view.h | 19 +++++++++++-------- apps/shared/function_graph_view.h | 4 ++-- apps/shared/storage_function_graph_view.h | 4 ++-- apps/statistics/box_axis_view.h | 2 +- apps/statistics/histogram_view.h | 2 +- 8 files changed, 26 insertions(+), 19 deletions(-) diff --git a/apps/probability/law_curve_view.h b/apps/probability/law_curve_view.h index b5b6217c7..393d87ee6 100644 --- a/apps/probability/law_curve_view.h +++ b/apps/probability/law_curve_view.h @@ -18,7 +18,7 @@ public: protected: char * label(Axis axis, int index) const override; private: - char m_labels[k_maxNumberOfXLabels][k_labelBufferSize]; + char m_labels[k_maxNumberOfXLabels][k_horizontalLabelBufferSize]; static float EvaluateAtAbscissa(float abscissa, void * model, void * context); Law * m_law; Calculation * m_calculation; diff --git a/apps/regression/graph_view.h b/apps/regression/graph_view.h index c53f997b0..3409e3407 100644 --- a/apps/regression/graph_view.h +++ b/apps/regression/graph_view.h @@ -15,8 +15,8 @@ public: private: char * label(Axis axis, int index) const override; Store * m_store; - char m_xLabels[k_maxNumberOfXLabels][k_labelBufferSize]; - char m_yLabels[k_maxNumberOfYLabels][k_labelBufferSize]; + char m_xLabels[k_maxNumberOfXLabels][k_horizontalLabelBufferSize]; + char m_yLabels[k_maxNumberOfYLabels][k_verticalLabelBufferSize]; Responder * m_controller; }; diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index adc10f3d9..6030b7504 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -140,8 +140,12 @@ void CurveView::computeLabels(Axis axis) { } /* Label cannot hold more than k_labelBufferSize characters to prevent them * from overprinting one another.*/ - PrintFloat::convertFloatToText(labelValue, label(axis, index), k_labelBufferSize, - Constant::ShortNumberOfSignificantDigits, Preferences::PrintFloatMode::Decimal); + PrintFloat::convertFloatToText( + labelValue, + label(axis, index), + axis == Axis::Vertical ? k_verticalLabelBufferSize : k_horizontalLabelBufferSize, + axis == Axis::Vertical ? 6 : Constant::ShortNumberOfSignificantDigits, + Preferences::PrintFloatMode::Decimal); } } diff --git a/apps/shared/curve_view.h b/apps/shared/curve_view.h index 8b741a902..7603f4260 100644 --- a/apps/shared/curve_view.h +++ b/apps/shared/curve_view.h @@ -41,14 +41,17 @@ protected: constexpr static KDCoordinate k_okVerticalMargin = 23; constexpr static KDCoordinate k_okHorizontalMargin = 10; constexpr static KDCoordinate k_labelGraduationLength = 6; - /* The labels are bounds by ±1E8 and ±1E-8 which in worse case can be written - * in 6 characters. - * To avoid overlapping labels, k_labelBufferSize should verify: - * k_labelBufferSize = Ion::Display::Width / ((CurveViewRange::k_maxNumberOfXGridUnits/2)*KDFont::SmallFont->glyphWidth) - * = 320/((18/2)*7) ~ 5. - * We take 6 creating small overlap in worse case but preventing from truncating - * labels (ie, "-1E-"). */ - constexpr static int k_labelBufferSize = 6; + /* The labels are bounds by ±1E-4 and ±1E-8 which in worst case can be written + * using 6 characters (including the null-terminating char). + * To avoid overlapping horizontal labels, k_horizontalLabelBufferSize should + * verify: + * k_horizontalLabelBufferSize = Ion::Display::Width / + * ((CurveViewRange::k_maxNumberOfXGridUnits/2)*KDFont::SmallFont->glyphWidth) + * = 320/((18/2)*7) ~ 5. + * We take 6, which creates a small overlap in worst cases but prevents from + * truncating labels (ie, "-1E-"). */ + constexpr static int k_horizontalLabelBufferSize = 6; + constexpr static int k_verticalLabelBufferSize = 14; // '-' + 6 significant digits + '.' + "E-" + 3 digits + null-terminating char constexpr static int k_maxNumberOfXLabels = CurveViewRange::k_maxNumberOfXGridUnits; constexpr static int k_maxNumberOfYLabels = CurveViewRange::k_maxNumberOfYGridUnits; constexpr static int k_externRectMargin = 2; diff --git a/apps/shared/function_graph_view.h b/apps/shared/function_graph_view.h index ebd780bd5..a96d09fdd 100644 --- a/apps/shared/function_graph_view.h +++ b/apps/shared/function_graph_view.h @@ -27,8 +27,8 @@ protected: bool m_shouldColorHighlighted; private: char * label(Axis axis, int index) const override; - char m_xLabels[k_maxNumberOfXLabels][k_labelBufferSize]; - char m_yLabels[k_maxNumberOfYLabels][k_labelBufferSize]; + char m_xLabels[k_maxNumberOfXLabels][k_horizontalLabelBufferSize]; + char m_yLabels[k_maxNumberOfYLabels][k_verticalLabelBufferSize]; Poincare::Context * m_context; }; diff --git a/apps/shared/storage_function_graph_view.h b/apps/shared/storage_function_graph_view.h index 40cc3e24e..3dafe390b 100644 --- a/apps/shared/storage_function_graph_view.h +++ b/apps/shared/storage_function_graph_view.h @@ -27,8 +27,8 @@ protected: bool m_shouldColorHighlighted; private: char * label(Axis axis, int index) const override; - char m_xLabels[k_maxNumberOfXLabels][k_labelBufferSize]; - char m_yLabels[k_maxNumberOfYLabels][k_labelBufferSize]; + char m_xLabels[k_maxNumberOfXLabels][k_horizontalLabelBufferSize]; + char m_yLabels[k_maxNumberOfYLabels][k_verticalLabelBufferSize]; Poincare::Context * m_context; }; diff --git a/apps/statistics/box_axis_view.h b/apps/statistics/box_axis_view.h index b22e0fc69..394daad65 100644 --- a/apps/statistics/box_axis_view.h +++ b/apps/statistics/box_axis_view.h @@ -20,7 +20,7 @@ public: private: constexpr static KDCoordinate k_axisMargin = 3; char * label(Axis axis, int index) const override; - char m_labels[k_maxNumberOfXLabels][k_labelBufferSize]; + char m_labels[k_maxNumberOfXLabels][k_horizontalLabelBufferSize]; BoxRange m_boxRange; }; diff --git a/apps/statistics/histogram_view.h b/apps/statistics/histogram_view.h index 1af1dad1f..8d47cfd5c 100644 --- a/apps/statistics/histogram_view.h +++ b/apps/statistics/histogram_view.h @@ -24,7 +24,7 @@ private: char * label(Axis axis, int index) const override; HistogramController * m_controller; Store * m_store; - char m_labels[k_maxNumberOfXLabels][k_labelBufferSize]; + char m_labels[k_maxNumberOfXLabels][k_horizontalLabelBufferSize]; static float EvaluateHistogramAtAbscissa(float abscissa, void * model, void * context); float m_highlightedBarStart; float m_highlightedBarEnd; From 78c277b1599111d9a442ecade7638085ed718b0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 5 Dec 2018 13:35:13 +0100 Subject: [PATCH 047/373] Fix comment typo --- poincare/include/poincare/print_float.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/include/poincare/print_float.h b/poincare/include/poincare/print_float.h index d2c435892..a73a17fe4 100644 --- a/poincare/include/poincare/print_float.h +++ b/poincare/include/poincare/print_float.h @@ -10,7 +10,7 @@ class Integer; namespace PrintFloat { constexpr static int bufferSizeForFloatsWithPrecision(int numberOfSignificantDigits) { - // The wors case is -1.234E-328 + // The worst case is -1.234E-328 return numberOfSignificantDigits + 8; } /* This function prints the integer i in the buffer with a '.' at the position From 2aa92ecffa2122dd22530e751f1cfc61caade1cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 5 Dec 2018 15:09:29 +0100 Subject: [PATCH 048/373] [apps] Add a proof for CurveViewRange::computeGridUnit's algorithm --- apps/shared/curve_view_range.cpp | 92 ++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 4 deletions(-) diff --git a/apps/shared/curve_view_range.cpp b/apps/shared/curve_view_range.cpp index 031830fd7..b539f3e8a 100644 --- a/apps/shared/curve_view_range.cpp +++ b/apps/shared/curve_view_range.cpp @@ -27,15 +27,99 @@ float CurveViewRange::computeGridUnit(Axis axis, float min, float max) { constexpr int unitsCount = 3; float units[unitsCount] = {k_smallGridUnitMantissa, k_mediumGridUnitMantissa, k_largeGridUnitMantissa}; for (int k = 0; k < unitsCount; k++) { - float unit = units[k]; - int b1 = std::floor(std::log10(d/(unit*maxNumberOfUnits))); - int b2 = std::floor(std::log10(d/(unit*minNumberOfUnits))); + float currentA = units[k]; + int b1 = std::floor(std::log10(d/(currentA*maxNumberOfUnits))); + int b2 = std::floor(std::log10(d/(currentA*minNumberOfUnits))); if (b1 != b2) { b = b2; - a = unit; + a = currentA; } } return a*std::pow(10.0f,b); + + /* Proof of the algorithm: + * + * We want to find gridUnit = a*10^b, with a in {1; 2; 5} and b an integer + * We want: minNumberOfUnits <= range/gridUnit < maxNumberOfUnits + * + * A solution thus needs to verify: + * + * minNumberOfUnits/range <= 1/(a*10^b) < maxNumberOfUnits/range + * => range/minNumberOfUnits >= a*10^b > range/maxNumberOfUnits + * => range/(a*minNumberOfUnits) >= 10^b > range/(a*maxNumberOfUnits) + * => log10(range/(a*minNumberOfUnits)) >= b > log10(range/(a*maxNumberOfUnits)) + * => (1) log10(range/(a*maxNumberOfUnits)) < b <= log10(range/(a*minNumberOfUnits)) + * And, because b must be an integer, + * => floor(log10(range/(a*maxNumberOfUnits))) != floor(log10(range/(a*minNumberOfUnits))) + * The solution is then b = floor(log10(range/(a*minNumberOfUnits))) + * + * Is there always at least one solution ? + * + * (1) also gives: + * E1 = log10(range)-log10(a)-log10(maxNumberOfUnits) < b <= log10(range)-log10(a)-log10(maxNumberOfUnits) = E2 + * + * Let's compute E2-E1: + * E2-E1 = log10(maxNumberOfUnits) - log10(minNumberOfUnits) + * For minNumberOfUnits=7 and maxNumberOfUnits=18, E2-E1 = 0.41... + * For minNumberOfUnits=5 and maxNumberOfUnits=13, E2-E1 = 0.41... + * + * Let's compute the union of the [E1;E2] for a in {1; 2; 5}: + * [E1;E2 for a=1] U [E1;E2 for a=2] U [E1;E2 for a=5] + * = [e1;e2] U [e1-log10(2); e2-log10(2)] U [e1-log10(5); e2-log10(5)] + * = [e1;e2] U [e1-0.3; e2-0.3] U [e1-0.7; e2-0.7] + * = [e1-0.7; e2-0.7] U [e1-0.3; e2-0.3] U [e1;e2] + * = [e1-0.7; e2] because e2-0.7 > e1-0.3 as e2-e1 > 0.7-0.3 and e2-e1 = E2-E1 = 0.41... + * and e2-0.3 > e1 as e2-e1 > 0.3 + * + * The union of the [E1;E2] for a in {1; 2; 5} is an interval of size + * e2-e1+0.7 = 1.1 > 1. + * We will thus always have at least one a in {1; 2; 5} for which E1 and E2 + * are on each side of an integer. + * + * Let's make a drawing. + * + * n n+1 n+2 n+3 n+4 n+5 + * |.........|.........|.........|.........|.........|... + * E1^---^E2 + * 0.41 + * * + * To have a solution, we need E1 and E2 to be on each side of an integer. + * + * -------------------------------------------------------------------------------------------- + * -------------------------------------------------------------------------------------------- + * + * If e1 - floor(e1) > 1-(e2-e1) = 0.58..., a=1 is a solution + * + * n n+0.2 n+0.4 n+0.6 n+0.8 n+1 + * .........||....|....|....|....|....|....|....|....|....|....||... a=1 + * e1^--------------------^e2 + * + * -------------------------------------------------------------------------------------------- + * -------------------------------------------------------------------------------------------- + * + * If log10(5)-(e2-e1) = 0.29... < e1 - floor(e1) < log10(5) = 0.69..., a=5 is a solution + * + * n n+0.2 n+0.4 n+0.6 n+0.8 n+1 + * .........||....|....|....|....|....|....|....|....|....|....||... + * e1^--------------------^e2 + * + * n n+0.2 n+0.4 n+0.6 n+0.8 n+1 + * .........||....|....|....|....|....|....|....|....|....|....||... a=5 + * E1^--------------------^E2 <- shift by log10(5) = 0.7 + * + * -------------------------------------------------------------------------------------------- + * -------------------------------------------------------------------------------------------- + * + * If e1 - floor(e1) < log10(2) = 0.3..., a=2 is a solution + * n n+0.2 n+0.4 n+0.6 n+0.8 n+1 + * .........||....|....|....|....|....|....|....|....|....|....||... + * e1^--------------------^e2 + * + * n n+0.2 n+0.4 n+0.6 n+0.8 n+1 + * .........||....|....|....|....|....|....|....|....|....|....||... a=2 + * E1^--------------------^E2 <- shift by log10(2) = 0.3 + * + * */ } } From f2310a881451c3a8f59f2c28f16797001801e973 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 5 Dec 2018 15:23:41 +0100 Subject: [PATCH 049/373] [apps] Change CurveViewRange::computeGridUnit parameters --- apps/probability/law/law.cpp | 2 +- apps/sequence/graph/curve_view_range.cpp | 12 ++++++------ apps/shared/curve_view_range.cpp | 7 +++---- apps/shared/curve_view_range.h | 2 +- .../shared/interactive_curve_view_range_delegate.cpp | 8 ++++---- apps/shared/memoized_curve_view_range.cpp | 8 ++++---- apps/statistics/box_range.cpp | 2 +- apps/statistics/histogram_controller.cpp | 2 +- 8 files changed, 21 insertions(+), 22 deletions(-) diff --git a/apps/probability/law/law.cpp b/apps/probability/law/law.cpp index 6540e4918..7e20b3b46 100644 --- a/apps/probability/law/law.cpp +++ b/apps/probability/law/law.cpp @@ -10,7 +10,7 @@ Law::Law() : } float Law::xGridUnit() { - return computeGridUnit(Axis::X, xMin(), xMax()); + return computeGridUnit(Axis::X, xMax() - xMin()); } double Law::cumulativeDistributiveFunctionAtAbscissa(double x) const { diff --git a/apps/sequence/graph/curve_view_range.cpp b/apps/sequence/graph/curve_view_range.cpp index 08aeed280..9bfa613c0 100644 --- a/apps/sequence/graph/curve_view_range.cpp +++ b/apps/sequence/graph/curve_view_range.cpp @@ -28,7 +28,7 @@ void CurveViewRange::roundAbscissa() { m_xMin = -k_displayLeftMarginRatio*(float)Ion::Display::Width; m_xMax = m_xMin+(float)Ion::Display::Width; } - m_xGridUnit = computeGridUnit(Axis::X, m_xMin, m_xMax); + m_xGridUnit = computeGridUnit(Axis::X, m_xMax - m_xMin); if (m_delegate) { m_delegate->didChangeRange(this); } @@ -44,7 +44,7 @@ void CurveViewRange::normalize() { if (!std::isnan(newXMin) && !std::isnan(newXMax)) { m_xMin = newXMin; m_xMax = newXMax; - m_xGridUnit = computeGridUnit(Axis::X, m_xMin, m_xMax); + m_xGridUnit = computeGridUnit(Axis::X, m_xMax - m_xMin); } if (m_xMin < 0.0f) { m_xMin = -k_displayLeftMarginRatio*2.0f*NormalizedXHalfRange(); @@ -56,7 +56,7 @@ void CurveViewRange::normalize() { if (!std::isnan(newYMin) && !std::isnan(newYMax)) { m_yMin = newYMin; m_yMax = newYMax; - m_yGridUnit = computeGridUnit(Axis::Y, m_yMin, m_yMax); + m_yGridUnit = computeGridUnit(Axis::Y, m_yMax - m_yMin); } } @@ -67,11 +67,11 @@ void CurveViewRange::setTrigonometric() { m_xMin = -k_displayLeftMarginRatio*1200; m_xMax = 1200; } - m_xGridUnit = computeGridUnit(Axis::X, m_xMin, m_xMax); + m_xGridUnit = computeGridUnit(Axis::X, m_xMax - m_xMin); m_yAuto = false; m_yMin = -1.6f; m_yMax = 1.6f; - m_yGridUnit = computeGridUnit(Axis::Y, m_yMin, m_yMax); + m_yGridUnit = computeGridUnit(Axis::Y, m_yMax - m_yMin); } void CurveViewRange::setDefault() { @@ -80,7 +80,7 @@ void CurveViewRange::setDefault() { } m_xMax = m_delegate->interestingXRange(); m_xMin = -k_displayLeftMarginRatio*m_xMax; - m_xGridUnit = computeGridUnit(Axis::X, m_xMin, m_xMax); + m_xGridUnit = computeGridUnit(Axis::X, m_xMax - m_xMin); setYAuto(true); } diff --git a/apps/shared/curve_view_range.cpp b/apps/shared/curve_view_range.cpp index b539f3e8a..cc23f94ab 100644 --- a/apps/shared/curve_view_range.cpp +++ b/apps/shared/curve_view_range.cpp @@ -18,18 +18,17 @@ float CurveViewRange::yGridUnit() { return 0.0f; } -float CurveViewRange::computeGridUnit(Axis axis, float min, float max) { +float CurveViewRange::computeGridUnit(Axis axis, float range) { int a = 0; int b = 0; - float d = max - min; float maxNumberOfUnits = (axis == Axis::X) ? k_maxNumberOfXGridUnits : k_maxNumberOfYGridUnits; float minNumberOfUnits = (axis == Axis::X) ? k_minNumberOfXGridUnits : k_minNumberOfYGridUnits; constexpr int unitsCount = 3; float units[unitsCount] = {k_smallGridUnitMantissa, k_mediumGridUnitMantissa, k_largeGridUnitMantissa}; for (int k = 0; k < unitsCount; k++) { float currentA = units[k]; - int b1 = std::floor(std::log10(d/(currentA*maxNumberOfUnits))); - int b2 = std::floor(std::log10(d/(currentA*minNumberOfUnits))); + int b1 = std::floor(std::log10(range/(currentA*maxNumberOfUnits))); + int b2 = std::floor(std::log10(range/(currentA*minNumberOfUnits))); if (b1 != b2) { b = b2; a = currentA; diff --git a/apps/shared/curve_view_range.h b/apps/shared/curve_view_range.h index f7ad4d42a..f72b0eb6b 100644 --- a/apps/shared/curve_view_range.h +++ b/apps/shared/curve_view_range.h @@ -19,7 +19,7 @@ public: virtual float yMax() = 0; virtual float xGridUnit() = 0; virtual float yGridUnit(); - float computeGridUnit(Axis axis, float min, float max); + float computeGridUnit(Axis axis, float range); constexpr static float k_maxNumberOfXGridUnits = 18.0f; constexpr static float k_maxNumberOfYGridUnits = 13.0f; private: diff --git a/apps/shared/interactive_curve_view_range_delegate.cpp b/apps/shared/interactive_curve_view_range_delegate.cpp index 45546fdd4..6f8742c7e 100644 --- a/apps/shared/interactive_curve_view_range_delegate.cpp +++ b/apps/shared/interactive_curve_view_range_delegate.cpp @@ -20,7 +20,7 @@ bool InteractiveCurveViewRangeDelegate::didChangeRange(InteractiveCurveViewRange return false; } if (min == max) { - float step = max != 0.0f ? interactiveCurveViewRange->computeGridUnit(CurveViewRange::Axis::Y, 0.0f, max) : 1.0f; + float step = max != 0.0f ? interactiveCurveViewRange->computeGridUnit(CurveViewRange::Axis::Y, max) : 1.0f; min = min - step; max = max + step; } @@ -29,11 +29,11 @@ bool InteractiveCurveViewRangeDelegate::didChangeRange(InteractiveCurveViewRange max = 1.0f; } if (min == FLT_MAX) { - float step = max != 0.0f ? interactiveCurveViewRange->computeGridUnit(CurveViewRange::Axis::Y, 0.0f, std::fabs(max)) : 1.0f; + float step = max != 0.0f ? interactiveCurveViewRange->computeGridUnit(CurveViewRange::Axis::Y, std::fabs(max)) : 1.0f; min = max-step; } - if (max == -FLT_MAX) { - float step = min != 0.0f ? interactiveCurveViewRange->computeGridUnit(CurveViewRange::Axis::Y, 0.0f, std::fabs(min)) : 1.0f; + if (max == -FLT_MAX) { + float step = min != 0.0f ? interactiveCurveViewRange->computeGridUnit(CurveViewRange::Axis::Y, std::fabs(min)) : 1.0f; max = min+step; } range = max - min; diff --git a/apps/shared/memoized_curve_view_range.cpp b/apps/shared/memoized_curve_view_range.cpp index 7e80aef5a..56f464154 100644 --- a/apps/shared/memoized_curve_view_range.cpp +++ b/apps/shared/memoized_curve_view_range.cpp @@ -47,7 +47,7 @@ void MemoizedCurveViewRange::setXMin(float xMin) { if (m_xMin >= m_xMax) { m_xMax = xMin + std::pow(10.0f, std::floor(std::log10(std::fabs(xMin)))-1.0f); } - m_xGridUnit = computeGridUnit(Axis::X, m_xMin, m_xMax); + m_xGridUnit = computeGridUnit(Axis::X, m_xMax - m_xMin); } void MemoizedCurveViewRange::setXMax(float xMax) { @@ -58,7 +58,7 @@ void MemoizedCurveViewRange::setXMax(float xMax) { if (m_xMin >= m_xMax) { m_xMin = xMax - std::pow(10.0f, std::floor(std::log10(std::fabs(xMax)))-1.0f); } - m_xGridUnit = computeGridUnit(Axis::X, m_xMin, m_xMax); + m_xGridUnit = computeGridUnit(Axis::X, m_xMax - m_xMin); } void MemoizedCurveViewRange::setYMin(float yMin) { @@ -69,7 +69,7 @@ void MemoizedCurveViewRange::setYMin(float yMin) { if (m_yMin >= m_yMax) { m_yMax = yMin + std::pow(10.0f, std::floor(std::log10(std::fabs(yMin)))-1.0f); } - m_yGridUnit = computeGridUnit(Axis::Y, m_yMin, m_yMax); + m_yGridUnit = computeGridUnit(Axis::Y, m_yMax - m_yMin); } void MemoizedCurveViewRange::setYMax(float yMax) { @@ -81,7 +81,7 @@ void MemoizedCurveViewRange::setYMax(float yMax) { m_yMin = yMax - + std::pow(10.0f, std::floor(std::log10(std::fabs(yMax)))-1.0f); } - m_yGridUnit = computeGridUnit(Axis::Y, m_yMin, m_yMax); + m_yGridUnit = computeGridUnit(Axis::Y, m_yMax - m_yMin); } } diff --git a/apps/statistics/box_range.cpp b/apps/statistics/box_range.cpp index f8a9c674d..1307acaf1 100644 --- a/apps/statistics/box_range.cpp +++ b/apps/statistics/box_range.cpp @@ -22,7 +22,7 @@ float BoxRange::xMax() { } float BoxRange::xGridUnit() { - return computeGridUnit(Axis::X, xMin(), xMax()); + return computeGridUnit(Axis::X, xMax() - xMin()); } } diff --git a/apps/statistics/histogram_controller.cpp b/apps/statistics/histogram_controller.cpp index 4414513ac..b4e1a22e9 100644 --- a/apps/statistics/histogram_controller.cpp +++ b/apps/statistics/histogram_controller.cpp @@ -250,7 +250,7 @@ void HistogramController::initBarParameters() { } maxValue = minValue >= maxValue ? minValue + std::pow(10.0f, std::floor(std::log10(std::fabs(minValue)))-1.0f) : maxValue; m_store->setFirstDrawnBarAbscissa(minValue); - float barWidth = m_store->computeGridUnit(CurveViewRange::Axis::X, minValue, maxValue); + float barWidth = m_store->computeGridUnit(CurveViewRange::Axis::X, maxValue - minValue); if (barWidth <= 0.0f) { barWidth = 1.0f; } From f62249c8ac770b1b455642049d806c39e887e4ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 6 Dec 2018 16:57:21 +0100 Subject: [PATCH 050/373] [poincare] Try to reduce the number of digits in print float We did not take into account the zeros ending the mantissa when computing a smaller required length. --- poincare/include/poincare/print_float.h | 2 +- poincare/src/print_float.cpp | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/poincare/include/poincare/print_float.h b/poincare/include/poincare/print_float.h index a73a17fe4..400b47076 100644 --- a/poincare/include/poincare/print_float.h +++ b/poincare/include/poincare/print_float.h @@ -47,7 +47,7 @@ namespace PrintFloat { template int convertFloatToText(T d, char * buffer, int bufferSize, int numberOfSignificantDigits, Preferences::PrintFloatMode mode); template - static int convertFloatToTextPrivate(T f, char * buffer, int numberOfSignificantDigits, Preferences::PrintFloatMode mode); + static int convertFloatToTextPrivate(T f, char * buffer, int numberOfSignificantDigits, Preferences::PrintFloatMode mode, int * numberOfRemovedZeros); } } diff --git a/poincare/src/print_float.cpp b/poincare/src/print_float.cpp index 369d8a1ee..33feeacb7 100644 --- a/poincare/src/print_float.cpp +++ b/poincare/src/print_float.cpp @@ -44,19 +44,20 @@ int PrintFloat::convertFloatToText(T f, char * buffer, int bufferSize, int numberOfSignificantDigits, Preferences::PrintFloatMode mode) { assert(numberOfSignificantDigits > 0); char tempBuffer[PrintFloat::k_maxFloatBufferLength]; - int requiredLength = convertFloatToTextPrivate(f, tempBuffer, numberOfSignificantDigits, mode); + int numberOfZerosRemoved = 0; + int requiredLength = convertFloatToTextPrivate(f, tempBuffer, numberOfSignificantDigits, mode, &numberOfZerosRemoved); /* if the required buffer size overflows the buffer size, we first force the * display mode to scientific and decrease the number of significant digits to * fit the buffer size. If the buffer size is still to small, we only write * the beginning of the float and truncate it (which can result in a non sense * text) */ if (mode == Preferences::PrintFloatMode::Decimal && requiredLength >= bufferSize) { - requiredLength = convertFloatToTextPrivate(f, tempBuffer, numberOfSignificantDigits, Preferences::PrintFloatMode::Scientific); + requiredLength = convertFloatToTextPrivate(f, tempBuffer, numberOfSignificantDigits, Preferences::PrintFloatMode::Scientific, &numberOfZerosRemoved); } if (requiredLength >= bufferSize) { - int adjustedNumberOfSignificantDigits = numberOfSignificantDigits - requiredLength + bufferSize - 1; + int adjustedNumberOfSignificantDigits = numberOfSignificantDigits - numberOfZerosRemoved - requiredLength + bufferSize - 1; adjustedNumberOfSignificantDigits = adjustedNumberOfSignificantDigits < 1 ? 1 : adjustedNumberOfSignificantDigits; - requiredLength = convertFloatToTextPrivate(f, tempBuffer, adjustedNumberOfSignificantDigits, Preferences::PrintFloatMode::Scientific); + requiredLength = convertFloatToTextPrivate(f, tempBuffer, adjustedNumberOfSignificantDigits, Preferences::PrintFloatMode::Scientific, &numberOfZerosRemoved); } requiredLength = requiredLength < bufferSize ? requiredLength : bufferSize-1; strlcpy(buffer, tempBuffer, bufferSize); @@ -64,7 +65,7 @@ int PrintFloat::convertFloatToText(T f, char * buffer, int bufferSize, } template -int PrintFloat::convertFloatToTextPrivate(T f, char * buffer, int numberOfSignificantDigits, Preferences::PrintFloatMode mode) { +int PrintFloat::convertFloatToTextPrivate(T f, char * buffer, int numberOfSignificantDigits, Preferences::PrintFloatMode mode, int * numberOfRemovedZeros) { assert(numberOfSignificantDigits > 0); if (std::isinf(f)) { assert(Infinity::NameSize()+1 < PrintFloat::k_maxFloatBufferLength); @@ -129,17 +130,22 @@ int PrintFloat::convertFloatToTextPrivate(T f, char * buffer, int numberOfSignif * that we stay beyond this threshold during computation. */ assert(numberOfSignificantDigits < std::log10(std::pow(2.0f, 63.0f))); - // Supress the 0 on the right side of the mantissa + // Remove the 0 on the right side of the mantissa Integer dividend = Integer((int64_t)mantissa); Integer quotient = Integer::Division(dividend, Integer(10)).quotient; Integer digit = Integer::Subtraction(dividend, Integer::Multiplication(quotient, Integer(10))); int minimumNumberOfCharsInMantissa = 1; + int numberOfZerosRemoved = 0; while (digit.isZero() && numberOfCharsForMantissaWithoutSign > minimumNumberOfCharsInMantissa && (numberOfCharsForMantissaWithoutSign > exponentInBase10+1 || mode == Preferences::PrintFloatMode::Scientific)) { numberOfCharsForMantissaWithoutSign--; dividend = quotient; quotient = Integer::Division(dividend, Integer(10)).quotient; digit = Integer::Subtraction(dividend, Integer::Multiplication(quotient, Integer(10))); + numberOfZerosRemoved++; + } + if (numberOfRemovedZeros != nullptr) { + *numberOfRemovedZeros = numberOfZerosRemoved; } /* Part II: Decimal marker */ @@ -192,4 +198,3 @@ template int PrintFloat::convertFloatToText(float, char*, int, int, Prefe template int PrintFloat::convertFloatToText(double, char*, int, int, Preferences::Preferences::PrintFloatMode); } - From 86409c771a0f69455c4e8a0afd5ea4aa7cb9c153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 13 Dec 2018 12:22:16 +0100 Subject: [PATCH 051/373] [poincare/expression] Add escape case on uninitialized expression --- poincare/src/expression.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 99a630389..9dd4ee761 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -428,6 +428,9 @@ U Expression::approximateToScalar(Context& context, Preferences::AngleUnit angle template U Expression::approximateToScalar(const char * text, Context& context, Preferences::AngleUnit angleUnit) { Expression exp = ParseAndSimplify(text, context, angleUnit); + if (exp.isUninitialized()) { + return NAN; + } return exp.approximateToScalar(context, angleUnit); } From 48bccac8de115ea83ccaf69c4bfc21992a251fac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 13 Dec 2018 13:51:40 +0100 Subject: [PATCH 052/373] [apps/probability] Clean class NormalLaw --- apps/probability/law/normal_law.cpp | 51 +++++++++-------------------- apps/probability/law/normal_law.h | 12 +++---- 2 files changed, 22 insertions(+), 41 deletions(-) diff --git a/apps/probability/law/normal_law.cpp b/apps/probability/law/normal_law.cpp index 37f1f2572..e1c240d53 100644 --- a/apps/probability/law/normal_law.cpp +++ b/apps/probability/law/normal_law.cpp @@ -7,41 +7,6 @@ namespace Probability { -NormalLaw::NormalLaw() : - TwoParameterLaw(0.0f, 1.0f) -{ -} - -I18n::Message NormalLaw::title() { - return I18n::Message::NormalLaw; -} - -Law::Type NormalLaw::type() const { - return Type::Normal; -} - -bool NormalLaw::isContinuous() const { - return true; -} - -I18n::Message NormalLaw::parameterNameAtIndex(int index) { - assert(index >= 0 && index < 2); - if (index == 0) { - return I18n::Message::Mu; - } else { - return I18n::Message::Sigma; - } -} - -I18n::Message NormalLaw::parameterDefinitionAtIndex(int index) { - assert(index >= 0 && index < 2); - if (index == 0) { - return I18n::Message::MeanDefinition; - } else { - return I18n::Message::DeviationDefinition; - } -} - float NormalLaw::xMin() { if (m_parameter2 == 0.0f) { return m_parameter1 - 1.0f; @@ -69,6 +34,22 @@ float NormalLaw::yMax() { return result*(1.0f+ k_displayTopMarginRatio); } +I18n::Message NormalLaw::parameterNameAtIndex(int index) { + if (index == 0) { + return I18n::Message::Mu; + } + assert(index == 1); + return I18n::Message::Sigma; +} + +I18n::Message NormalLaw::parameterDefinitionAtIndex(int index) { + if (index == 0) { + return I18n::Message::MeanDefinition; + } + assert(index == 1); + return I18n::Message::DeviationDefinition; +} + float NormalLaw::evaluateAtAbscissa(float x) const { if (m_parameter2 == 0.0f) { return NAN; diff --git a/apps/probability/law/normal_law.h b/apps/probability/law/normal_law.h index b346fb4c3..7816ddaa7 100644 --- a/apps/probability/law/normal_law.h +++ b/apps/probability/law/normal_law.h @@ -5,12 +5,12 @@ namespace Probability { -class NormalLaw : public TwoParameterLaw { +class NormalLaw final : public TwoParameterLaw { public: - NormalLaw(); - I18n::Message title() override; - Type type() const override; - bool isContinuous() const override; + NormalLaw() : TwoParameterLaw(0.0f, 1.0f) {} + I18n::Message title() override { return I18n::Message::NormalLaw; } + Type type() const override { return Type::Normal; } + bool isContinuous() const override { return true; } float xMin() override; float yMin() override; float xMax() override; @@ -24,7 +24,7 @@ public: double cumulativeDistributiveInverseForProbability(double * probability) override; private: constexpr static double k_maxRatioMuSigma = 1000.0f; - /* For the standard norma law, P(X < y) > 0.9999995 with y >= 4.892 so the + /* For the standard normal law, P(X < y) > 0.9999995 with y >= 4.892 so the * value displayed is 1. But this is dependent on the fact that we display * only 7 decimal values! */ static_assert(Constant::LargeNumberOfSignificantDigits == 7, "k_maxProbability is ill-defined compared to LargeNumberOfSignificantDigits"); From 8c6ffa6d42e6d6452a04101e46905c6401a717f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 21 Dec 2018 17:49:54 +0100 Subject: [PATCH 053/373] [apps] Fix graph X axis labels that read the same Scenario: just zoom in in a graph Fix: - Do not truncate labels. - Label size is computed depending on available size and number of labels. - If labels cannot be displayed properly, just display the minimal and maximal labels! --- apps/probability/law_curve_view.h | 2 +- apps/regression/graph_view.h | 4 +- apps/shared/curve_view.cpp | 110 +++++++++++++++++----- apps/shared/curve_view.h | 20 ++-- apps/shared/curve_view_range.cpp | 5 +- apps/shared/function_graph_view.h | 4 +- apps/shared/storage_function_graph_view.h | 4 +- apps/statistics/box_axis_view.h | 2 +- apps/statistics/histogram_view.h | 2 +- poincare/include/poincare/print_float.h | 2 +- poincare/src/print_float.cpp | 22 +++-- 11 files changed, 125 insertions(+), 52 deletions(-) diff --git a/apps/probability/law_curve_view.h b/apps/probability/law_curve_view.h index 393d87ee6..c4517f528 100644 --- a/apps/probability/law_curve_view.h +++ b/apps/probability/law_curve_view.h @@ -18,7 +18,7 @@ public: protected: char * label(Axis axis, int index) const override; private: - char m_labels[k_maxNumberOfXLabels][k_horizontalLabelBufferSize]; + char m_labels[k_maxNumberOfXLabels][k_labelBufferMaxSize]; static float EvaluateAtAbscissa(float abscissa, void * model, void * context); Law * m_law; Calculation * m_calculation; diff --git a/apps/regression/graph_view.h b/apps/regression/graph_view.h index 3409e3407..27fe89dc4 100644 --- a/apps/regression/graph_view.h +++ b/apps/regression/graph_view.h @@ -15,8 +15,8 @@ public: private: char * label(Axis axis, int index) const override; Store * m_store; - char m_xLabels[k_maxNumberOfXLabels][k_horizontalLabelBufferSize]; - char m_yLabels[k_maxNumberOfYLabels][k_verticalLabelBufferSize]; + char m_xLabels[k_maxNumberOfXLabels][k_labelBufferMaxSize]; + char m_yLabels[k_maxNumberOfYLabels][k_labelBufferMaxSize]; Responder * m_controller; }; diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index 6030b7504..370476992 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -1,16 +1,17 @@ #include "curve_view.h" #include "../constant.h" +#include #include #include #include #include -#include - using namespace Poincare; namespace Shared { +static inline int minInt(int x, int y) { return (x 0.0f || max(otherAxis) < 0.0f) { + return 0; + } + float minA = min(axis); + float maxA = max(axis); + float margin = labelsDisplayMarginRatio(axis) * (maxA - minA); + float minVisibleInAxis = minA + margin; + float maxVisibleInAxis = maxA - margin; + float labelStep = 2.0f * gridUnit(axis); + float minLabel = std::ceil(minVisibleInAxis/labelStep); + float maxLabel = std::floor(maxVisibleInAxis/labelStep); + return maxLabel - minLabel + 1; +} + float CurveView::pixelToFloat(Axis axis, KDCoordinate p) const { KDCoordinate pixels = axis == Axis::Horizontal ? p : pixelLength(axis)-p; return min(axis) + pixels*((float)(max(axis)-min(axis)))/((float)pixelLength(axis)); @@ -132,31 +149,55 @@ float CurveView::floatToPixel(Axis axis, float f) const { void CurveView::computeLabels(Axis axis) { float step = gridUnit(axis); - int labelsCount = numberOfLabels(axis); - for (int index = 0; index < labelsCount; index++) { - float labelValue = 2.0f*step*(std::ceil(min(axis)/(2.0f*step)))+index*2.0f*step; + int axisLabelsCount = numberOfLabels(axis); + for (int i = 0; i < axisLabelsCount; i++) { + float labelValue = labelValueAtIndex(axis, i); + /* Label cannot hold more than k_labelBufferMaxSize characters to prevent + * them from overprinting one another.*/ + int labelMaxSize = k_labelBufferMaxSize; + if (axis == Axis::Horizontal) { + float pixelsPerLabel = 320.0f/axisLabelsCount - 10; // 10 is a margin between the labels + labelMaxSize = minInt(k_labelBufferMaxSize, pixelsPerLabel/k_font->glyphSize().width()); + } + if (labelValue < step && labelValue > -step) { + // Make sure the 0 value is really written 0 labelValue = 0.0f; } + /* Label cannot hold more than k_labelBufferSize characters to prevent them * from overprinting one another.*/ + + char * labelBuffer = label(axis, i); PrintFloat::convertFloatToText( labelValue, - label(axis, index), - axis == Axis::Vertical ? k_verticalLabelBufferSize : k_horizontalLabelBufferSize, - axis == Axis::Vertical ? 6 : Constant::ShortNumberOfSignificantDigits, - Preferences::PrintFloatMode::Decimal); + labelBuffer, + labelMaxSize, + k_numberSignificantDigits, + Preferences::PrintFloatMode::Decimal, + axis == Axis::Vertical); + + if (labelBuffer[0] == 0 && axis == Axis::Horizontal) { + /* Some labels are too big and may overlap their neighbours. We write the + * extrema labels only. */ + computeHorizontalExtremaLabels(); + return; + } } } void CurveView::drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOrigin, bool graduationOnly, bool fixCoordinate, KDCoordinate fixedCoordinate) const { + int labelsCount = numberOfLabels(axis); + if (labelsCount < 1) { + return; + } float step = gridUnit(axis); - float start = 2.0f*step*(std::ceil(min(axis)/(2.0f*step))); - float end = max(axis); + float start = labelValueAtIndex(axis, 0); + float end = labelValueAtIndex(axis, labelsCount - 1); float verticalCoordinate = fixCoordinate ? fixedCoordinate : std::round(floatToPixel(Axis::Vertical, 0.0f)); float horizontalCoordinate = fixCoordinate ? fixedCoordinate : std::round(floatToPixel(Axis::Horizontal, 0.0f)); int i = 0; - for (float x = start; x < end; x += 2.0f*step) { + for (float x = start; x <= end + step; x += 2.0f*step) { /* When |start| >> step, start + step = start. In that case, quit the * infinite loop. */ if (x == x-step || x == x+step) { @@ -167,7 +208,7 @@ void CurveView::drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOr graduation = KDRect(horizontalCoordinate-(k_labelGraduationLength-2)/2, std::round(floatToPixel(Axis::Vertical, x)), k_labelGraduationLength, 1); } if (!graduationOnly) { - KDSize textSize = KDFont::SmallFont->stringSize(label(axis, i)); + KDSize textSize = k_font->stringSize(label(axis, i)); KDPoint origin(std::round(floatToPixel(Axis::Horizontal, x)) - textSize.width()/2, verticalCoordinate + k_labelMargin); if (axis == Axis::Vertical) { origin = KDPoint(horizontalCoordinate + k_labelMargin, std::round(floatToPixel(Axis::Vertical, x)) - textSize.height()/2); @@ -175,8 +216,8 @@ void CurveView::drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOr if (-step < x && x < step && shiftOrigin) { origin = KDPoint(horizontalCoordinate + k_labelMargin, verticalCoordinate + k_labelMargin); } - if (rect.intersects(KDRect(origin, KDFont::SmallFont->stringSize(label(axis, i))))) { - ctx->drawString(label(axis, i), origin, KDFont::SmallFont, KDColorBlack); + if (rect.intersects(KDRect(origin, k_font->stringSize(label(axis, i))))) { + ctx->drawString(label(axis, i), origin, k_font, KDColorBlack); } } ctx->fillRect(graduation, KDColorBlack); @@ -432,14 +473,6 @@ void CurveView::drawHistogram(KDContext * ctx, KDRect rect, EvaluateModelWithPar } } -int CurveView::numberOfLabels(Axis axis) const { - Axis otherAxis = axis == Axis::Horizontal ? Axis::Vertical : Axis::Horizontal; - if (min(otherAxis) > 0.0f || max(otherAxis) < 0.0f) { - return 0; - } - return std::ceil((max(axis) - min(axis))/(2*gridUnit(axis))); -} - void CurveView::jointDots(KDContext * ctx, KDRect rect, EvaluateModelWithParameter evaluation, void * model, void * context, float x, float y, float u, float v, KDColor color, int maxNumberOfRecursion) const { float pyf = floatToPixel(Axis::Vertical, y); float pvf = floatToPixel(Axis::Vertical, v); @@ -599,4 +632,35 @@ View * CurveView::subviewAtIndex(int index) { return m_bannerView; } +void CurveView::computeHorizontalExtremaLabels() { + Axis axis = Axis::Horizontal; + int axisLabelsCount = numberOfLabels(axis); + + // All labels but the extrema are empty + for (int i = 1; i < axisLabelsCount - 1 ; i++) { + label(axis, i)[0] = 0; + } + + int minMax[] = {0, axisLabelsCount-1}; + for (int i : minMax) { + // Compute the minimal and maximal label + PrintFloat::convertFloatToText( + labelValueAtIndex(axis, i), + label(axis, i), + k_labelBufferMaxSize, + k_numberSignificantDigits, + Preferences::PrintFloatMode::Decimal, + false); + } +} + +float CurveView::labelValueAtIndex(Axis axis, int i) const { + assert(i >= 0 && i < numberOfLabels(axis)); + float minA = min(axis); + float maxA = max(axis); + float labelStep = 2.0f * gridUnit(axis); + float minVisibleInAxis = minA + labelsDisplayMarginRatio(axis) * (maxA - minA); + return labelStep*(std::ceil(minVisibleInAxis/labelStep)+i); +} + } diff --git a/apps/shared/curve_view.h b/apps/shared/curve_view.h index 7603f4260..516716f00 100644 --- a/apps/shared/curve_view.h +++ b/apps/shared/curve_view.h @@ -11,6 +11,9 @@ namespace Shared { class CurveView : public View { public: + /* We want a 3 characters margin before the first label tick, so that most + * labels appear completely. This gives 3*charWidth/320 = 3*7/320= 0.066 */ + static constexpr float k_labelsHorizontalMarginRatio = 0.066f; typedef float (*EvaluateModelWithParameter)(float t, void * model, void * context); enum class Axis { Horizontal = 0, @@ -41,17 +44,8 @@ protected: constexpr static KDCoordinate k_okVerticalMargin = 23; constexpr static KDCoordinate k_okHorizontalMargin = 10; constexpr static KDCoordinate k_labelGraduationLength = 6; - /* The labels are bounds by ±1E-4 and ±1E-8 which in worst case can be written - * using 6 characters (including the null-terminating char). - * To avoid overlapping horizontal labels, k_horizontalLabelBufferSize should - * verify: - * k_horizontalLabelBufferSize = Ion::Display::Width / - * ((CurveViewRange::k_maxNumberOfXGridUnits/2)*KDFont::SmallFont->glyphWidth) - * = 320/((18/2)*7) ~ 5. - * We take 6, which creates a small overlap in worst cases but prevents from - * truncating labels (ie, "-1E-"). */ - constexpr static int k_horizontalLabelBufferSize = 6; - constexpr static int k_verticalLabelBufferSize = 14; // '-' + 6 significant digits + '.' + "E-" + 3 digits + null-terminating char + constexpr static int k_numberSignificantDigits = 6; + constexpr static int k_labelBufferMaxSize = 1 + k_numberSignificantDigits + 3 + 3 + 1; // '-' + 6 significant digits + '.' + "E-" + 3 digits + null-terminating char constexpr static int k_maxNumberOfXLabels = CurveViewRange::k_maxNumberOfXGridUnits; constexpr static int k_maxNumberOfYLabels = CurveViewRange::k_maxNumberOfYGridUnits; constexpr static int k_externRectMargin = 2; @@ -74,6 +68,7 @@ protected: View * m_bannerView; CurveViewCursor * m_curveViewCursor; private: + static constexpr const KDFont * k_font = KDFont::SmallFont; /* The window bounds are deduced from the model bounds but also take into account a margin (computed with k_marginFactor) */ float min(Axis axis) const; @@ -99,6 +94,9 @@ private: View * subviewAtIndex(int index) override; /* m_curveViewRange has to be non null but the cursor model, the banner and * cursor views may be nullptr if not needed. */ + void computeHorizontalExtremaLabels(); + float labelValueAtIndex(Axis axis, int i) const; + float labelsDisplayMarginRatio(Axis axis) const { return axis == Axis::Horizontal ? k_labelsHorizontalMarginRatio : 0.0f; } CurveViewRange * m_curveViewRange; View * m_cursorView; View * m_okView; diff --git a/apps/shared/curve_view_range.cpp b/apps/shared/curve_view_range.cpp index cc23f94ab..13dcd7fe3 100644 --- a/apps/shared/curve_view_range.cpp +++ b/apps/shared/curve_view_range.cpp @@ -1,4 +1,5 @@ #include "curve_view_range.h" +#include "curve_view.h" #include #include #include @@ -18,7 +19,9 @@ float CurveViewRange::yGridUnit() { return 0.0f; } -float CurveViewRange::computeGridUnit(Axis axis, float range) { +float CurveViewRange::computeGridUnit(Axis axis, float range1) { + float range = axis == Axis::Y ? range1 : ((1.0f-2.0f*CurveView::k_labelsHorizontalMarginRatio)*range1); + // TODO share the axis enum of curve_view and then call a static method CurveView::marginRatio(Axis) int a = 0; int b = 0; float maxNumberOfUnits = (axis == Axis::X) ? k_maxNumberOfXGridUnits : k_maxNumberOfYGridUnits; diff --git a/apps/shared/function_graph_view.h b/apps/shared/function_graph_view.h index a96d09fdd..34de2e4d2 100644 --- a/apps/shared/function_graph_view.h +++ b/apps/shared/function_graph_view.h @@ -27,8 +27,8 @@ protected: bool m_shouldColorHighlighted; private: char * label(Axis axis, int index) const override; - char m_xLabels[k_maxNumberOfXLabels][k_horizontalLabelBufferSize]; - char m_yLabels[k_maxNumberOfYLabels][k_verticalLabelBufferSize]; + char m_xLabels[k_maxNumberOfXLabels][k_labelBufferMaxSize]; + char m_yLabels[k_maxNumberOfYLabels][k_labelBufferMaxSize]; Poincare::Context * m_context; }; diff --git a/apps/shared/storage_function_graph_view.h b/apps/shared/storage_function_graph_view.h index 3dafe390b..97b5f6990 100644 --- a/apps/shared/storage_function_graph_view.h +++ b/apps/shared/storage_function_graph_view.h @@ -27,8 +27,8 @@ protected: bool m_shouldColorHighlighted; private: char * label(Axis axis, int index) const override; - char m_xLabels[k_maxNumberOfXLabels][k_horizontalLabelBufferSize]; - char m_yLabels[k_maxNumberOfYLabels][k_verticalLabelBufferSize]; + char m_xLabels[k_maxNumberOfXLabels][k_labelBufferMaxSize]; + char m_yLabels[k_maxNumberOfYLabels][k_labelBufferMaxSize]; Poincare::Context * m_context; }; diff --git a/apps/statistics/box_axis_view.h b/apps/statistics/box_axis_view.h index 394daad65..2fbfe0df8 100644 --- a/apps/statistics/box_axis_view.h +++ b/apps/statistics/box_axis_view.h @@ -20,7 +20,7 @@ public: private: constexpr static KDCoordinate k_axisMargin = 3; char * label(Axis axis, int index) const override; - char m_labels[k_maxNumberOfXLabels][k_horizontalLabelBufferSize]; + char m_labels[k_maxNumberOfXLabels][k_labelBufferMaxSize]; BoxRange m_boxRange; }; diff --git a/apps/statistics/histogram_view.h b/apps/statistics/histogram_view.h index 8d47cfd5c..32117ffde 100644 --- a/apps/statistics/histogram_view.h +++ b/apps/statistics/histogram_view.h @@ -24,7 +24,7 @@ private: char * label(Axis axis, int index) const override; HistogramController * m_controller; Store * m_store; - char m_labels[k_maxNumberOfXLabels][k_horizontalLabelBufferSize]; + char m_labels[k_maxNumberOfXLabels][k_labelBufferMaxSize]; static float EvaluateHistogramAtAbscissa(float abscissa, void * model, void * context); float m_highlightedBarStart; float m_highlightedBarEnd; diff --git a/poincare/include/poincare/print_float.h b/poincare/include/poincare/print_float.h index 400b47076..7509878b0 100644 --- a/poincare/include/poincare/print_float.h +++ b/poincare/include/poincare/print_float.h @@ -45,7 +45,7 @@ namespace PrintFloat { * ConvertFloatToText return the number of characters that have been written * in buffer (excluding the last \O character) */ template - int convertFloatToText(T d, char * buffer, int bufferSize, int numberOfSignificantDigits, Preferences::PrintFloatMode mode); + int convertFloatToText(T d, char * buffer, int bufferSize, int numberOfSignificantDigits, Preferences::PrintFloatMode mode, bool allowRounding = true); template static int convertFloatToTextPrivate(T f, char * buffer, int numberOfSignificantDigits, Preferences::PrintFloatMode mode, int * numberOfRemovedZeros); } diff --git a/poincare/src/print_float.cpp b/poincare/src/print_float.cpp index 33feeacb7..d6a3e3fdc 100644 --- a/poincare/src/print_float.cpp +++ b/poincare/src/print_float.cpp @@ -41,20 +41,28 @@ void PrintFloat::printBase10IntegerWithDecimalMarker(char * buffer, int bufferLe template int PrintFloat::convertFloatToText(T f, char * buffer, int bufferSize, - int numberOfSignificantDigits, Preferences::PrintFloatMode mode) { + int numberOfSignificantDigits, Preferences::PrintFloatMode mode, bool allowRounding) +{ assert(numberOfSignificantDigits > 0); + assert(bufferSize > 0); + char tempBuffer[PrintFloat::k_maxFloatBufferLength]; int numberOfZerosRemoved = 0; int requiredLength = convertFloatToTextPrivate(f, tempBuffer, numberOfSignificantDigits, mode, &numberOfZerosRemoved); - /* if the required buffer size overflows the buffer size, we first force the + /* If the required buffer size overflows the buffer size, we first force the * display mode to scientific and decrease the number of significant digits to - * fit the buffer size. If the buffer size is still to small, we only write - * the beginning of the float and truncate it (which can result in a non sense - * text) */ + * fit the buffer size. */ if (mode == Preferences::PrintFloatMode::Decimal && requiredLength >= bufferSize) { requiredLength = convertFloatToTextPrivate(f, tempBuffer, numberOfSignificantDigits, Preferences::PrintFloatMode::Scientific, &numberOfZerosRemoved); } if (requiredLength >= bufferSize) { + /* If the buffer size is still too small and rounding is allowed, we only + * write the beginning of the float and truncate it (which can result in a + * non sense text). If no rounding is allowed, we set the text to null. */ + if (!allowRounding) { + buffer[0] = 0; + return requiredLength; + } int adjustedNumberOfSignificantDigits = numberOfSignificantDigits - numberOfZerosRemoved - requiredLength + bufferSize - 1; adjustedNumberOfSignificantDigits = adjustedNumberOfSignificantDigits < 1 ? 1 : adjustedNumberOfSignificantDigits; requiredLength = convertFloatToTextPrivate(f, tempBuffer, adjustedNumberOfSignificantDigits, Preferences::PrintFloatMode::Scientific, &numberOfZerosRemoved); @@ -194,7 +202,7 @@ int PrintFloat::convertFloatToTextPrivate(T f, char * buffer, int numberOfSignif return (numberOfCharsForMantissaWithSign+1+numberOfCharExponent); } -template int PrintFloat::convertFloatToText(float, char*, int, int, Preferences::Preferences::PrintFloatMode); -template int PrintFloat::convertFloatToText(double, char*, int, int, Preferences::Preferences::PrintFloatMode); +template int PrintFloat::convertFloatToText(float, char*, int, int, Preferences::Preferences::PrintFloatMode, bool); +template int PrintFloat::convertFloatToText(double, char*, int, int, Preferences::Preferences::PrintFloatMode, bool); } From c14483b0e79199c75944040afefe50be784b5db3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 21 Dec 2018 17:57:34 +0100 Subject: [PATCH 054/373] [apps/shared] Clean some code in CurveViewRange --- apps/shared/curve_view.cpp | 4 ++-- apps/shared/curve_view.h | 2 +- apps/shared/curve_view_range.cpp | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index 370476992..55aaa8bf3 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -118,7 +118,7 @@ int CurveView::numberOfLabels(Axis axis) const { } float minA = min(axis); float maxA = max(axis); - float margin = labelsDisplayMarginRatio(axis) * (maxA - minA); + float margin = LabelsMarginRatio(axis) * (maxA - minA); float minVisibleInAxis = minA + margin; float maxVisibleInAxis = maxA - margin; float labelStep = 2.0f * gridUnit(axis); @@ -659,7 +659,7 @@ float CurveView::labelValueAtIndex(Axis axis, int i) const { float minA = min(axis); float maxA = max(axis); float labelStep = 2.0f * gridUnit(axis); - float minVisibleInAxis = minA + labelsDisplayMarginRatio(axis) * (maxA - minA); + float minVisibleInAxis = minA + LabelsMarginRatio(axis) * (maxA - minA); return labelStep*(std::ceil(minVisibleInAxis/labelStep)+i); } diff --git a/apps/shared/curve_view.h b/apps/shared/curve_view.h index 516716f00..c4dc1803d 100644 --- a/apps/shared/curve_view.h +++ b/apps/shared/curve_view.h @@ -36,6 +36,7 @@ public: void setOkView(View * okView); void setForceOkDisplay(bool force) { m_forceOkDisplay = force; } float resolution() const; + static float LabelsMarginRatio(Axis axis) { return axis == Axis::Horizontal ? k_labelsHorizontalMarginRatio : 0.0f; } protected: void setCurveViewRange(CurveViewRange * curveViewRange); // Drawing methods @@ -96,7 +97,6 @@ private: * cursor views may be nullptr if not needed. */ void computeHorizontalExtremaLabels(); float labelValueAtIndex(Axis axis, int i) const; - float labelsDisplayMarginRatio(Axis axis) const { return axis == Axis::Horizontal ? k_labelsHorizontalMarginRatio : 0.0f; } CurveViewRange * m_curveViewRange; View * m_cursorView; View * m_okView; diff --git a/apps/shared/curve_view_range.cpp b/apps/shared/curve_view_range.cpp index 13dcd7fe3..dd958a2d4 100644 --- a/apps/shared/curve_view_range.cpp +++ b/apps/shared/curve_view_range.cpp @@ -20,8 +20,8 @@ float CurveViewRange::yGridUnit() { } float CurveViewRange::computeGridUnit(Axis axis, float range1) { - float range = axis == Axis::Y ? range1 : ((1.0f-2.0f*CurveView::k_labelsHorizontalMarginRatio)*range1); - // TODO share the axis enum of curve_view and then call a static method CurveView::marginRatio(Axis) + float marginRatio = CurveView::LabelsMarginRatio(axis == Axis::X ? CurveView::Axis::Horizontal : CurveView::Axis::Vertical); + float range = range1 * (1.0f-2.0f*marginRatio); int a = 0; int b = 0; float maxNumberOfUnits = (axis == Axis::X) ? k_maxNumberOfXGridUnits : k_maxNumberOfYGridUnits; From d40b17a45e9d137446d083ce9fbe018d1e5c9eb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 27 Dec 2018 10:20:24 +0100 Subject: [PATCH 055/373] [apps] In curve view, draw the graduation even if the label is not drawn --- apps/shared/curve_view.cpp | 57 ++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index 55aaa8bf3..45286e67a 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -191,11 +191,37 @@ void CurveView::drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOr if (labelsCount < 1) { return; } + float step = gridUnit(axis); - float start = labelValueAtIndex(axis, 0); - float end = labelValueAtIndex(axis, labelsCount - 1); float verticalCoordinate = fixCoordinate ? fixedCoordinate : std::round(floatToPixel(Axis::Vertical, 0.0f)); float horizontalCoordinate = fixCoordinate ? fixedCoordinate : std::round(floatToPixel(Axis::Horizontal, 0.0f)); + + /* There might be less labels than graduations, if the extrema labels are too + * close to the screen edge to write them. We must thus draw the graduations + * separately from the labels. */ + + + // Draw the graduations + float start = 2.0f*step*(std::ceil(min(axis)/(2.0f*step))); + float end = max(axis); + for (float x = start; x <= end; x += 2.0f*step) { + /* When |start| >> step, start + step = start. In that case, quit the + * infinite loop. */ + if (x == x-step || x == x+step) { + return; + } + KDRect graduation = axis == Axis::Horizontal ? + KDRect(std::round(floatToPixel(Axis::Horizontal, x)), verticalCoordinate -(k_labelGraduationLength-2)/2, 1, k_labelGraduationLength) : + KDRect(horizontalCoordinate-(k_labelGraduationLength-2)/2, std::round(floatToPixel(Axis::Vertical, x)), k_labelGraduationLength, 1); + ctx->fillRect(graduation, KDColorBlack); + } + if (graduationOnly) { + return; + } + + // Draw the labels + start = labelValueAtIndex(axis, 0); + end = labelValueAtIndex(axis, labelsCount - 1); int i = 0; for (float x = start; x <= end + step; x += 2.0f*step) { /* When |start| >> step, start + step = start. In that case, quit the @@ -203,24 +229,19 @@ void CurveView::drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOr if (x == x-step || x == x+step) { return; } - KDRect graduation(std::round(floatToPixel(Axis::Horizontal, x)), verticalCoordinate -(k_labelGraduationLength-2)/2, 1, k_labelGraduationLength); - if (axis == Axis::Vertical) { - graduation = KDRect(horizontalCoordinate-(k_labelGraduationLength-2)/2, std::round(floatToPixel(Axis::Vertical, x)), k_labelGraduationLength, 1); + char * labelI = label(axis, i); + KDSize textSize = k_font->stringSize(labelI); + KDPoint origin = KDPointZero; + if (-step < x && x < step && shiftOrigin) { + origin = KDPoint(horizontalCoordinate + k_labelMargin, verticalCoordinate + k_labelMargin); + } else { + origin = axis == Axis::Horizontal ? + KDPoint(std::round(floatToPixel(Axis::Horizontal, x)) - textSize.width()/2, verticalCoordinate + k_labelMargin) : + KDPoint(horizontalCoordinate + k_labelMargin, std::round(floatToPixel(Axis::Vertical, x)) - textSize.height()/2); } - if (!graduationOnly) { - KDSize textSize = k_font->stringSize(label(axis, i)); - KDPoint origin(std::round(floatToPixel(Axis::Horizontal, x)) - textSize.width()/2, verticalCoordinate + k_labelMargin); - if (axis == Axis::Vertical) { - origin = KDPoint(horizontalCoordinate + k_labelMargin, std::round(floatToPixel(Axis::Vertical, x)) - textSize.height()/2); - } - if (-step < x && x < step && shiftOrigin) { - origin = KDPoint(horizontalCoordinate + k_labelMargin, verticalCoordinate + k_labelMargin); - } - if (rect.intersects(KDRect(origin, k_font->stringSize(label(axis, i))))) { - ctx->drawString(label(axis, i), origin, k_font, KDColorBlack); - } + if (rect.intersects(KDRect(origin, textSize))) { + ctx->drawString(labelI, origin, k_font, KDColorBlack); } - ctx->fillRect(graduation, KDColorBlack); i++; } } From 9ac32cf8fe811be0be7ec3422e87da361d5a6684 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 27 Dec 2018 10:35:20 +0100 Subject: [PATCH 056/373] [apps] Use standard variables in curve view --- apps/shared/curve_view.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index 45286e67a..879ddf5d9 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -156,7 +156,7 @@ void CurveView::computeLabels(Axis axis) { * them from overprinting one another.*/ int labelMaxSize = k_labelBufferMaxSize; if (axis == Axis::Horizontal) { - float pixelsPerLabel = 320.0f/axisLabelsCount - 10; // 10 is a margin between the labels + float pixelsPerLabel = ((float)Ion::Display::Width)/((float)axisLabelsCount) - k_labelMargin; labelMaxSize = minInt(k_labelBufferMaxSize, pixelsPerLabel/k_font->glyphSize().width()); } From 6b381957df47a6a82ff33c6a86ac5b1f0e87702b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 27 Dec 2018 11:28:32 +0100 Subject: [PATCH 057/373] [apps] Handle cut labels in curves. Draw all labels even if cut. If only the extrema horizontal labels are drawn, pick the labels 1 and numberOfLabels-2 if the real extrema labels will be cut. --- apps/shared/curve_view.cpp | 41 ++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index 879ddf5d9..9d60c99f0 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -116,20 +116,17 @@ int CurveView::numberOfLabels(Axis axis) const { if (min(otherAxis) > 0.0f || max(otherAxis) < 0.0f) { return 0; } - float minA = min(axis); - float maxA = max(axis); - float margin = LabelsMarginRatio(axis) * (maxA - minA); - float minVisibleInAxis = minA + margin; - float maxVisibleInAxis = maxA - margin; float labelStep = 2.0f * gridUnit(axis); - float minLabel = std::ceil(minVisibleInAxis/labelStep); - float maxLabel = std::floor(maxVisibleInAxis/labelStep); + float minLabel = std::ceil(min(axis)/labelStep); + float maxLabel = std::floor(max(axis)/labelStep); return maxLabel - minLabel + 1; } float CurveView::pixelToFloat(Axis axis, KDCoordinate p) const { - KDCoordinate pixels = axis == Axis::Horizontal ? p : pixelLength(axis)-p; - return min(axis) + pixels*((float)(max(axis)-min(axis)))/((float)pixelLength(axis)); + float pixelLen = pixelLength(axis); + float minA = min(axis); + KDCoordinate pixels = axis == Axis::Horizontal ? p : pixelLen - p; + return minA + pixels*(max(axis)-minA)/pixelLen; } float CurveView::floatToPixel(Axis axis, float f) const { @@ -656,13 +653,30 @@ View * CurveView::subviewAtIndex(int index) { void CurveView::computeHorizontalExtremaLabels() { Axis axis = Axis::Horizontal; int axisLabelsCount = numberOfLabels(axis); + float minA = min(axis); + + /* We want to draw the extrema labels (0 and numberOfLabels -1), but if they + * might not be fully visible, draw the labels 1 and numberOfLabels - 2. */ + bool skipExtremaLabels = + (axisLabelsCount >= 4) + && ((labelValueAtIndex(axis, 0) - minA)/(max(axis) - minA) < k_labelsHorizontalMarginRatio+FLT_EPSILON); + int firstLabel = skipExtremaLabels ? 1 : 0; + int lastLabel = axisLabelsCount - (skipExtremaLabels ? 2 : 1); + + assert(firstLabel != lastLabel); // All labels but the extrema are empty - for (int i = 1; i < axisLabelsCount - 1 ; i++) { + for (int i = 0; i < firstLabel; i++) { + label(axis, i)[0] = 0; + } + for (int i = firstLabel + 1; i < lastLabel; i++) { + label(axis, i)[0] = 0; + } + for (int i = lastLabel + 1; i < axisLabelsCount; i++) { label(axis, i)[0] = 0; } - int minMax[] = {0, axisLabelsCount-1}; + int minMax[] = {firstLabel, lastLabel}; for (int i : minMax) { // Compute the minimal and maximal label PrintFloat::convertFloatToText( @@ -677,11 +691,8 @@ void CurveView::computeHorizontalExtremaLabels() { float CurveView::labelValueAtIndex(Axis axis, int i) const { assert(i >= 0 && i < numberOfLabels(axis)); - float minA = min(axis); - float maxA = max(axis); float labelStep = 2.0f * gridUnit(axis); - float minVisibleInAxis = minA + LabelsMarginRatio(axis) * (maxA - minA); - return labelStep*(std::ceil(minVisibleInAxis/labelStep)+i); + return labelStep*(std::ceil(min(axis)/labelStep)+i); } } From fa24a4fd547af8b4e040da9e7c494054caf3f5e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 27 Dec 2018 11:49:51 +0100 Subject: [PATCH 058/373] [apps] Put the Y labels left of the Y axis --- apps/shared/curve_view.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index 9d60c99f0..604e7a159 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -230,11 +230,11 @@ void CurveView::drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOr KDSize textSize = k_font->stringSize(labelI); KDPoint origin = KDPointZero; if (-step < x && x < step && shiftOrigin) { - origin = KDPoint(horizontalCoordinate + k_labelMargin, verticalCoordinate + k_labelMargin); + origin = KDPoint(horizontalCoordinate - k_labelMargin - textSize.width(), verticalCoordinate + k_labelMargin); } else { origin = axis == Axis::Horizontal ? KDPoint(std::round(floatToPixel(Axis::Horizontal, x)) - textSize.width()/2, verticalCoordinate + k_labelMargin) : - KDPoint(horizontalCoordinate + k_labelMargin, std::round(floatToPixel(Axis::Vertical, x)) - textSize.height()/2); + KDPoint(horizontalCoordinate - k_labelMargin - textSize.width(), std::round(floatToPixel(Axis::Vertical, x)) - textSize.height()/2); } if (rect.intersects(KDRect(origin, textSize))) { ctx->drawString(labelI, origin, k_font, KDColorBlack); From fd34e83a564d37177b71fb8660c2889c07a7770a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 27 Dec 2018 16:14:50 +0100 Subject: [PATCH 059/373] [apps] In curve views, display floating labels when axes non visible --- apps/shared/curve_view.cpp | 112 ++++++++++++++++++++++++++----------- apps/shared/curve_view.h | 1 + 2 files changed, 81 insertions(+), 32 deletions(-) diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index 604e7a159..8b760d25e 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -10,7 +10,7 @@ using namespace Poincare; namespace Shared { -static inline int minInt(int x, int y) { return (x 0.0f || max(otherAxis) < 0.0f) { - return 0; - } float labelStep = 2.0f * gridUnit(axis); float minLabel = std::ceil(min(axis)/labelStep); float maxLabel = std::floor(max(axis)/labelStep); @@ -183,42 +179,73 @@ void CurveView::computeLabels(Axis axis) { } } +enum class FloatingPosition : uint8_t { + None, + Min, + Max +}; + void CurveView::drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOrigin, bool graduationOnly, bool fixCoordinate, KDCoordinate fixedCoordinate) const { - int labelsCount = numberOfLabels(axis); - if (labelsCount < 1) { - return; - } + assert(numberOfLabels(axis) > 1); float step = gridUnit(axis); float verticalCoordinate = fixCoordinate ? fixedCoordinate : std::round(floatToPixel(Axis::Vertical, 0.0f)); float horizontalCoordinate = fixCoordinate ? fixedCoordinate : std::round(floatToPixel(Axis::Horizontal, 0.0f)); + int viewHeight = bounds().height() - (bannerIsVisible() ? m_bannerView->minimalSizeForOptimalDisplay().height() : 0); + // If the axis is not visible, draw floating labels on the edge of the screen + FloatingPosition floatingLabels = FloatingPosition::None; + if (axis == Axis::Horizontal) { + Axis otherAxis = Axis::Vertical; + if (verticalCoordinate > viewHeight - k_font->glyphSize().height() - k_labelMargin) { + floatingLabels = FloatingPosition::Max; + } else if (max(otherAxis) < 0.0f) { + floatingLabels = FloatingPosition::Min; + } + } else { + Axis otherAxis = Axis::Horizontal; + if (horizontalCoordinate < k_labelMargin + k_font->glyphSize().width()*3) { // We want do display at least three characters left of the Y axis + floatingLabels = FloatingPosition::Min; + } else if (max(otherAxis) < 0.0f) { + floatingLabels = FloatingPosition::Max; + } + } /* There might be less labels than graduations, if the extrema labels are too * close to the screen edge to write them. We must thus draw the graduations * separately from the labels. */ - // Draw the graduations - float start = 2.0f*step*(std::ceil(min(axis)/(2.0f*step))); - float end = max(axis); - for (float x = start; x <= end; x += 2.0f*step) { - /* When |start| >> step, start + step = start. In that case, quit the - * infinite loop. */ - if (x == x-step || x == x+step) { - return; + if (floatingLabels == FloatingPosition::None) { + float start = 2.0f*step*(std::ceil(min(axis)/(2.0f*step))); + float end = max(axis); + for (float x = start; x <= end; x += 2.0f*step) { + /* When |start| >> step, start + step = start. In that case, quit the + * infinite loop. */ + if (x == x-step || x == x+step) { + return; + } + KDRect graduation = axis == Axis::Horizontal ? + KDRect( + std::round(floatToPixel(Axis::Horizontal, x)), + verticalCoordinate -(k_labelGraduationLength-2)/2, + 1, + k_labelGraduationLength) : + KDRect( + horizontalCoordinate-(k_labelGraduationLength-2)/2, + std::round(floatToPixel(Axis::Vertical, x)), + k_labelGraduationLength, + 1); + ctx->fillRect(graduation, KDColorBlack); } - KDRect graduation = axis == Axis::Horizontal ? - KDRect(std::round(floatToPixel(Axis::Horizontal, x)), verticalCoordinate -(k_labelGraduationLength-2)/2, 1, k_labelGraduationLength) : - KDRect(horizontalCoordinate-(k_labelGraduationLength-2)/2, std::round(floatToPixel(Axis::Vertical, x)), k_labelGraduationLength, 1); - ctx->fillRect(graduation, KDColorBlack); } + if (graduationOnly) { - return; - } + return; + } // Draw the labels - start = labelValueAtIndex(axis, 0); - end = labelValueAtIndex(axis, labelsCount - 1); + float start = labelValueAtIndex(axis, 0); + float end = labelValueAtIndex(axis, numberOfLabels(axis) - 1); int i = 0; for (float x = start; x <= end + step; x += 2.0f*step) { /* When |start| >> step, start + step = start. In that case, quit the @@ -228,14 +255,31 @@ void CurveView::drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOr } char * labelI = label(axis, i); KDSize textSize = k_font->stringSize(labelI); - KDPoint origin = KDPointZero; - if (-step < x && x < step && shiftOrigin) { - origin = KDPoint(horizontalCoordinate - k_labelMargin - textSize.width(), verticalCoordinate + k_labelMargin); + float xPosition = 0.0f; + float yPosition = 0.0f; + if (-step < x && x < step && shiftOrigin && floatingLabels == FloatingPosition::None) { + xPosition = horizontalCoordinate - k_labelMargin - textSize.width(); + yPosition = verticalCoordinate + k_labelMargin; + } else if (axis == Axis::Horizontal) { + xPosition = std::round(floatToPixel(Axis::Horizontal, x)) - textSize.width()/2; + if (floatingLabels == FloatingPosition::None) { + yPosition = verticalCoordinate + k_labelMargin; + } else if (floatingLabels == FloatingPosition::Min) { + yPosition = k_labelMargin; + } else { + yPosition = viewHeight - k_font->glyphSize().height() - k_labelMargin; + } } else { - origin = axis == Axis::Horizontal ? - KDPoint(std::round(floatToPixel(Axis::Horizontal, x)) - textSize.width()/2, verticalCoordinate + k_labelMargin) : - KDPoint(horizontalCoordinate - k_labelMargin - textSize.width(), std::round(floatToPixel(Axis::Vertical, x)) - textSize.height()/2); + yPosition = std::round(floatToPixel(Axis::Vertical, x)) - textSize.height()/2; + if (floatingLabels == FloatingPosition::None) { + xPosition = horizontalCoordinate - k_labelMargin - textSize.width(); + } else if (floatingLabels == FloatingPosition::Min) { + xPosition = k_labelMargin; + } else { + xPosition = Ion::Display::Width - textSize.width() - k_labelMargin; + } } + KDPoint origin = KDPoint(xPosition, yPosition); if (rect.intersects(KDRect(origin, textSize))) { ctx->drawString(labelI, origin, k_font, KDColorBlack); } @@ -606,7 +650,7 @@ KDRect CurveView::cursorFrame() { KDRect CurveView::bannerFrame() { KDRect bannerFrame = KDRectZero; - if (m_bannerView && m_mainViewSelected) { + if (bannerIsVisible()) { KDCoordinate bannerHeight = m_bannerView->minimalSizeForOptimalDisplay().height(); bannerFrame = KDRect(0, bounds().height()- bannerHeight, bounds().width(), bannerHeight); } @@ -695,4 +739,8 @@ float CurveView::labelValueAtIndex(Axis axis, int i) const { return labelStep*(std::ceil(min(axis)/labelStep)+i); } +bool CurveView::bannerIsVisible() const { + return m_bannerView && m_mainViewSelected; +} + } diff --git a/apps/shared/curve_view.h b/apps/shared/curve_view.h index c4dc1803d..7e295accc 100644 --- a/apps/shared/curve_view.h +++ b/apps/shared/curve_view.h @@ -97,6 +97,7 @@ private: * cursor views may be nullptr if not needed. */ void computeHorizontalExtremaLabels(); float labelValueAtIndex(Axis axis, int i) const; + bool bannerIsVisible() const; CurveViewRange * m_curveViewRange; View * m_cursorView; View * m_okView; From c4ce3c28e17e2e05201cdacf183378e47c9a5c09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 28 Nov 2018 11:02:59 +0100 Subject: [PATCH 060/373] [poincare] Factorial::sign is always positive --- poincare/include/poincare/factorial.h | 3 +++ poincare/src/factorial.cpp | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index 4d2b97d16..bc0461b3e 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -21,6 +21,9 @@ public: // Properties Type type() const override { return Type::Factorial; } + Sign sign() const override { return Sign::Positive; } + Expression setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override; + private: // Layout bool childNeedsParenthesis(const TreeNode * child) const override; diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index f730a2bef..c53ecd55a 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -12,6 +12,13 @@ namespace Poincare { +// Property + +Expression FactorialNode::setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) { + assert(s == Sign::Positive); + return Factorial(this); +} + // Layout bool FactorialNode::childNeedsParenthesis(const TreeNode * child) const { From 88a2751e6b07025a6c75d75f49c57f6b115d8468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 26 Nov 2018 16:59:38 +0100 Subject: [PATCH 061/373] [poincare] Add SignFunction class --- poincare/Makefile | 1 + poincare/include/poincare/expression.h | 1 + poincare/include/poincare/expression_node.h | 1 + poincare/include/poincare/sign_function.h | 57 +++++++++++++++ poincare/include/poincare_nodes.h | 1 + poincare/src/parsing/parser.h | 1 + poincare/src/sign_function.cpp | 81 +++++++++++++++++++++ poincare/src/tree_pool.cpp | 1 + poincare/test/function.cpp | 12 +++ 9 files changed, 156 insertions(+) create mode 100644 poincare/include/poincare/sign_function.h create mode 100644 poincare/src/sign_function.cpp diff --git a/poincare/Makefile b/poincare/Makefile index 4f5baca15..702c3dd78 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -112,6 +112,7 @@ objs += $(addprefix poincare/src/,\ round.o\ sequence.o\ serialization_helper.o\ + sign_function.o\ simplification_helper.o\ sine.o\ square_root.o\ diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 77a6a5fc4..b68c5debc 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -66,6 +66,7 @@ class Expression : public TreeHandle { friend class Product; friend class RealPart; friend class Round; + friend class SignFunction; friend class Sine; friend class SquareRoot; friend class Store; diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index 64d65bc67..85a3744e2 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -77,6 +77,7 @@ public: Randint, RealPart, Round, + SignFunction, SquareRoot, Subtraction, Sum, diff --git a/poincare/include/poincare/sign_function.h b/poincare/include/poincare/sign_function.h new file mode 100644 index 000000000..460108dcd --- /dev/null +++ b/poincare/include/poincare/sign_function.h @@ -0,0 +1,57 @@ +#ifndef POINCARE_SIGN_FUNCTION_H +#define POINCARE_SIGN_FUNCTION_H + +#include +#include + +namespace Poincare { + +class SignFunctionNode final : public ExpressionNode { +public: + + // TreeNode + size_t size() const override { return sizeof(SignFunctionNode); } + int numberOfChildren() const override; +#if POINCARE_TREE_LOG + virtual void logNodeName(std::ostream & stream) const override { + stream << "SignFunction"; + } +#endif + + // Properties + Type type() const override { return Type::SignFunction; } + Sign sign() const override; + Expression setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override; +private: + // Layout + Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; + int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; + // Simplification + Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + // Evaluation + template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + } +}; + +class SignFunction final : public Expression { +public: + SignFunction(const SignFunctionNode * n) : Expression(n) {} + static SignFunction Builder(Expression child) { return SignFunction(child); } + static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("sign", 1, &UntypedBuilder); + + Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); +private: + explicit SignFunction(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { + replaceChildAtIndexInPlace(0, child); + } +}; + +} + +#endif diff --git a/poincare/include/poincare_nodes.h b/poincare/include/poincare_nodes.h index 5020ecace..0315fd467 100644 --- a/poincare/include/poincare_nodes.h +++ b/poincare/include/poincare_nodes.h @@ -67,6 +67,7 @@ #include #include #include +#include #include #include #include diff --git a/poincare/src/parsing/parser.h b/poincare/src/parsing/parser.h index f85d00171..ca3d28b05 100644 --- a/poincare/src/parsing/parser.h +++ b/poincare/src/parsing/parser.h @@ -127,6 +127,7 @@ private: &DivisionRemainder::s_functionHelper, &NthRoot::s_functionHelper, &Round::s_functionHelper, + &SignFunction::s_functionHelper, &Sine::s_functionHelper, &HyperbolicSine::s_functionHelper, &Sum::s_functionHelper, diff --git a/poincare/src/sign_function.cpp b/poincare/src/sign_function.cpp new file mode 100644 index 000000000..34a56f61f --- /dev/null +++ b/poincare/src/sign_function.cpp @@ -0,0 +1,81 @@ +#include +#include +#include +#include +#include +#include +#include + +namespace Poincare { + +constexpr Expression::FunctionHelper SignFunction::s_functionHelper; + +int SignFunctionNode::numberOfChildren() const { return SignFunction::s_functionHelper.numberOfChildren(); } + +ExpressionNode::Sign SignFunctionNode::sign() const { + return childAtIndex(0)->sign(); +} + +Expression SignFunctionNode::setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) { + SignFunction sign(this); + Rational r(s == ExpressionNode::Sign::Positive ? 1 : -1); + sign.replaceWithInPlace(r); + return r; +} + +Layout SignFunctionNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::Prefix(SignFunction(this), floatDisplayMode, numberOfSignificantDigits, SignFunction::s_functionHelper.name()); +} + +int SignFunctionNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, SignFunction::s_functionHelper.name()); +} + +Expression SignFunctionNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return SignFunction(this).shallowReduce(context, angleUnit); +} + +template +Complex SignFunctionNode::computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { + if (c.imag() != 0) { + return Complex::Undefined(); + } + if (signbit(c.real())) { + return Complex(-1.0); + } + return Complex(1.0); +} + +Expression SignFunction::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { + { + Expression e = Expression::defaultShallowReduce(context, angleUnit); + if (e.isUndefined()) { + return e; + } + } +#if MATRIX_EXACT_REDUCING + if (c.type() == ExpressionNode::Type::Matrix) { + return SimplificationHelper::Map(*this, context, angleUnit); + } +#endif + Rational one(1); + if (childAtIndex(0).sign() != ExpressionNode::Sign::Unknown) { + if (childAtIndex(0).sign() == ExpressionNode::Sign::Negative) { + one = Rational(-1); + } + } else { + Evaluation childApproximated = childAtIndex(0).node()->approximate(1.0f, context, angleUnit); + assert(childApproximated.type() == EvaluationNode::Type::Complex); + Complex c = static_cast&>(childApproximated); + if (std::isnan(c.imag()) || std::isnan(c.real()) || c.imag() != 0) { + return *this; + } + if (c.real() < 0) { + one = Rational(-1); + } + } + replaceWithInPlace(one); + return one; +} + +} diff --git a/poincare/src/tree_pool.cpp b/poincare/src/tree_pool.cpp index 17b476f53..35a6ab825 100644 --- a/poincare/src/tree_pool.cpp +++ b/poincare/src/tree_pool.cpp @@ -272,6 +272,7 @@ template RandomNode * Poincare::TreePool::createTreeNode(size_t size template RationalNode * Poincare::TreePool::createTreeNode(size_t size); template RealPartNode * Poincare::TreePool::createTreeNode(size_t size); template RoundNode * Poincare::TreePool::createTreeNode(size_t size); +template SignFunctionNode * Poincare::TreePool::createTreeNode(size_t size); template SineNode * Poincare::TreePool::createTreeNode(size_t size); template SquareRootNode * Poincare::TreePool::createTreeNode(size_t size); template SubtractionNode * Poincare::TreePool::createTreeNode(size_t size); diff --git a/poincare/test/function.cpp b/poincare/test/function.cpp index c3b4cae9a..8c711a7b5 100644 --- a/poincare/test/function.cpp +++ b/poincare/test/function.cpp @@ -54,6 +54,7 @@ QUIZ_CASE(poincare_parse_function) { assert_parsed_expression_type("root(2,3)", ExpressionNode::Type::NthRoot); assert_parsed_expression_type("R(2)", ExpressionNode::Type::SquareRoot); assert_parsed_expression_type("round(2,3)", ExpressionNode::Type::Round); + assert_parsed_expression_type("sign(3)", ExpressionNode::Type::SignFunction); assert_parsed_expression_type("sum(n,n, 4, 10)", ExpressionNode::Type::Sum); #if MATRICES_ARE_DEFINED assert_parsed_expression_type("trace([[1,2,3][4,5,6][7,8,9]])", ExpressionNode::Type::MatrixTrace); @@ -191,6 +192,10 @@ QUIZ_CASE(poincare_function_evaluate) { assert_parsed_expression_evaluates_to("R(3+I)", "1.755317+0.2848488*I"); assert_parsed_expression_evaluates_to("R(3+I)", "1.7553173018244+2.8484878459314E-1*I"); + assert_parsed_expression_evaluates_to("sign(-23+1)", "-1"); + assert_parsed_expression_evaluates_to("sign(x)", "undef"); + assert_parsed_expression_evaluates_to("sign(2+I)", "undef"); + assert_parsed_expression_evaluates_to("sum(2+n*I,n,1,5)", "10+15*I"); assert_parsed_expression_evaluates_to("sum(2+n*I,n,1,5)", "10+15*I"); @@ -263,6 +268,13 @@ QUIZ_CASE(poincare_function_simplify) { assert_parsed_expression_simplify_to("round(4.9,0)", "5"); assert_parsed_expression_simplify_to("round(12.9,-1)", "10"); assert_parsed_expression_simplify_to("round(12.9,-2)", "0"); + assert_parsed_expression_simplify_to("sign(-23)", "-1"); + assert_parsed_expression_simplify_to("sign(-I)", "sign(-I)"); + assert_parsed_expression_simplify_to("sign(23)", "1"); + assert_parsed_expression_simplify_to("sign(log(18))", "1"); + assert_parsed_expression_simplify_to("sign(-R(2))", "-1"); + assert_parsed_expression_simplify_to("sign(x)", "sign(x)"); + assert_parsed_expression_simplify_to("sign(2+I)", "sign(2+I)"); assert_parsed_expression_simplify_to("permute(99,4)", "90345024"); assert_parsed_expression_simplify_to("permute(20,-10)", Undefined::Name()); assert_parsed_expression_simplify_to("re(1/2)", "1/2"); From f8f365268750a003a156e771203158c5242141c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 26 Nov 2018 17:14:14 +0100 Subject: [PATCH 062/373] [poincare] Expression: add radianToDegree and degreeToRadian methods --- poincare/include/poincare/expression.h | 2 ++ poincare/src/expression.cpp | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index b68c5debc..7b37c9e25 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -175,6 +175,8 @@ public: Expression simplify(Context & context, Preferences::AngleUnit angleUnit); Expression reduce(Context & context, Preferences::AngleUnit angleUnit); static Expression ExpressionWithoutSymbols(Expression expressionWithSymbols, Context & context); + Expression radianToDegree(); + Expression degreeToRadian(); /* Approximation Helper */ template static U epsilon(); diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 9dd4ee761..6cd75323c 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -378,6 +378,14 @@ Expression Expression::ExpressionWithoutSymbols(Expression e, Context & context) return e; } +Expression Expression::radianToDegree() { + return Multiplication(*this, Division(Rational(180), Constant(Ion::Charset::SmallPi))); +} + +Expression Expression::degreeToRadian( ) { + return Multiplication(*this, Division(Constant(Ion::Charset::SmallPi), Rational(180))); +} + Expression Expression::reduce(Context & context, Preferences::AngleUnit angleUnit) { sSimplificationHasBeenInterrupted = false; return deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); From 0c1e76c9c5979653d239f6a0d056bc3734e9a9a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 26 Nov 2018 17:14:35 +0100 Subject: [PATCH 063/373] [poincare] Expression: add methods to get complex parts of expression --- poincare/include/poincare/expression.h | 6 +++ poincare/include/poincare/expression_node.h | 6 +++ poincare/src/expression_node.cpp | 48 ++++++++++++++++++++- 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 7b37c9e25..13fa788a8 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -159,6 +159,12 @@ public: Expression replaceUnknown(const Symbol & symbol); Expression defaultReplaceUnknown(const Symbol & symbol); + /* Complex */ + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const { return node()->realPart(context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const { return node()->imaginaryPart(context, angleUnit); } + Expression complexNorm(Context & context, Preferences::AngleUnit angleUnit) const { return node()->complexNorm(context, angleUnit); } + Expression complexArgument(Context & context, Preferences::AngleUnit angleUnit) const { return node()->complexArgument(context, angleUnit); } + /* Comparison */ /* isIdenticalTo is the "easy" equality, it returns true if both trees have * same structures and all their nodes have same types and values (ie, diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index 85a3744e2..d13c2ab8c 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -115,6 +115,12 @@ public: virtual float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const; bool isOfType(Type * types, int length) const; + /* Complex */ + virtual Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const; + virtual Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const; + virtual Expression complexNorm(Context & context, Preferences::AngleUnit angleUnit) const; + virtual Expression complexArgument(Context & context, Preferences::AngleUnit angleUnit) const; + /* Simplification */ /* SimplificationOrder returns: * 1 if e1 > e2 diff --git a/poincare/src/expression_node.cpp b/poincare/src/expression_node.cpp index 446b7caa5..e45906e11 100644 --- a/poincare/src/expression_node.cpp +++ b/poincare/src/expression_node.cpp @@ -1,6 +1,14 @@ #include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include namespace Poincare { @@ -63,6 +71,44 @@ float ExpressionNode::characteristicXRange(Context & context, Preferences::Angle return range; } +Expression ExpressionNode::realPart(Context & context, Preferences::AngleUnit angleUnit) const { + return Expression(); +} + +Expression ExpressionNode::imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const { + return Expression(); +} + +Expression ExpressionNode::complexNorm(Context & context, Preferences::AngleUnit angleUnit) const { + Expression a = realPart(context, angleUnit); + Expression b = imaginaryPart(context, angleUnit); + if (!a.isUninitialized() && !b.isUninitialized()) { + // sqrt(a^2+b^2) + return SquareRoot::Builder(Addition(Power(a, Rational(2)), Power(b, Rational(2)))); + } + return Expression(); +} + +Expression ExpressionNode::complexArgument(Context & context, Preferences::AngleUnit angleUnit) const { + Expression a = realPart(context, angleUnit); + Expression b = imaginaryPart(context, angleUnit); + if (!a.isUninitialized() && !b.isUninitialized()) { + if (b.type() != Type::Rational || !static_cast(b).isZero()) { + // arctan(a/b) or (180/Pi)*arctan(a/b) + Expression arcTangent = ArcTangent::Builder(Division(a, b.clone())); + if (angleUnit == Preferences::AngleUnit::Degree) { + arcTangent = arcTangent.degreeToRadian(); + } + // sign(b) * Pi/2 - arctan(a/b) + return Subtraction(Multiplication(SignFunction::Builder(b), Division(Constant(Ion::Charset::SmallPi), Rational(2))), arcTangent); + } else { + // (1-sign(a))*Pi/2 + return Multiplication(Subtraction(Rational(1), SignFunction::Builder(a)), Division(Constant(Ion::Charset::SmallPi), Rational(2))); + } + } + return Expression(); +} + int ExpressionNode::SimplificationOrder(const ExpressionNode * e1, const ExpressionNode * e2, bool canBeInterrupted) { if (e1->type() > e2->type()) { if (canBeInterrupted && Expression::shouldStopProcessing()) { From 0e1825817b6f8d9f576dbb1bee7e6d20ca52d7ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 27 Nov 2018 14:03:08 +0100 Subject: [PATCH 064/373] [poincare] Test: clean helper Create a method expressions_are_equal --- poincare/test/helper.cpp | 24 ++++++++++++++---------- poincare/test/helper.h | 1 + 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/poincare/test/helper.cpp b/poincare/test/helper.cpp index 02a62367d..5cb153315 100644 --- a/poincare/test/helper.cpp +++ b/poincare/test/helper.cpp @@ -28,6 +28,19 @@ const char * BigOverflowedIntegerString() { return s; } +bool expressions_are_equal(Poincare::Expression expected, Poincare::Expression got) { + bool identical = expected.isIdenticalTo(got); +#if POINCARE_TREE_LOG + if (!identical) { + std::cout << "Expecting" << std::endl; + expected.log(); + std::cout << "Got" << std::endl; + got.log(); + } +#endif + return identical; +} + void translate_in_special_chars(char * expression) { for (char *c = expression; *c; c++) { switch (*c) { @@ -87,16 +100,7 @@ void assert_parsed_expression_type(const char * expression, Poincare::Expression void assert_parsed_expression_is(const char * expression, Poincare::Expression r) { Expression e = parse_expression(expression); - bool identical = e.isIdenticalTo(r); -#if POINCARE_TREE_LOG - if (!identical) { - std::cout << "Expecting" << std::endl; - r.log(); - std::cout << "Got" << std::endl; - e.log(); - } -#endif - quiz_assert(identical); + quiz_assert(expressions_are_equal(r, e)); } void assert_parsed_expression_polynomial_degree(const char * expression, int degree, const char * symbolName) { diff --git a/poincare/test/helper.h b/poincare/test/helper.h index 1792f36bf..bb31e28d9 100644 --- a/poincare/test/helper.h +++ b/poincare/test/helper.h @@ -15,6 +15,7 @@ constexpr Poincare::Preferences::ComplexFormat Polar = Poincare::Preferences::Co constexpr Poincare::Preferences::PrintFloatMode DecimalMode = Poincare::Preferences::PrintFloatMode::Decimal; constexpr Poincare::Preferences::PrintFloatMode ScientificMode = Poincare::Preferences::PrintFloatMode::Scientific; +bool expressions_are_equal(Poincare::Expression expected, Poincare::Expression got); void translate_in_special_chars(char * expression); void translate_in_ASCII_chars(char * expression); Poincare::Expression parse_expression(const char * expression, bool canBeUnparsable = false); From d95585956ca69c4f0ef34711e593408a8f30f123 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 27 Nov 2018 18:13:20 +0100 Subject: [PATCH 065/373] [poincare] Implement Expression::realPart, Expression::imaginaryPart, Expression::complexNorm, Expression::complexArgument --- poincare/Makefile | 2 + poincare/include/poincare/absolute_value.h | 6 + poincare/include/poincare/addition.h | 6 + poincare/include/poincare/arc_tangent.h | 9 ++ .../include/poincare/binomial_coefficient.h | 5 +- poincare/include/poincare/ceiling.h | 5 + poincare/include/poincare/complex_argument.h | 4 + poincare/include/poincare/complex_helper.h | 32 ++++ .../include/poincare/confidence_interval.h | 5 + poincare/include/poincare/conjugate.h | 3 + poincare/include/poincare/constant.h | 4 + poincare/include/poincare/cosine.h | 5 + poincare/include/poincare/decimal.h | 1 + poincare/include/poincare/derivative.h | 5 + poincare/include/poincare/division.h | 8 + poincare/include/poincare/division_quotient.h | 5 + .../include/poincare/division_remainder.h | 5 + poincare/include/poincare/expression.h | 1 + poincare/include/poincare/factorial.h | 5 +- poincare/include/poincare/floor.h | 6 + poincare/include/poincare/frac_part.h | 6 + poincare/include/poincare/function.h | 4 + .../include/poincare/great_common_divisor.h | 4 + poincare/include/poincare/imaginary_part.h | 5 + poincare/include/poincare/integral.h | 4 + .../include/poincare/least_common_multiple.h | 5 + poincare/include/poincare/matrix_dimension.h | 5 + poincare/include/poincare/multiplication.h | 8 + poincare/include/poincare/nth_root.h | 9 ++ poincare/include/poincare/number.h | 5 + poincare/include/poincare/opposite.h | 7 + poincare/include/poincare/parenthesis.h | 4 + .../include/poincare/permute_coefficient.h | 6 + poincare/include/poincare/power.h | 8 + .../include/poincare/prediction_interval.h | 5 + poincare/include/poincare/randint.h | 6 + poincare/include/poincare/random.h | 5 + poincare/include/poincare/real_part.h | 5 + poincare/include/poincare/round.h | 6 + poincare/include/poincare/sign_function.h | 6 + poincare/include/poincare/sine.h | 5 + poincare/include/poincare/square_root.h | 7 +- poincare/include/poincare/subtraction.h | 7 + poincare/include/poincare/symbol.h | 4 + poincare/include/poincare/tangent.h | 4 + poincare/include/poincare/undefined.h | 4 + poincare/src/addition.cpp | 14 ++ poincare/src/complex_helper.cpp | 44 ++++++ poincare/src/conjugate.cpp | 13 ++ poincare/src/constant.cpp | 15 ++ poincare/src/division.cpp | 18 +++ poincare/src/function.cpp | 18 +++ poincare/src/multiplication.cpp | 26 +++ poincare/src/nth_root.cpp | 26 +++ poincare/src/opposite.cpp | 8 + poincare/src/power.cpp | 22 +++ poincare/src/square_root.cpp | 19 +++ poincare/src/subtraction.cpp | 10 ++ poincare/src/symbol.cpp | 18 +++ poincare/test/complex.cpp | 149 ++++++++++++++++++ poincare/test/helper.cpp | 1 + poincare/test/helper.h | 2 +- 62 files changed, 665 insertions(+), 4 deletions(-) create mode 100644 poincare/include/poincare/complex_helper.h create mode 100644 poincare/src/complex_helper.cpp create mode 100644 poincare/test/complex.cpp diff --git a/poincare/Makefile b/poincare/Makefile index 702c3dd78..a30d17d52 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -49,6 +49,7 @@ objs += $(addprefix poincare/src/,\ ceiling.o\ complex.o\ complex_argument.o\ + complex_helper.o\ confidence_interval.o\ conjugate.o\ constant.o\ @@ -141,6 +142,7 @@ tests += $(addprefix poincare/test/,\ addition.cpp\ arithmetic.cpp\ binomial_coefficient_layout.cpp\ + complex.cpp\ complex_to_expression.cpp\ convert_expression_to_text.cpp\ decimal.cpp\ diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 3f8d5d546..819f8a4ac 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -2,7 +2,9 @@ #define POINCARE_ABSOLUTE_VALUE_H #include +#include #include +#include namespace Poincare { @@ -22,6 +24,10 @@ public: Sign sign() const override { return Sign::Positive; } Expression setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override; + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + // Approximation template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { return Complex(std::abs(c)); diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index ca822b7a5..2956351c5 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -27,6 +27,10 @@ public: int polynomialDegree(Context & context, const char * symbolName) const override; int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const override; + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPart(context, angleUnit, true); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPart(context, angleUnit, false); } + // Evaluation template static Complex compute(const std::complex c, const std::complex d) { return Complex(c+d); } template static MatrixComplex computeOnMatrices(const MatrixComplex m, const MatrixComplex n) { @@ -36,6 +40,8 @@ public: return ApproximationHelper::ElementWiseOnMatrixComplexAndComplex(m, c, compute); } private: + // Complex + Expression complexPart(Context & context, Preferences::AngleUnit angleUnit, bool real) const; // Layout bool childNeedsParenthesis(const TreeNode * child) const override; Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/arc_tangent.h b/poincare/include/poincare/arc_tangent.h index d6d67fdac..924772deb 100644 --- a/poincare/include/poincare/arc_tangent.h +++ b/poincare/include/poincare/arc_tangent.h @@ -2,6 +2,7 @@ #define POINCARE_ARC_TANGENT_H #include +#include #include #include @@ -21,6 +22,14 @@ public: // Properties Type type() const override { return Type::ArcTangent; } + + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { + return ComplexHelper::realPartOfComplexFunction(this, context, angleUnit); + } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { + return ComplexHelper::imaginaryPartOfComplexFunction(this, context, angleUnit); + } private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/binomial_coefficient.h b/poincare/include/poincare/binomial_coefficient.h index 14af31fa6..1b05a0fc7 100644 --- a/poincare/include/poincare/binomial_coefficient.h +++ b/poincare/include/poincare/binomial_coefficient.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -18,7 +19,9 @@ public: } #endif - // ExpressionNode + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } // Properties Type type() const override{ return Type::BinomialCoefficient; } diff --git a/poincare/include/poincare/ceiling.h b/poincare/include/poincare/ceiling.h index 9604ec5d6..2d1efeeac 100644 --- a/poincare/include/poincare/ceiling.h +++ b/poincare/include/poincare/ceiling.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -18,6 +19,10 @@ public: } #endif + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + // Properties Type type() const override { return Type::Ceiling; } private: diff --git a/poincare/include/poincare/complex_argument.h b/poincare/include/poincare/complex_argument.h index a4a026641..014b8956d 100644 --- a/poincare/include/poincare/complex_argument.h +++ b/poincare/include/poincare/complex_argument.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -17,6 +18,9 @@ public: stream << "ComplexArgument"; } #endif + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } // Properties Type type() const override { return Type::ComplexArgument; } diff --git a/poincare/include/poincare/complex_helper.h b/poincare/include/poincare/complex_helper.h new file mode 100644 index 000000000..96fd6079a --- /dev/null +++ b/poincare/include/poincare/complex_helper.h @@ -0,0 +1,32 @@ +#ifndef POINCARE_COMPLEX_HELPER_H +#define POINCARE_COMPLEX_HELPER_H + +#include + +namespace Poincare { + +class ComplexHelper { +public: + static Expression realPartOfComplexFunction(const ExpressionNode * e, Context & context, Preferences::AngleUnit angleUnit) { + return cartesianPartOfComplexFunction(e, context, angleUnit, true); + } + static Expression imaginaryPartOfComplexFunction(const ExpressionNode * e, Context & context, Preferences::AngleUnit angleUnit) { + return cartesianPartOfComplexFunction(e, context, angleUnit, false); + } + static Expression realPartRealFunction(const ExpressionNode * e, Context & context, Preferences::AngleUnit angleUnit) { + return Expression(e).clone(); + } + static Expression imaginaryPartRealFunction(const ExpressionNode * e, Context & context, Preferences::AngleUnit angleUnit); + // static Expression realPartMatrix(const Expression e, Context & context, Preferences::AngleUnit angleUnit); + + static Expression realPartFromPolarParts(const ExpressionNode * node, Context & context, Preferences::AngleUnit angleUnit) { return complexCartesianPartFromPolarParts(node, context, angleUnit, true); } + static Expression imaginaryPartFromPolarParts(const ExpressionNode * node, Context & context, Preferences::AngleUnit angleUnit) { return complexCartesianPartFromPolarParts(node, context, angleUnit, false); } + +private: + static Expression cartesianPartOfComplexFunction(const ExpressionNode * node, Context & context, Preferences::AngleUnit angleUnit, bool real); + static Expression complexCartesianPartFromPolarParts(const ExpressionNode * node, Context & context, Preferences::AngleUnit angleUnit, bool isReal); +}; + +} + +#endif diff --git a/poincare/include/poincare/confidence_interval.h b/poincare/include/poincare/confidence_interval.h index 78c526f68..395c56e04 100644 --- a/poincare/include/poincare/confidence_interval.h +++ b/poincare/include/poincare/confidence_interval.h @@ -2,6 +2,7 @@ #define POINCARE_CONFIDENCE_INTERVAL_H #include +#include namespace Poincare { @@ -19,6 +20,10 @@ public: // ExpressionNode + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + // Properties Type type() const override { return Type::ConfidenceInterval; } int polynomialDegree(Context & context, const char * symbolName) const override { return -1; } diff --git a/poincare/include/poincare/conjugate.h b/poincare/include/poincare/conjugate.h index 840f5e490..c05c47e1c 100644 --- a/poincare/include/poincare/conjugate.h +++ b/poincare/include/poincare/conjugate.h @@ -18,6 +18,9 @@ public: } #endif + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override; + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override; + // Properties Type type() const override { return Type::Conjugate; } private: diff --git a/poincare/include/poincare/constant.h b/poincare/include/poincare/constant.h index ba975a6d5..5b3bfdb84 100644 --- a/poincare/include/poincare/constant.h +++ b/poincare/include/poincare/constant.h @@ -17,6 +17,10 @@ public: } #endif + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override; + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override; + // Expression Properties Type type() const override { return Type::Constant; } Sign sign() const override; diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index 944adb7b0..83dbee238 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -2,6 +2,7 @@ #define POINCARE_COSINE_H #include +#include #include #include @@ -19,6 +20,10 @@ public: } #endif + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartOfComplexFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartOfComplexFunction(this, context, angleUnit); } + // Properties Type type() const override { return Type::Cosine; } float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override; diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index 664518dcb..9a54ec27b 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { diff --git a/poincare/include/poincare/derivative.h b/poincare/include/poincare/derivative.h index 3e2458f7f..62d813000 100644 --- a/poincare/include/poincare/derivative.h +++ b/poincare/include/poincare/derivative.h @@ -2,6 +2,7 @@ #define POINCARE_DERIVATIVE_H #include +#include #include #include @@ -19,6 +20,10 @@ public: } #endif + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + // Properties Type type() const override { return Type::Derivative; } int polynomialDegree(Context & context, const char * symbolName) const override; diff --git a/poincare/include/poincare/division.h b/poincare/include/poincare/division.h index c7c799fde..045a89c3a 100644 --- a/poincare/include/poincare/division.h +++ b/poincare/include/poincare/division.h @@ -22,6 +22,11 @@ public: } #endif + /* Property */ + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPart(context, angleUnit, true); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPart(context, angleUnit, false); } + // TODO: implement + // Properties Type type() const override { return Type::Division; } int polynomialDegree(Context & context, const char * symbolName) const override; @@ -49,6 +54,9 @@ public: Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; private: + // Complex + Expression complexPart(Context & context, Preferences::AngleUnit angleUnit, bool isReal) const; + // Approximation template static Complex compute(const std::complex c, const std::complex d); template static MatrixComplex computeOnMatrixAndComplex(const MatrixComplex m, const std::complex c) { return ApproximationHelper::ElementWiseOnMatrixComplexAndComplex(m, c, compute); diff --git a/poincare/include/poincare/division_quotient.h b/poincare/include/poincare/division_quotient.h index c2ec88224..1a1b052cb 100644 --- a/poincare/include/poincare/division_quotient.h +++ b/poincare/include/poincare/division_quotient.h @@ -2,6 +2,7 @@ #define POINCARE_DIVISION_QUOTIENT_H #include +#include namespace Poincare { @@ -19,6 +20,10 @@ public: // ExpressionNode Type type() const override { return Type::DivisionQuotient; } + + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/division_remainder.h b/poincare/include/poincare/division_remainder.h index b99624809..c0a09c4e4 100644 --- a/poincare/include/poincare/division_remainder.h +++ b/poincare/include/poincare/division_remainder.h @@ -2,6 +2,7 @@ #define POINCARE_DIVISION_REMAINDER_H #include +#include #include namespace Poincare { @@ -20,6 +21,10 @@ public: // ExpressionNode Type type() const override { return Type::DivisionRemainder; } + + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 13fa788a8..912683d34 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -27,6 +27,7 @@ class Expression : public TreeHandle { friend class Ceiling; friend class CommonLogarithm; friend class ComplexArgument; + friend class ComplexHelper; friend class ConfidenceInterval; friend class Conjugate; friend class Cosine; diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index bc0461b3e..659734961 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -3,7 +3,7 @@ #include #include -#include +#include namespace Poincare { @@ -24,6 +24,9 @@ public: Sign sign() const override { return Sign::Positive; } Expression setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override; + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } private: // Layout bool childNeedsParenthesis(const TreeNode * child) const override; diff --git a/poincare/include/poincare/floor.h b/poincare/include/poincare/floor.h index 50f0da020..084683a78 100644 --- a/poincare/include/poincare/floor.h +++ b/poincare/include/poincare/floor.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -20,6 +21,11 @@ public: // Properties Type type() const override { return Type::Floor; } + + + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/frac_part.h b/poincare/include/poincare/frac_part.h index cf85f4eed..4fd583323 100644 --- a/poincare/include/poincare/frac_part.h +++ b/poincare/include/poincare/frac_part.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -20,6 +21,11 @@ public: // Properties Type type() const override { return Type::FracPart; } + + + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/function.h b/poincare/include/poincare/function.h index e94b248f3..e032befc1 100644 --- a/poincare/include/poincare/function.h +++ b/poincare/include/poincare/function.h @@ -28,6 +28,10 @@ public: int getVariables(Context & context, isVariableTest isVariable, char * variables, int maxSizeVariable) const override; float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override; + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override; + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override; + private: char m_name[0]; // MUST be the last member variable diff --git a/poincare/include/poincare/great_common_divisor.h b/poincare/include/poincare/great_common_divisor.h index 3e12416c5..7de2de838 100644 --- a/poincare/include/poincare/great_common_divisor.h +++ b/poincare/include/poincare/great_common_divisor.h @@ -2,6 +2,7 @@ #define POINCARE_GREAT_COMMON_DIVISOR_H #include +#include namespace Poincare { @@ -19,6 +20,9 @@ public: // ExpressionNode Type type() const override { return Type::GreatCommonDivisor; } + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/imaginary_part.h b/poincare/include/poincare/imaginary_part.h index f79044cb8..8b40bfdd8 100644 --- a/poincare/include/poincare/imaginary_part.h +++ b/poincare/include/poincare/imaginary_part.h @@ -2,6 +2,7 @@ #define POINCARE_IMAGINARY_PART_H #include +#include #include namespace Poincare { @@ -20,6 +21,10 @@ public: // Properties Type type() const override { return Type::ImaginaryPart; } + + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/integral.h b/poincare/include/poincare/integral.h index 9c2f08dfa..91848e280 100644 --- a/poincare/include/poincare/integral.h +++ b/poincare/include/poincare/integral.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -23,6 +24,9 @@ public: int polynomialDegree(Context & context, const char * symbolName) const override; Expression replaceUnknown(const Symbol & symbol) override; + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/least_common_multiple.h b/poincare/include/poincare/least_common_multiple.h index c36b64ec3..8ab9d7a41 100644 --- a/poincare/include/poincare/least_common_multiple.h +++ b/poincare/include/poincare/least_common_multiple.h @@ -2,6 +2,7 @@ #define POINCARE_LEAST_COMMON_MULTIPLE_H #include +#include namespace Poincare { @@ -18,6 +19,10 @@ public: #endif // ExpressionNode Type type() const override { return Type::LeastCommonMultiple; } + + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } private: /* Layout */ Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/matrix_dimension.h b/poincare/include/poincare/matrix_dimension.h index d1ebdb252..5e3555f2b 100644 --- a/poincare/include/poincare/matrix_dimension.h +++ b/poincare/include/poincare/matrix_dimension.h @@ -2,6 +2,7 @@ #define POINCARE_MATRIX_DIMENSION_H #include +#include namespace Poincare { @@ -19,6 +20,10 @@ public: // Properties Type type() const override { return Type::MatrixDimension; } + +// Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index da6a19330..328d5453c 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -2,6 +2,7 @@ #define POINCARE_MULTIPLICATION_H #include +#include #include namespace Poincare { @@ -25,6 +26,13 @@ public: int polynomialDegree(Context & context, const char * symbolName) const override; int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const override; + // Complex + // TODO: implement realPart and imaginaryPart to optimize? + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartFromPolarParts(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartFromPolarParts(this, context, angleUnit); } + Expression complexNorm(Context & context, Preferences::AngleUnit angleUnit) const override; + Expression complexArgument(Context & context, Preferences::AngleUnit angleUnit) const override; + // Approximation template static Complex compute(const std::complex c, const std::complex d) { return Complex(c*d); } template static MatrixComplex computeOnComplexAndMatrix(const std::complex c, const MatrixComplex m) { diff --git a/poincare/include/poincare/nth_root.h b/poincare/include/poincare/nth_root.h index 191d881db..e16e7ddea 100644 --- a/poincare/include/poincare/nth_root.h +++ b/poincare/include/poincare/nth_root.h @@ -2,6 +2,7 @@ #define POINCARE_NTH_ROOT_H #include +#include namespace Poincare { @@ -19,7 +20,15 @@ public: } #endif + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartFromPolarParts(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartFromPolarParts(this, context, angleUnit); } + Expression complexNorm(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPolarPart(context, angleUnit, true); } + Expression complexArgument(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPolarPart(context, angleUnit, false); } + private: + // Complex + Expression complexPolarPart(Context & context, Preferences::AngleUnit angleUnit, bool isNorm) const; // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/number.h b/poincare/include/poincare/number.h index 8de3464bd..40baa4cb8 100644 --- a/poincare/include/poincare/number.h +++ b/poincare/include/poincare/number.h @@ -2,6 +2,7 @@ #define POINCARE_NUMBER_H #include +#include namespace Poincare { @@ -21,6 +22,10 @@ public: int numberOfChildren() const override { return 0; } double doubleApproximation() const; + + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } }; class Number : public Expression { diff --git a/poincare/include/poincare/opposite.h b/poincare/include/poincare/opposite.h index 6a030ff9e..96f3300be 100644 --- a/poincare/include/poincare/opposite.h +++ b/poincare/include/poincare/opposite.h @@ -27,6 +27,10 @@ public: int polynomialDegree(Context & context, const char * symbolName) const override; Sign sign() const override; + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexCartesianPart(context, angleUnit, true); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexCartesianPart(context, angleUnit, false); } + // Approximation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return ApproximationHelper::Map(this, context, angleUnit, compute); @@ -42,6 +46,9 @@ public: // Simplification Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + +private: + Expression complexCartesianPart(Context & context, Preferences::AngleUnit angleUnit, bool real) const; }; class Opposite final : public Expression { diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index eaf35caf9..f29e10277 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -21,6 +21,10 @@ public: Type type() const override { return Type::Parenthesis; } int polynomialDegree(Context & context, const char * symbolName) const override; + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return childAtIndex(0)->realPart(context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return childAtIndex(0)->imaginaryPart(context, angleUnit); } + // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/permute_coefficient.h b/poincare/include/poincare/permute_coefficient.h index c1366a29e..a4477cdcc 100644 --- a/poincare/include/poincare/permute_coefficient.h +++ b/poincare/include/poincare/permute_coefficient.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -22,6 +23,11 @@ public: // Properties Type type() const override{ return Type::PermuteCoefficient; } + + + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 9da73580d..b155bb8f0 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -21,6 +21,12 @@ public: } #endif + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartFromPolarParts(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartFromPolarParts(this, context, angleUnit); } + Expression complexNorm(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPolarPart(context, angleUnit, true); } + Expression complexArgument(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPolarPart(context, angleUnit, false); } + // Properties Type type() const override { return Type::Power; } Sign sign() const override; @@ -34,6 +40,8 @@ public: private: constexpr static int k_maxApproximatePowerMatrix = 1000; + // Complex + Expression complexPolarPart(Context & context, Preferences::AngleUnit angleUnit, bool norm) const; // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/prediction_interval.h b/poincare/include/poincare/prediction_interval.h index 9b27a7861..d1250e089 100644 --- a/poincare/include/poincare/prediction_interval.h +++ b/poincare/include/poincare/prediction_interval.h @@ -2,6 +2,7 @@ #define POINCARE_PREDICTION_INTERVAL_H #include +#include namespace Poincare { @@ -19,6 +20,10 @@ public: // ExpressionNode + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + // Properties Type type() const override { return Type::PredictionInterval; } int polynomialDegree(Context & context, const char * symbolName) const override { return -1; } diff --git a/poincare/include/poincare/randint.h b/poincare/include/poincare/randint.h index 26baebae0..650648a5c 100644 --- a/poincare/include/poincare/randint.h +++ b/poincare/include/poincare/randint.h @@ -2,6 +2,7 @@ #define POINCARE_RANDINT_H #include +#include namespace Poincare { @@ -19,6 +20,11 @@ public: // Properties Type type() const override { return Type::Randint; } + + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/random.h b/poincare/include/poincare/random.h index 8ea1a4b01..e20172e85 100644 --- a/poincare/include/poincare/random.h +++ b/poincare/include/poincare/random.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -18,6 +19,10 @@ public: } #endif + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + // Properties Type type() const override { return Type::Random; } Sign sign() const override { return Sign::Positive; } diff --git a/poincare/include/poincare/real_part.h b/poincare/include/poincare/real_part.h index 61200e3c9..e719175cd 100644 --- a/poincare/include/poincare/real_part.h +++ b/poincare/include/poincare/real_part.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -20,6 +21,10 @@ public: // Properties Type type() const override { return Type::RealPart; } + + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/round.h b/poincare/include/poincare/round.h index 3965e3c73..4e798e5dd 100644 --- a/poincare/include/poincare/round.h +++ b/poincare/include/poincare/round.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -18,6 +19,11 @@ public: } #endif + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + + // Properties Type type() const override { return Type::Round; } private: diff --git a/poincare/include/poincare/sign_function.h b/poincare/include/poincare/sign_function.h index 460108dcd..2ff96ff6c 100644 --- a/poincare/include/poincare/sign_function.h +++ b/poincare/include/poincare/sign_function.h @@ -2,6 +2,7 @@ #define POINCARE_SIGN_FUNCTION_H #include +#include #include namespace Poincare { @@ -22,6 +23,11 @@ public: Type type() const override { return Type::SignFunction; } Sign sign() const override; Expression setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override; + + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index 70c6dc88f..afdf44bf0 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace Poincare { @@ -19,6 +20,10 @@ public: } #endif + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartOfComplexFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartOfComplexFunction(this, context, angleUnit); } + // Properties Type type() const override { return Type::Sine; } float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override; diff --git a/poincare/include/poincare/square_root.h b/poincare/include/poincare/square_root.h index 7e140afd1..047d8a6c9 100644 --- a/poincare/include/poincare/square_root.h +++ b/poincare/include/poincare/square_root.h @@ -2,6 +2,7 @@ #define POINCARE_SQUARE_ROOT_H #include +#include #include #include @@ -21,7 +22,11 @@ public: } #endif - + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartFromPolarParts(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartFromPolarParts(this, context, angleUnit); } + Expression complexNorm(Context & context, Preferences::AngleUnit angleUnit) const override; + Expression complexArgument(Context & context, Preferences::AngleUnit angleUnit) const override; private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/subtraction.h b/poincare/include/poincare/subtraction.h index 122c4f994..9a03ff8cd 100644 --- a/poincare/include/poincare/subtraction.h +++ b/poincare/include/poincare/subtraction.h @@ -24,6 +24,10 @@ public: Type type() const override { return Type::Subtraction; } int polynomialDegree(Context & context, const char * symbolName) const override; + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPart(context, angleUnit, true); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPart(context, angleUnit, false); } + // Approximation template static Complex compute(const std::complex c, const std::complex d) { return Complex(c - d); } Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { @@ -42,6 +46,9 @@ public: Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; private: + // Complex + Expression complexPart(Context & context, Preferences::AngleUnit angleUnit, bool real) const; + /* Evaluation */ template static MatrixComplex computeOnMatrixAndComplex(const MatrixComplex m, const std::complex c) { return ApproximationHelper::ElementWiseOnMatrixComplexAndComplex(m, c, compute); diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index eb6a90389..2def334c4 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -26,6 +26,10 @@ public: int getVariables(Context & context, isVariableTest isVariable, char * variables, int maxSizeVariable) const override; float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override; + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override; + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override; + /* Layout */ Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/tangent.h b/poincare/include/poincare/tangent.h index 3f32fd99e..a97d08da2 100644 --- a/poincare/include/poincare/tangent.h +++ b/poincare/include/poincare/tangent.h @@ -2,6 +2,7 @@ #define POINCARE_TANGENT_H #include +#include #include namespace Poincare { @@ -22,6 +23,9 @@ public: Type type() const override { return Type::Tangent; } float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override; + // Complex + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartOfComplexFunction(this, context, angleUnit); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartOfComplexFunction(this, context, angleUnit); } private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/undefined.h b/poincare/include/poincare/undefined.h index 198f4adb6..31eb950a6 100644 --- a/poincare/include/poincare/undefined.h +++ b/poincare/include/poincare/undefined.h @@ -16,6 +16,10 @@ public: } #endif + // Complex + using ExpressionNode::realPart; + using ExpressionNode::imaginaryPart; + // Properties Type type() const override { return Type::Undefined; } int polynomialDegree(Context & context, const char * symbolName) const override; diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index d3de4068e..b4a9f297d 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -29,6 +29,20 @@ int AdditionNode::getPolynomialCoefficients(Context & context, const char * symb // Private +Expression AdditionNode::complexPart(Context & context, Preferences::AngleUnit angleUnit, bool real) const { + Expression e(this); + Addition result; + int nbOfChildren = e.numberOfChildren(); + for (int i = 0; i < nbOfChildren; i++) { + Expression part = real ? e.childAtIndex(i).realPart(context, angleUnit) : e.childAtIndex(i).imaginaryPart(context, angleUnit); + if (part.isUninitialized()) { + return Expression(); + } + result.addChildAtIndexInPlace(part, result.numberOfChildren(), result.numberOfChildren()); + } + return result; +} + // Layout bool AdditionNode::childNeedsParenthesis(const TreeNode * child) const { if (((static_cast(child)->isNumber() diff --git a/poincare/src/complex_helper.cpp b/poincare/src/complex_helper.cpp new file mode 100644 index 000000000..2d571ae8e --- /dev/null +++ b/poincare/src/complex_helper.cpp @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include + +namespace Poincare { + +Expression ComplexHelper::cartesianPartOfComplexFunction(const ExpressionNode * node, Context & context, Preferences::AngleUnit angleUnit, bool real) { + Expression e(node); + Expression opImaginaryPart = e.childAtIndex(0).imaginaryPart(context, angleUnit); + if (opImaginaryPart.isUninitialized() || opImaginaryPart.type() != ExpressionNode::Type::Rational || !static_cast(opImaginaryPart).isZero()) { + return Expression(); + } + if (real) { + Expression result = e.clone(); + result.replaceChildAtIndexInPlace(0, e.childAtIndex(0).realPart(context, angleUnit)); + return result; + } + return Rational(0); +} + +Expression ComplexHelper::imaginaryPartRealFunction(const ExpressionNode * e, Context & context, Preferences::AngleUnit angleUnit) { + return Rational(0); +} + +Expression ComplexHelper::complexCartesianPartFromPolarParts(const ExpressionNode * node, Context & context, Preferences::AngleUnit angleUnit, bool isReal) { + Expression e(node); + Expression r = e.complexNorm(context, angleUnit); + Expression th = e.complexArgument(context, angleUnit); + if (r.isUninitialized() || th.isUninitialized()) { + return Expression(); + } + Expression argument = angleUnit == Preferences::AngleUnit::Radian ? th : th.radianToDegree(); + Expression trigo; + if (isReal) { + trigo = Cosine::Builder(argument); + } else { + trigo = Sine::Builder(argument); + } + return Multiplication(r, trigo); +} + +} diff --git a/poincare/src/conjugate.cpp b/poincare/src/conjugate.cpp index 49076891f..26825f9a5 100644 --- a/poincare/src/conjugate.cpp +++ b/poincare/src/conjugate.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -11,6 +12,18 @@ constexpr Expression::FunctionHelper Conjugate::s_functionHelper; int ConjugateNode::numberOfChildren() const { return Conjugate::s_functionHelper.numberOfChildren(); } +Expression ConjugateNode::realPart(Context & context, Preferences::AngleUnit angleUnit) const { + return childAtIndex(0)->realPart(context, angleUnit); +} + +Expression ConjugateNode::imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const { + Expression e = childAtIndex(0)->imaginaryPart(context, angleUnit); + if (!e.isUninitialized()) { + return Opposite(e); + } + return Expression(); +} + Layout ConjugateNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { return ConjugateLayout(childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits)); } diff --git a/poincare/src/constant.cpp b/poincare/src/constant.cpp index 7fdc38003..f2b8f15ef 100644 --- a/poincare/src/constant.cpp +++ b/poincare/src/constant.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -15,6 +16,20 @@ ExpressionNode::Sign ConstantNode::sign() const { return Sign::Unknown; } +Expression ConstantNode::realPart(Context & context, Preferences::AngleUnit angleUnit) const { + if (isIComplex()) { + return Rational(0); + } + return Constant(this).clone(); +} + +Expression ConstantNode::imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const { + if (isIComplex()) { + return Rational(1); + } + return Rational(0); +} + Layout ConstantNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { return LayoutHelper::String(m_name, strlen(m_name)); } diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index a6843f97b..8635d1369 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include #include @@ -44,6 +46,22 @@ Expression DivisionNode::shallowReduce(Context & context, Preferences::AngleUnit return Division(this).shallowReduce(context, angleUnit, target); } +Expression DivisionNode::complexPart(Context & context, Preferences::AngleUnit angleUnit, bool real) const { + Division e(this); + Expression a = e.childAtIndex(0).realPart(context, angleUnit); + Expression b = e.childAtIndex(0).imaginaryPart(context, angleUnit); + Expression c = e.childAtIndex(1).realPart(context, angleUnit); + Expression d = e.childAtIndex(1).imaginaryPart(context, angleUnit); + if (a.isUninitialized() || b.isUninitialized() || c.isUninitialized() || d.isUninitialized()) { + return Expression(); + } + Expression denominator = Addition(Power(c.clone(), Rational(2)), Power(d.clone(), Rational(2))); + if (real) { + return Division(Addition(Multiplication(a, c), Multiplication(b, d)), denominator); + } + return Division(Subtraction(Multiplication(b, c), Multiplication(a, d)), denominator); +} + template Complex DivisionNode::compute(const std::complex c, const std::complex d) { return Complex(c/d); } diff --git a/poincare/src/function.cpp b/poincare/src/function.cpp index 8c57fdde9..f0770b2ab 100644 --- a/poincare/src/function.cpp +++ b/poincare/src/function.cpp @@ -9,6 +9,24 @@ namespace Poincare { +Expression FunctionNode::realPart(Context & context, Preferences::AngleUnit angleUnit) const { + Function f(this); + Expression e = SymbolAbstract::Expand(f, context, true); + if (e.isUninitialized()) { + return f.clone(); + } + return e.realPart(context, angleUnit); +} + +Expression FunctionNode::imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const { + Function f(this); + Expression e = SymbolAbstract::Expand(f, context, false); + if (e.isUninitialized()) { + return Rational(0); + } + return e.imaginaryPart(context, angleUnit); +} + Expression FunctionNode::replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression) { return Function(this).replaceSymbolWithExpression(symbol, expression); } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 5973298c7..ec8e64ac7 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -28,6 +28,32 @@ ExpressionNode::Sign MultiplicationNode::sign() const { return (Sign)sign; } +Expression MultiplicationNode::complexNorm(Context & context, Preferences::AngleUnit angleUnit) const { + Multiplication m(this); + Multiplication norm; + for (int i = 0; i < m.numberOfChildren(); i++) { + Expression r = m.childAtIndex(i).complexNorm(context, angleUnit); + if (r.isUninitialized()) { + return Expression(); + } + norm.addChildAtIndexInPlace(r, norm.numberOfChildren(), norm.numberOfChildren()); + } + return norm; +} + +Expression MultiplicationNode::complexArgument(Context & context, Preferences::AngleUnit angleUnit) const { + Multiplication m(this); + Addition arg; + for (int i = 0; i < m.numberOfChildren(); i++) { + Expression r = m.childAtIndex(i).complexArgument(context, angleUnit); + if (r.isUninitialized()) { + return Expression(); + } + arg.addChildAtIndexInPlace(r, arg.numberOfChildren(), arg.numberOfChildren()); + } + return arg; +} + int MultiplicationNode::polynomialDegree(Context & context, const char * symbolName) const { int degree = 0; for (ExpressionNode * c : children()) { diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index 0624a2b70..7aee33973 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -1,8 +1,12 @@ #include +#include +#include #include +#include #include #include #include +#include #include #include #include @@ -14,6 +18,28 @@ constexpr Expression::FunctionHelper NthRoot::s_functionHelper; int NthRootNode::numberOfChildren() const { return NthRoot::s_functionHelper.numberOfChildren(); } +Expression NthRootNode::complexPolarPart(Context & context, Preferences::AngleUnit angleUnit, bool isNorm) const { + NthRoot e(this); + // NthRoot(r*e^(i*th), c+id) + Expression r = e.childAtIndex(0).complexNorm(context, angleUnit); + Expression th = e.childAtIndex(0).complexArgument(context, angleUnit); + Expression c = e.childAtIndex(1).realPart(context, angleUnit); + Expression d = e.childAtIndex(1).imaginaryPart(context, angleUnit); + if (r.isUninitialized() || th.isUninitialized() || c.isUninitialized() || d.isUninitialized()) { + return Expression(); + } + Expression denominator = Addition(Power(c.clone(), Rational(2)), Power(d.clone(), Rational(2))); + if (isNorm) { + // R = e^((c*ln(r)+th*d)/(c^2+d^2)) + // R = r^(c/(c^2+d^2))*e^(th*d/(c^2+d^2)) + return Multiplication(Power(r, Division(c, denominator.clone())), Power(Constant(Ion::Charset::Exponential), Division(Multiplication(d, th), denominator))); + //return Power(Constant(Ion::Charset::Exponential), Division(Addition(Multiplication(c, NaperianLogarithm::Builder(r)), Multiplication(d, th)), denominator)); + } else { + // TH = (th*c-d*ln(r))/(c^2+d^2) + return Division(Subtraction(Multiplication(th, c), Multiplication(d, NaperianLogarithm::Builder(r))), denominator); + } +} + Layout NthRootNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { return NthRootLayout( childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits), diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index e3bff0c12..b59a1fca5 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -27,6 +27,14 @@ ExpressionNode::Sign OppositeNode::sign() const { return Sign::Unknown; } +Expression OppositeNode::complexCartesianPart(Context & context, Preferences::AngleUnit angleUnit, bool real) const { + Expression a = real ? childAtIndex(0)->realPart(context, angleUnit) : childAtIndex(0)->imaginaryPart(context, angleUnit); + if (a.isUninitialized()) { + return Expression(); + } + return Opposite(a); +} + /* Layout */ bool OppositeNode::childNeedsParenthesis(const TreeNode * child) const { diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 4ad731d1f..58453bc39 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -80,6 +81,27 @@ int PowerNode::getPolynomialCoefficients(Context & context, const char * symbolN // Private +Expression PowerNode::complexPolarPart(Context & context, Preferences::AngleUnit angleUnit, bool norm) const { + Power p(this); + // Power(r*e^(i*th), c+id) + Expression r = p.childAtIndex(0).complexNorm(context, angleUnit); + Expression th = p.childAtIndex(0).complexArgument(context, angleUnit); + Expression c = p.childAtIndex(1).realPart(context, angleUnit); + Expression d = p.childAtIndex(1).imaginaryPart(context, angleUnit); + if (r.isUninitialized() || th.isUninitialized() || c.isUninitialized() || d.isUninitialized()) { + return Expression(); + } + if (norm) { + // R = e^(c*ln(r)-th*d) + // R = r^c*e^(-th*d) + return Multiplication(Power(r, c), Power(Constant(Ion::Charset::Exponential), Opposite(Multiplication(th, d)))); + //return Power(Constant(Ion::Charset::Exponential), Subtraction(Multiplication(c, NaperianLogarithm::Builder(r)), Multiplication(d, th))); + } else { + // TH = d*ln(r)+c*th + return Addition(Multiplication(th, c), Multiplication(d, NaperianLogarithm::Builder(r))); + } +} + template Complex PowerNode::compute(const std::complex c, const std::complex d) { std::complex result; diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index 9fd0ee7cc..1e64d7a11 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -14,6 +15,24 @@ constexpr Expression::FunctionHelper SquareRoot::s_functionHelper; int SquareRootNode::numberOfChildren() const { return SquareRoot::s_functionHelper.numberOfChildren(); } +Expression SquareRootNode::complexNorm(Context & context, Preferences::AngleUnit angleUnit) const { + Expression r = childAtIndex(0)->complexNorm(context, angleUnit); + if (r.isUninitialized()) { + return Expression(); + } + // R = sqrt(r) + return SquareRoot::Builder(r); +} + +Expression SquareRootNode::complexArgument(Context & context, Preferences::AngleUnit angleUnit) const { + Expression th = childAtIndex(0)->complexArgument(context, angleUnit); + if (th.isUninitialized()) { + return Expression(); + } + // TH = th/2 + return Division(th, Rational(2)); +} + Layout SquareRootNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { return NthRootLayout(childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits)); } diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index cebd5e29a..2c2006019 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -23,6 +23,16 @@ int SubtractionNode::polynomialDegree(Context & context, const char * symbolName // Private +Expression SubtractionNode::complexPart(Context & context, Preferences::AngleUnit angleUnit, bool real) const { + Subtraction e(this); + Expression a0 = real ? e.childAtIndex(0).realPart(context, angleUnit) : e.childAtIndex(0).imaginaryPart(context, angleUnit); + Expression a1 = real ? e.childAtIndex(1).realPart(context, angleUnit) : e.childAtIndex(1).imaginaryPart(context, angleUnit); + if (a0.isUninitialized() || a1.isUninitialized()) { + return Expression(); + } + return Subtraction(a0, a1); +} + bool SubtractionNode::childNeedsParenthesis(const TreeNode * child) const { if (child == childAtIndex(0)) { return false; diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index dc9ecf035..b2250df25 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -77,6 +77,24 @@ float SymbolNode::characteristicXRange(Context & context, Preferences::AngleUnit return 0.0f; } +Expression SymbolNode::realPart(Context & context, Preferences::AngleUnit angleUnit) const { + Symbol s(this); + Expression e = SymbolAbstract::Expand(s, context, false); + if (e.isUninitialized()) { + return s.clone(); + } + return e.realPart(context, angleUnit); +} + +Expression SymbolNode::imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const { + Symbol s(this); + Expression e = SymbolAbstract::Expand(s, context, false); + if (e.isUninitialized()) { + return Rational(0); + } + return e.imaginaryPart(context, angleUnit); +} + Layout SymbolNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { if (m_name[0] == Symbol::SpecialSymbols::UnknownX) { assert(m_name[1] == 0); diff --git a/poincare/test/complex.cpp b/poincare/test/complex.cpp new file mode 100644 index 000000000..fd9ad3f47 --- /dev/null +++ b/poincare/test/complex.cpp @@ -0,0 +1,149 @@ +#include +#include +#include +#include +#include "helper.h" + +using namespace Poincare; + +void assert_expression_has_complex_cartesian_parts(const char * expression, const char * real, const char * imag, Preferences::AngleUnit angleUnit = Degree) { + Shared::GlobalContext context; + Expression e = parse_expression(expression); + Expression r = e.realPart(context, angleUnit); + if (r.isUninitialized()) { + assert(real == nullptr); + } else { + r = r.simplify(context, angleUnit); + assert_parsed_expression_serialize_to(r, real); + } + Expression i = e.imaginaryPart(context, angleUnit); + if (i.isUninitialized()) { + assert(imag == nullptr); + } else { + i = i.simplify(context, angleUnit); + assert_parsed_expression_serialize_to(i, imag); + } +} + +void assert_expression_has_complex_polar_parts(const char * expression, const char * norm, const char * arg, Preferences::AngleUnit angleUnit = Degree) { + Shared::GlobalContext context; + Expression e = parse_expression(expression); + Expression n = e.complexNorm(context, angleUnit); + if (n.isUninitialized()) { + assert(norm == nullptr); + } else { + n = n.simplify(context, angleUnit); + assert_parsed_expression_serialize_to(n, norm); + } + Expression a = e.complexArgument(context, angleUnit); + if (a.isUninitialized()) { + assert(arg == nullptr); + } else { + a = a.simplify(context, angleUnit); + assert_parsed_expression_serialize_to(a, arg); + } +} + +QUIZ_CASE(poincare_complex_parts) { + assert_expression_has_complex_cartesian_parts("-2.3E3", "-2300", "0"); + assert_expression_has_complex_cartesian_parts("3", "3", "0"); + assert_expression_has_complex_cartesian_parts("inf", "inf", "0"); + assert_expression_has_complex_cartesian_parts("1+2+I", "3", "1"); + assert_expression_has_complex_cartesian_parts("-(5+2*I)", "-5", "-2"); + assert_expression_has_complex_cartesian_parts("(5+2*I)", "5", "2"); + assert_expression_has_complex_cartesian_parts("I+I", "0", "2"); + assert_expression_has_complex_cartesian_parts("-2+2*I", "-2", "2"); + assert_expression_has_complex_cartesian_parts("(3+I)-(2+4*I)", "1", "-3"); + // TODO: implement TODO of multiplication + //assert_expression_has_complex_cartesian_parts("(2+3*I)*(4-2*I)", "14", "8"); + assert_expression_has_complex_cartesian_parts("(3+I)/2", "3/2", "1/2"); + assert_expression_has_complex_cartesian_parts("(3+I)/(2+I)", "7/5", "-1/5"); + assert_expression_has_complex_cartesian_parts("(3+I)^(2+I)", "10*cos((-4*atan(3)+ln(2)+ln(5)+2*P)/2)*X^((2*atan(3)-P)/2)", "10*sin((-4*atan(3)+ln(2)+ln(5)+2*P)/2)*X^((2*atan(3)-P)/2)", Radian); + assert_expression_has_complex_cartesian_parts("I!", "undef", "0"); + assert_expression_has_complex_cartesian_parts("3!", "6", "0"); + assert_expression_has_complex_cartesian_parts("x!", "x!", "0"); + assert_expression_has_complex_cartesian_parts("X", "X", "0"); + assert_expression_has_complex_cartesian_parts("P", "P", "0"); + assert_expression_has_complex_cartesian_parts("I", "0", "1"); + + assert_expression_has_complex_cartesian_parts("abs(-3)", "3", "0"); + assert_expression_has_complex_cartesian_parts("abs(-3+I)", "abs(-3+I)", "0"); + assert_expression_has_complex_cartesian_parts("atan(2)", "atan(2)", "0"); + assert_expression_has_complex_cartesian_parts("atan(2+I)", nullptr, nullptr); + assert_expression_has_complex_cartesian_parts("binomial(10, 4)", "210", "0"); + assert_expression_has_complex_cartesian_parts("ceil(-1.3)", "-1", "0"); + assert_expression_has_complex_cartesian_parts("arg(-2)", "arg(-2)", "0"); + // TODO: confidence is not simplified yet + //assert_expression_has_complex_cartesian_parts("confidence(-2,-3)", "confidence(-2)", "0"); + assert_expression_has_complex_cartesian_parts("conj(-2)", "-2", "0"); + assert_expression_has_complex_cartesian_parts("conj(-2+2*I+I)", "-2", "-3"); + assert_expression_has_complex_cartesian_parts("cos(12)", "cos(12)", "0"); + assert_expression_has_complex_cartesian_parts("cos(12+I)", nullptr, nullptr); + assert_expression_has_complex_cartesian_parts("diff(3*x, x, 3)", "diff(3*x,x,3)", "0"); + assert_expression_has_complex_cartesian_parts("quo(34,x)", "quo(34,x)", "0"); + assert_expression_has_complex_cartesian_parts("rem(5,3)", "2", "0"); + assert_expression_has_complex_cartesian_parts("floor(x)", "floor(x)", "0"); + assert_expression_has_complex_cartesian_parts("frac(x)", "frac(x)", "0"); + assert_expression_has_complex_cartesian_parts("gcd(x,y)", "gcd(x,y)", "0"); + assert_expression_has_complex_cartesian_parts("im(x)", "im(x)", "0"); + assert_expression_has_complex_cartesian_parts("int(x^2, x, 1, 2)", "int(x^2,x,1,2)", "0"); + assert_expression_has_complex_cartesian_parts("lcm(x,y)", "lcm(x,y)", "0"); + // TODO: dim is not simplified yet + //assert_expression_has_complex_cartesian_parts("dim(x)", "dim(x)", "0"); + + assert_expression_has_complex_cartesian_parts("root(2,I)", "cos(-ln(2))", "sin(-ln(2))", Radian); + assert_expression_has_complex_cartesian_parts("root(2,I+1)", "R(2)*cos(-(90*ln(2))/P)", "R(2)*sin(-(90*ln(2))/P)"); + assert_expression_has_complex_cartesian_parts("root(2,I+1)", "R(2)*cos(-ln(2)/2)", "R(2)*sin(-ln(2)/2)", Radian); + assert_expression_has_complex_cartesian_parts("permute(10, 4)", "5040", "0"); + // TODO: prediction is not simplified yet + //assert_expression_has_complex_cartesian_parts("prediction(-2,-3)", "prediction(-2)", "0"); + assert_expression_has_complex_cartesian_parts("randint(2,4)", "randint(2,4)", "0"); + assert_expression_has_complex_cartesian_parts("random()", "random()", "0"); + assert_expression_has_complex_cartesian_parts("re(x)", "re(x)", "0"); + assert_expression_has_complex_cartesian_parts("round(x,y)", "round(x,y)", "0"); + assert_expression_has_complex_cartesian_parts("sign(x)", "sign(x)", "0"); + assert_expression_has_complex_cartesian_parts("sin(23)", "sin(23)", "0"); + assert_expression_has_complex_cartesian_parts("sin(23+I)", nullptr, nullptr); + assert_expression_has_complex_cartesian_parts("R(1-I)", "(root(2,4)*R(2+R(2)))/2", "-(root(2,4)*R(2-R(2)))/2"); + assert_expression_has_complex_cartesian_parts("tan(23)", "tan(23)", "0"); + assert_expression_has_complex_cartesian_parts("tan(23+I)", nullptr, nullptr); + + // User defined variable + assert_expression_has_complex_cartesian_parts("a", "a", "0"); + // a = 2+i + assert_simplify("2+I>a"); + assert_expression_has_complex_cartesian_parts("a", "2", "1"); + // Clean the storage for other tests + Ion::Storage::sharedStorage()->recordNamed("a.exp").destroy(); + // User defined function + assert_expression_has_complex_cartesian_parts("f(3)", "f(3)", "0"); + // f: x -> x+1 + assert_simplify("x+1+I>f(x)"); + assert_expression_has_complex_cartesian_parts("f(3)", "4", "1"); + // Clean the storage for other tests + Ion::Storage::sharedStorage()->recordNamed("f.func").destroy(); + + assert_expression_has_complex_polar_parts("-2.3E3", "2300", "P"); + assert_expression_has_complex_polar_parts("3", "3", "0"); + assert_expression_has_complex_polar_parts("inf", "inf", "0"); + assert_expression_has_complex_polar_parts("1+2+I", "R(10)", "(-2*atan(3)+P)/2", Radian); + assert_expression_has_complex_polar_parts("1+2+I", "R(10)", "(90*P-atan(3)*P)/180"); + assert_expression_has_complex_polar_parts("-(5+2*I)", "R(29)", "(-2*atan(5/2)-P)/2", Radian); + assert_expression_has_complex_polar_parts("(5+2*I)", "R(29)", "(-2*atan(5/2)+P)/2", Radian); + assert_expression_has_complex_polar_parts("I+I", "2", "P/2", Radian); + assert_expression_has_complex_polar_parts("I+I", "2", "P/2"); + assert_expression_has_complex_polar_parts("-2+2*I", "2*R(2)", "(3*P)/4", Radian); + assert_expression_has_complex_polar_parts("(3+I)-(2+4*I)", "R(10)", "(2*atan(1/3)-P)/2", Radian); + // TODO: implement TODO of multiplication + //assert_expression_has_complex_polar_parts("(2+3*I)*(4-2*I)", "2*R(65)", "(2*atan(7/4)-P)/2", Radian); + assert_expression_has_complex_polar_parts("(3+I)/2", "R(10)/2", "(-2*atan(3)+P)/2", Radian); + assert_expression_has_complex_polar_parts("(3+I)/(2+I)", "R(2)", "(2*atan(7)-P)/2", Radian); + assert_expression_has_complex_polar_parts("(3+I)^(2+I)", "10*X^((2*atan(3)-P)/2)", "(-4*atan(3)+ln(2)+ln(5)+2*P)/2", Radian); + assert_expression_has_complex_polar_parts("3!", "6", "0"); + assert_expression_has_complex_polar_parts("x!", "x!", "0"); + assert_expression_has_complex_polar_parts("X", "X", "0"); + assert_expression_has_complex_polar_parts("P", "P", "0"); + assert_expression_has_complex_polar_parts("I", "1", "P/2"); + assert_expression_has_complex_polar_parts("abs(-3)", "3", "0"); + assert_expression_has_complex_polar_parts("abs(-3+I)", "abs(-3+I)", "0"); +} diff --git a/poincare/test/helper.cpp b/poincare/test/helper.cpp index 5cb153315..bbc7c1720 100644 --- a/poincare/test/helper.cpp +++ b/poincare/test/helper.cpp @@ -183,6 +183,7 @@ void assert_parsed_expression_serialize_to(Expression expression, const char * s #endif char buffer[500]; expression.serialize(buffer, sizeof(buffer), mode, numberOfSignifiantDigits); + translate_in_ASCII_chars(buffer); quiz_assert(strcmp(buffer, serializedExpression) == 0); } diff --git a/poincare/test/helper.h b/poincare/test/helper.h index bb31e28d9..cbd3084ef 100644 --- a/poincare/test/helper.h +++ b/poincare/test/helper.h @@ -32,7 +32,7 @@ template void assert_parsed_expression_approximates_with_value_for_symbol(Poincare::Expression expression, const char * symbol, T value, T approximation, Poincare::Preferences::AngleUnit angleUnit = Degree); void assert_parsed_expression_simplify_to(const char * expression, const char * simplifiedExpression, Poincare::Preferences::AngleUnit angleUnit = Poincare::Preferences::AngleUnit::Radian); -void assert_parsed_expression_serialize_to(Poincare::Expression expression, const char * serializedExpression, Poincare::Preferences::PrintFloatMode mode = DecimalMode, int numberOfSignifiantDigits = -1); +void assert_parsed_expression_serialize_to(Poincare::Expression expression, const char * serializedExpression, Poincare::Preferences::PrintFloatMode mode = DecimalMode, int numberOfSignifiantDigits = 7); // Layouts From 3c3f68c6c4155309a87b15957aa1b13ccacdf309 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 28 Nov 2018 11:50:40 +0100 Subject: [PATCH 066/373] [poincare] Multiplication and Division implement realPart, imaginaryPart and complexNorm --- poincare/include/poincare/division.h | 5 +++- poincare/include/poincare/multiplication.h | 14 +++++++---- poincare/src/division.cpp | 10 ++++++++ poincare/src/multiplication.cpp | 27 ++++++++++++++++++++-- poincare/test/complex.cpp | 6 ++--- 5 files changed, 50 insertions(+), 12 deletions(-) diff --git a/poincare/include/poincare/division.h b/poincare/include/poincare/division.h index 045a89c3a..85e6d6441 100644 --- a/poincare/include/poincare/division.h +++ b/poincare/include/poincare/division.h @@ -25,7 +25,10 @@ public: /* Property */ Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPart(context, angleUnit, true); } Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPart(context, angleUnit, false); } - // TODO: implement + Expression complexNorm(Context & context, Preferences::AngleUnit angleUnit) const override; + /* If we use the formula arg(a/b) = arg(a)-arg(b), we are likely to end up + * with subtractions of arcTangent. To avoid that, we compute the argument(a/b) + * from the real and imaginary part of a/b. */ // Properties Type type() const override { return Type::Division; } diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 328d5453c..733201df8 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -2,7 +2,6 @@ #define POINCARE_MULTIPLICATION_H #include -#include #include namespace Poincare { @@ -27,11 +26,13 @@ public: int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const override; // Complex - // TODO: implement realPart and imaginaryPart to optimize? - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartFromPolarParts(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartFromPolarParts(this, context, angleUnit); } + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexCartesianPart(context, angleUnit, true); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexCartesianPart(context, angleUnit, false); } Expression complexNorm(Context & context, Preferences::AngleUnit angleUnit) const override; - Expression complexArgument(Context & context, Preferences::AngleUnit angleUnit) const override; + /* If we use the formula arg(a*b) = arg(a)+arg(b), we are likely to end up + * with additions of arcTangent. To avoid that, we compute the argument(a*b) + * from the real and imaginary part of a*b. */ + //Expression complexArgument(Context & context, Preferences::AngleUnit angleUnit) const override; // Approximation template static Complex compute(const std::complex c, const std::complex d) { return Complex(c*d); } @@ -41,6 +42,9 @@ public: template static MatrixComplex computeOnMatrices(const MatrixComplex m, const MatrixComplex n); private: + // Complex + Expression complexCartesianPart(Context & context, Preferences::AngleUnit angleUnit, bool real) const; + // Property Expression setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override; diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index 8635d1369..44dc57c59 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -46,6 +46,16 @@ Expression DivisionNode::shallowReduce(Context & context, Preferences::AngleUnit return Division(this).shallowReduce(context, angleUnit, target); } +Expression DivisionNode::complexNorm(Context & context, Preferences::AngleUnit angleUnit) const { + Division d(this); + Expression r0 = d.childAtIndex(0).complexNorm(context, angleUnit); + Expression r1 = d.childAtIndex(1).complexNorm(context, angleUnit); + if (r0.isUninitialized() || r1.isUninitialized()) { + return Expression(); + } + return Division(r0,r1); +} + Expression DivisionNode::complexPart(Context & context, Preferences::AngleUnit angleUnit, bool real) const { Division e(this); Expression a = e.childAtIndex(0).realPart(context, angleUnit); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index ec8e64ac7..1c87f9935 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -28,6 +28,29 @@ ExpressionNode::Sign MultiplicationNode::sign() const { return (Sign)sign; } +Expression MultiplicationNode::complexCartesianPart(Context & context, Preferences::AngleUnit angleUnit, bool realPart) const { + Multiplication m(this); + int nbChildren = m.numberOfChildren(); + assert(nbChildren > 0); + Expression real = m.childAtIndex(0).realPart(context, angleUnit); + Expression imag = m.childAtIndex(0).imaginaryPart(context, angleUnit); + for (int i = 1; i < nbChildren; i++) { + if (real.isUninitialized() || imag.isUninitialized()) { + return Expression(); + } + Expression childReal = m.childAtIndex(i).realPart(context, angleUnit); + Expression childImag = m.childAtIndex(i).imaginaryPart(context, angleUnit); + if (childReal.isUninitialized() || childImag.isUninitialized()) { + return Expression(); + } + Expression newReal = Subtraction(Multiplication(real.clone(), childReal.clone()), Multiplication(imag.clone(), childImag.clone())); + Expression newImag = Addition(Multiplication(real, childImag), Multiplication(imag, childReal)); + real = newReal; + imag = newImag; + } + return realPart ? real : imag; +} + Expression MultiplicationNode::complexNorm(Context & context, Preferences::AngleUnit angleUnit) const { Multiplication m(this); Multiplication norm; @@ -41,7 +64,7 @@ Expression MultiplicationNode::complexNorm(Context & context, Preferences::Angle return norm; } -Expression MultiplicationNode::complexArgument(Context & context, Preferences::AngleUnit angleUnit) const { +/*Expression MultiplicationNode::complexArgument(Context & context, Preferences::AngleUnit angleUnit) const { Multiplication m(this); Addition arg; for (int i = 0; i < m.numberOfChildren(); i++) { @@ -53,7 +76,7 @@ Expression MultiplicationNode::complexArgument(Context & context, Preferences::A } return arg; } - +*/ int MultiplicationNode::polynomialDegree(Context & context, const char * symbolName) const { int degree = 0; for (ExpressionNode * c : children()) { diff --git a/poincare/test/complex.cpp b/poincare/test/complex.cpp index fd9ad3f47..aed432698 100644 --- a/poincare/test/complex.cpp +++ b/poincare/test/complex.cpp @@ -54,8 +54,7 @@ QUIZ_CASE(poincare_complex_parts) { assert_expression_has_complex_cartesian_parts("I+I", "0", "2"); assert_expression_has_complex_cartesian_parts("-2+2*I", "-2", "2"); assert_expression_has_complex_cartesian_parts("(3+I)-(2+4*I)", "1", "-3"); - // TODO: implement TODO of multiplication - //assert_expression_has_complex_cartesian_parts("(2+3*I)*(4-2*I)", "14", "8"); + assert_expression_has_complex_cartesian_parts("(2+3*I)*(4-2*I)", "14", "8"); assert_expression_has_complex_cartesian_parts("(3+I)/2", "3/2", "1/2"); assert_expression_has_complex_cartesian_parts("(3+I)/(2+I)", "7/5", "-1/5"); assert_expression_has_complex_cartesian_parts("(3+I)^(2+I)", "10*cos((-4*atan(3)+ln(2)+ln(5)+2*P)/2)*X^((2*atan(3)-P)/2)", "10*sin((-4*atan(3)+ln(2)+ln(5)+2*P)/2)*X^((2*atan(3)-P)/2)", Radian); @@ -134,8 +133,7 @@ QUIZ_CASE(poincare_complex_parts) { assert_expression_has_complex_polar_parts("I+I", "2", "P/2"); assert_expression_has_complex_polar_parts("-2+2*I", "2*R(2)", "(3*P)/4", Radian); assert_expression_has_complex_polar_parts("(3+I)-(2+4*I)", "R(10)", "(2*atan(1/3)-P)/2", Radian); - // TODO: implement TODO of multiplication - //assert_expression_has_complex_polar_parts("(2+3*I)*(4-2*I)", "2*R(65)", "(2*atan(7/4)-P)/2", Radian); + assert_expression_has_complex_polar_parts("(2+3*I)*(4-2*I)", "2*R(65)", "(-2*atan(7/4)+P)/2", Radian); assert_expression_has_complex_polar_parts("(3+I)/2", "R(10)/2", "(-2*atan(3)+P)/2", Radian); assert_expression_has_complex_polar_parts("(3+I)/(2+I)", "R(2)", "(2*atan(7)-P)/2", Radian); assert_expression_has_complex_polar_parts("(3+I)^(2+I)", "10*X^((2*atan(3)-P)/2)", "(-4*atan(3)+ln(2)+ln(5)+2*P)/2", Radian); From fe6a5af47bd67f5aaedfc51a6d9a1ad9ab5d5038 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 28 Nov 2018 14:57:00 +0100 Subject: [PATCH 067/373] [poincare] Change Expression::setSign signature --- poincare/include/poincare/absolute_value.h | 4 ++-- poincare/include/poincare/decimal.h | 4 ++-- poincare/include/poincare/expression.h | 2 +- poincare/include/poincare/expression_node.h | 2 +- poincare/include/poincare/factorial.h | 2 +- poincare/include/poincare/float.h | 2 +- poincare/include/poincare/infinity.h | 4 ++-- poincare/include/poincare/multiplication.h | 4 ++-- poincare/include/poincare/number.h | 2 +- poincare/include/poincare/power.h | 4 ++-- poincare/include/poincare/random.h | 4 ++-- poincare/include/poincare/rational.h | 2 +- poincare/include/poincare/sign_function.h | 2 +- poincare/include/poincare/undefined.h | 2 +- poincare/src/absolute_value.cpp | 6 +++--- poincare/src/addition.cpp | 2 +- poincare/src/decimal.cpp | 6 +++--- poincare/src/expression.cpp | 2 +- poincare/src/expression_node.cpp | 2 +- poincare/src/factorial.cpp | 2 +- poincare/src/float.cpp | 2 +- poincare/src/infinity.cpp | 4 ++-- poincare/src/multiplication.cpp | 14 +++++++------- poincare/src/power.cpp | 10 +++++----- poincare/src/random.cpp | 4 ++-- poincare/src/rational.cpp | 2 +- poincare/src/sign_function.cpp | 2 +- poincare/src/trigonometry.cpp | 4 ++-- poincare/src/undefined.cpp | 2 +- 29 files changed, 52 insertions(+), 52 deletions(-) diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 819f8a4ac..14fd29977 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -22,7 +22,7 @@ public: // Properties Type type() const override { return Type::AbsoluteValue; } Sign sign() const override { return Sign::Positive; } - Expression setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override; + Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; // Complex Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } @@ -60,7 +60,7 @@ private: explicit AbsoluteValue(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); } - Expression setSign(ExpressionNode::Sign s, Context & context, Preferences::AngleUnit angleUnit); + Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit); }; } diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index 9a54ec27b..204937875 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -49,7 +49,7 @@ public: // Properties Type type() const override { return Type::Decimal; } Sign sign() const override { return m_negative ? Sign::Negative : Sign::Positive; } - Expression setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override; + Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; // Approximation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { @@ -101,7 +101,7 @@ private: constexpr static int k_maxMantissaLength = 20; DecimalNode * node() const { return static_cast(Number::node()); } Decimal(size_t size, const Integer & m, int e); - Expression setSign(ExpressionNode::Sign s, Context & context, Preferences::AngleUnit angleUnit); + Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit); // Simplification Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit); diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 912683d34..ff33fb582 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -267,7 +267,7 @@ protected: Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { return node()->shallowReduce(context, angleUnit, target); } Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { return node()->shallowBeautify(context, angleUnit); } Expression deepBeautify(Context & context, Preferences::AngleUnit angleUnit); - Expression setSign(ExpressionNode::Sign s, Context & context, Preferences::AngleUnit angleUnit); + Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit); private: static constexpr int k_maxSymbolReplacementsCount = 10; diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index d13c2ab8c..248d2211e 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -106,7 +106,7 @@ public: virtual bool isNumber() const { return false; } /*!*/ virtual Expression replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression); /*!*/ virtual Expression replaceUnknown(const Symbol & symbol); - /*!*/ virtual Expression setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit); + /*!*/ virtual Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit); virtual int polynomialDegree(Context & context, const char * symbolName) const; /*!*/ virtual int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const; /*!*/ virtual Expression shallowReplaceReplaceableSymbols(Context & context); diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index 659734961..83a6a5b3c 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -22,7 +22,7 @@ public: // Properties Type type() const override { return Type::Factorial; } Sign sign() const override { return Sign::Positive; } - Expression setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override; + Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; // Complex Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } diff --git a/poincare/include/poincare/float.h b/poincare/include/poincare/float.h index 6c243c6bf..b999e61d2 100644 --- a/poincare/include/poincare/float.h +++ b/poincare/include/poincare/float.h @@ -40,7 +40,7 @@ public: // Properties Type type() const override { return Type::Float; } Sign sign() const override { return m_value < 0 ? Sign::Negative : Sign::Positive; } - Expression setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override; + Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override; // Layout diff --git a/poincare/include/poincare/infinity.h b/poincare/include/poincare/infinity.h index 6cd6efdb9..fb24216c2 100644 --- a/poincare/include/poincare/infinity.h +++ b/poincare/include/poincare/infinity.h @@ -9,7 +9,7 @@ class InfinityNode final : public NumberNode { public: void setNegative(bool negative) { m_negative = negative; } - Expression setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override; + Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; // TreeNode size_t size() const override { return sizeof(InfinityNode); } @@ -48,7 +48,7 @@ public: Infinity(bool negative) : Number(TreePool::sharedPool()->createTreeNode()) { node()->setNegative(negative); } - Expression setSign(ExpressionNode::Sign s, Context & context, Preferences::AngleUnit angleUnit); + Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit); static const char * Name() { return "inf"; } diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 733201df8..e56aa87d8 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -46,7 +46,7 @@ private: Expression complexCartesianPart(Context & context, Preferences::AngleUnit angleUnit, bool real) const; // Property - Expression setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override; + Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; // Layout bool childNeedsParenthesis(const TreeNode * child) const override; @@ -92,7 +92,7 @@ public: template static void computeOnArrays(T * m, T * n, T * result, int mNumberOfColumns, int mNumberOfRows, int nNumberOfColumns); // Expression - Expression setSign(ExpressionNode::Sign s, Context & context, Preferences::AngleUnit angleUnit); + Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit); Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit); int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const; diff --git a/poincare/include/poincare/number.h b/poincare/include/poincare/number.h index 40baa4cb8..dde67d910 100644 --- a/poincare/include/poincare/number.h +++ b/poincare/include/poincare/number.h @@ -46,7 +46,7 @@ public: static Number Power(const Number & i, const Number & j); static int NaturalOrder(const Number & i, const Number & j); - Number setSign(ExpressionNode::Sign s, Context & context, Preferences::AngleUnit angleUnit) { return Expression::setSign(s, context, angleUnit).convert(); } + Number setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit) { return Expression::setSign(s, context, angleUnit).convert(); } protected: Number() : Expression() {} NumberNode * node() const { return static_cast(Expression::node()); } diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index b155bb8f0..cce1d3050 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -30,7 +30,7 @@ public: // Properties Type type() const override { return Type::Power; } Sign sign() const override; - Expression setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override; + Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; int polynomialDegree(Context & context, const char * symbolName) const override; int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const override; @@ -73,7 +73,7 @@ class Power final : public Expression { public: Power(Expression base, Expression exponent); Power(const PowerNode * n) : Expression(n) {} - Expression setSign(ExpressionNode::Sign s, Context & context, Preferences::AngleUnit angleUnit); + Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit); int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const; Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit); diff --git a/poincare/include/poincare/random.h b/poincare/include/poincare/random.h index e20172e85..f84453a84 100644 --- a/poincare/include/poincare/random.h +++ b/poincare/include/poincare/random.h @@ -26,7 +26,7 @@ public: // Properties Type type() const override { return Type::Random; } Sign sign() const override { return Sign::Positive; } - Expression setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override; + Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; @@ -52,7 +52,7 @@ public: template static T random(); private: Random() : Expression(TreePool::sharedPool()->createTreeNode()) {} - Expression setSign(ExpressionNode::Sign s, Context & context, Preferences::AngleUnit angleUnit); + Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit); }; } diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index dcaa4175f..46aab0b6e 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -59,7 +59,7 @@ private: int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override; Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) override; - Expression setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override; + Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; Expression denominator(Context & context, Preferences::AngleUnit angleUnit) const override; bool m_negative; uint8_t m_numberOfDigitsNumerator; diff --git a/poincare/include/poincare/sign_function.h b/poincare/include/poincare/sign_function.h index 2ff96ff6c..85a76663c 100644 --- a/poincare/include/poincare/sign_function.h +++ b/poincare/include/poincare/sign_function.h @@ -22,7 +22,7 @@ public: // Properties Type type() const override { return Type::SignFunction; } Sign sign() const override; - Expression setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override; + Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; // Complex Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } diff --git a/poincare/include/poincare/undefined.h b/poincare/include/poincare/undefined.h index 31eb950a6..915d9e594 100644 --- a/poincare/include/poincare/undefined.h +++ b/poincare/include/poincare/undefined.h @@ -23,7 +23,7 @@ public: // Properties Type type() const override { return Type::Undefined; } int polynomialDegree(Context & context, const char * symbolName) const override; - Expression setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override; + Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; // Approximation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 6a16ccb95..1cc856463 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -12,7 +12,7 @@ constexpr Expression::FunctionHelper AbsoluteValue::s_functionHelper; int AbsoluteValueNode::numberOfChildren() const { return AbsoluteValue::s_functionHelper.numberOfChildren(); } -Expression AbsoluteValueNode::setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) { +Expression AbsoluteValueNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { return AbsoluteValue(this).setSign(s, context, angleUnit); } @@ -28,7 +28,7 @@ Expression AbsoluteValueNode::shallowReduce(Context & context, Preferences::Angl return AbsoluteValue(this).shallowReduce(context, angleUnit); } -Expression AbsoluteValue::setSign(ExpressionNode::Sign s, Context & context, Preferences::AngleUnit angleUnit) { +Expression AbsoluteValue::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit) { assert(s == ExpressionNode::Sign::Positive); return *this; } @@ -51,7 +51,7 @@ Expression AbsoluteValue::shallowReduce(Context & context, Preferences::AngleUni return c; } if (c.sign() == ExpressionNode::Sign::Negative) { - Expression result = c.setSign(ExpressionNode::Sign::Positive, context, angleUnit); + Expression result = c.setSign(ExpressionNode::Sign::Positive, &context, angleUnit); replaceWithInPlace(result); return result; } diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index b4a9f297d..6dfb5451e 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -129,7 +129,7 @@ Expression Addition::shallowBeautify(Context & context, Preferences::AngleUnit a if (m.childAtIndex(0).type() == ExpressionNode::Type::Rational && m.childAtIndex(0).convert().isMinusOne()) { m.removeChildAtIndexInPlace(0); } else { - m.childAtIndex(0).setSign(ExpressionNode::Sign::Positive, context, angleUnit); + m.childAtIndex(0).setSign(ExpressionNode::Sign::Positive, &context, angleUnit); } Expression subtractant = m.squashUnaryHierarchyInPlace(); diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index 8aeb5feca..1ab59a71b 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -56,7 +56,7 @@ size_t DecimalNode::size() const { return DecimalSize(m_numberOfDigitsInMantissa); } -Expression DecimalNode::setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) { +Expression DecimalNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { return Decimal(this).setSign(s, context, angleUnit); } @@ -336,7 +336,7 @@ Decimal::Decimal(size_t size, const Integer & m, int e) : Number(TreePool::share node()->setValue(m.digits(), m.numberOfDigits(), e, m.isNegative()); } -Expression Decimal::setSign(ExpressionNode::Sign s, Context & context, Preferences::AngleUnit angleUnit) { +Expression Decimal::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit) { Decimal result = *this; result.node()->setNegative(s == ExpressionNode::Sign::Negative); return result; @@ -372,7 +372,7 @@ Expression Decimal::shallowReduce(Context & context, Preferences::AngleUnit angl Expression Decimal::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { if (sign() == ExpressionNode::Sign::Negative) { - Expression abs = setSign(ExpressionNode::Sign::Positive, context, angleUnit); + Expression abs = setSign(ExpressionNode::Sign::Positive, &context, angleUnit); Opposite o; replaceWithInPlace(o); o.replaceChildAtIndexInPlace(0, abs); diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 6cd75323c..04adadb99 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -416,7 +416,7 @@ Expression Expression::deepBeautify(Context & context, Preferences::AngleUnit an return e; } -Expression Expression::setSign(ExpressionNode::Sign s, Context & context, Preferences::AngleUnit angleUnit) { +Expression Expression::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit) { return node()->setSign(s, context, angleUnit); } diff --git a/poincare/src/expression_node.cpp b/poincare/src/expression_node.cpp index e45906e11..8b7a4bf00 100644 --- a/poincare/src/expression_node.cpp +++ b/poincare/src/expression_node.cpp @@ -21,7 +21,7 @@ Expression ExpressionNode::replaceUnknown(const Symbol & symbol) { return Expression(this).defaultReplaceUnknown(symbol); } -Expression ExpressionNode::setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) { +Expression ExpressionNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { assert(false); return Expression(); } diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index c53ecd55a..c2cbd0c04 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -14,7 +14,7 @@ namespace Poincare { // Property -Expression FactorialNode::setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) { +Expression FactorialNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { assert(s == Sign::Positive); return Factorial(this); } diff --git a/poincare/src/float.cpp b/poincare/src/float.cpp index 0ac32507d..c1c144996 100644 --- a/poincare/src/float.cpp +++ b/poincare/src/float.cpp @@ -4,7 +4,7 @@ namespace Poincare { template -Expression FloatNode::setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) { +Expression FloatNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { Expression thisExpr = Number(this); Expression result = Float(-m_value); thisExpr.replaceWithInPlace(result); diff --git a/poincare/src/infinity.cpp b/poincare/src/infinity.cpp index 691fb0f48..2302fbdfb 100644 --- a/poincare/src/infinity.cpp +++ b/poincare/src/infinity.cpp @@ -9,7 +9,7 @@ extern "C" { namespace Poincare { -Expression InfinityNode::setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) { +Expression InfinityNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { return Infinity(this).setSign(s, context, angleUnit); } @@ -30,7 +30,7 @@ template Evaluation InfinityNode::templatedApproximate() const { return Complex(m_negative ? -INFINITY : INFINITY); } -Expression Infinity::setSign(ExpressionNode::Sign s, Context & context, Preferences::AngleUnit angleUnit) { +Expression Infinity::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit) { Expression result = Infinity(s == ExpressionNode::Sign::Negative); replaceWithInPlace(result); return result; diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 1c87f9935..31230994f 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -112,7 +112,7 @@ MatrixComplex MultiplicationNode::computeOnMatrices(const MatrixComplex m, return result; } -Expression MultiplicationNode::setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) { +Expression MultiplicationNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { return Multiplication(this).setSign(s, context, angleUnit); } @@ -168,14 +168,14 @@ void Multiplication::computeOnArrays(T * m, T * n, T * result, int mNumberOfColu } } -Expression Multiplication::setSign(ExpressionNode::Sign s, Context & context, Preferences::AngleUnit angleUnit) { +Expression Multiplication::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit) { assert(s == ExpressionNode::Sign::Positive); for (int i = 0; i < numberOfChildren(); i++) { if (childAtIndex(i).sign() == ExpressionNode::Sign::Negative) { replaceChildAtIndexInPlace(i, childAtIndex(i).setSign(s, context, angleUnit)); } } - return shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); + return shallowReduce(*context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); } Expression Multiplication::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { @@ -195,7 +195,7 @@ Expression Multiplication::shallowBeautify(Context & context, Preferences::Angle if (child0.type() == ExpressionNode::Type::Rational && static_cast(child0).isMinusOne()) { removeChildAtIndexInPlace(0); } else { - child0.setSign(ExpressionNode::Sign::Positive, context, angleUnit); + child0.setSign(ExpressionNode::Sign::Positive, &context, angleUnit); } Expression e = squashUnaryHierarchyInPlace(); Opposite o = Opposite(); @@ -664,8 +664,8 @@ void Multiplication::factorizeSineAndCosine(int i, int j, Context & context, Pre return; } Number sumPQ = Number::Addition(p, q); - Number absP = p.clone().convert().setSign(ExpressionNode::Sign::Positive, context, angleUnit); - Number absQ = q.clone().convert().setSign(ExpressionNode::Sign::Positive, context, angleUnit); + Number absP = p.clone().convert().setSign(ExpressionNode::Sign::Positive, &context, angleUnit); + Number absQ = q.clone().convert().setSign(ExpressionNode::Sign::Positive, &context, angleUnit); Expression tan = Tangent::Builder(x.clone()); if (Number::NaturalOrder(absP, absQ) < 0) { // Replace sin(x) by tan(x) or sin(x)^p by tan(x)^p @@ -753,7 +753,7 @@ Expression Multiplication::mergeNegativePower(Context & context, Preferences::An while (i < numberOfChildren()) { if (childAtIndex(i).type() == ExpressionNode::Type::Power && childAtIndex(i).childAtIndex(1).sign() == ExpressionNode::Sign::Negative) { Expression e = childAtIndex(i); - e.childAtIndex(1).setSign(ExpressionNode::Sign::Positive, context, angleUnit); + e.childAtIndex(1).setSign(ExpressionNode::Sign::Positive, &context, angleUnit); removeChildAtIndexInPlace(i); m.addChildAtIndexInPlace(e, m.numberOfChildren(), m.numberOfChildren()); e.shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 58453bc39..158b564b6 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -47,7 +47,7 @@ ExpressionNode::Sign PowerNode::sign() const { return Sign::Unknown; } -Expression PowerNode::setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) { +Expression PowerNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { return Power(this).setSign(s, context, angleUnit); } @@ -244,7 +244,7 @@ Power::Power(Expression base, Expression exponent) : Expression(TreePool::shared replaceChildAtIndexInPlace(1, exponent); } -Expression Power::setSign(ExpressionNode::Sign s, Context & context, Preferences::AngleUnit angleUnit) { +Expression Power::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit) { assert(s == ExpressionNode::Sign::Positive); assert(childAtIndex(0).sign() == ExpressionNode::Sign::Negative); Expression result = Power(childAtIndex(0).setSign(ExpressionNode::Sign::Positive, context, angleUnit), childAtIndex(1)); @@ -552,7 +552,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU // (sign(a)*b*...)^r if (factor.sign() == ExpressionNode::Sign::Negative) { m.replaceChildAtIndexInPlace(i, Rational(-1)); - factor = factor.setSign(ExpressionNode::Sign::Positive, context, angleUnit); + factor = factor.setSign(ExpressionNode::Sign::Positive, &context, angleUnit); } else { m.removeChildAtIndexInPlace(i); } @@ -732,7 +732,7 @@ Expression Power::shallowBeautify(Context & context, Preferences::AngleUnit angl // Simplification Expression Power::denominator(Context & context, Preferences::AngleUnit angleUnit) const { if (childAtIndex(1).sign() == ExpressionNode::Sign::Negative) { - Expression positivePowerClone = Power(childAtIndex(0).clone(), childAtIndex(1).clone().setSign(ExpressionNode::Sign::Positive, context, angleUnit)); + Expression positivePowerClone = Power(childAtIndex(0).clone(), childAtIndex(1).clone().setSign(ExpressionNode::Sign::Positive, &context, angleUnit)); if (positivePowerClone.childAtIndex(1).type() == ExpressionNode::Type::Rational && positivePowerClone.childAtIndex(1).convert().isOne()) { return positivePowerClone.childAtIndex(0); } @@ -803,7 +803,7 @@ Expression Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational r, bo if (numberOfPrimeFactors < 0) { /* We could not break i in prime factors (it might take either too many * factors or too much time). */ - Expression rClone = r.clone().setSign(isDenominator ? ExpressionNode::Sign::Negative : ExpressionNode::Sign::Positive, context, angleUnit); + Expression rClone = r.clone().setSign(isDenominator ? ExpressionNode::Sign::Negative : ExpressionNode::Sign::Positive, &context, angleUnit); return Power(Rational(i), rClone); } diff --git a/poincare/src/random.cpp b/poincare/src/random.cpp index 66474af83..ef8efd518 100644 --- a/poincare/src/random.cpp +++ b/poincare/src/random.cpp @@ -12,7 +12,7 @@ constexpr Expression::FunctionHelper Random::s_functionHelper; int RandomNode::numberOfChildren() const { return Random::s_functionHelper.numberOfChildren(); } -Expression RandomNode::setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) { +Expression RandomNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { return Random(this).setSign(s, context, angleUnit); } @@ -28,7 +28,7 @@ template Evaluation RandomNode::templateApproximate() const { return Complex(Random::random()); } -Expression Random::setSign(ExpressionNode::Sign s, Context & context, Preferences::AngleUnit angleUnit) { +Expression Random::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit) { assert(s == ExpressionNode::Sign::Positive); return *this; } diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index 886465c1f..7edd58ac1 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -98,7 +98,7 @@ int RationalNode::serialize(char * buffer, int bufferSize, Preferences::PrintFlo // Expression subclassing -Expression RationalNode::setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) { +Expression RationalNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { return Rational(this).setSign(s); } diff --git a/poincare/src/sign_function.cpp b/poincare/src/sign_function.cpp index 34a56f61f..e1534f65e 100644 --- a/poincare/src/sign_function.cpp +++ b/poincare/src/sign_function.cpp @@ -16,7 +16,7 @@ ExpressionNode::Sign SignFunctionNode::sign() const { return childAtIndex(0)->sign(); } -Expression SignFunctionNode::setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) { +Expression SignFunctionNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { SignFunction sign(this); Rational r(s == ExpressionNode::Sign::Positive ? 1 : -1); sign.replaceWithInPlace(r); diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 5aac41b0d..0932b9dc2 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -61,7 +61,7 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& co // Step 3. Look for an expression of type "cos(-a)", return "+/-cos(a)" if (e.childAtIndex(0).sign() == ExpressionNode::Sign::Negative) { - e.childAtIndex(0).setSign(ExpressionNode::Sign::Positive, context, angleUnit).shallowReduce(context, angleUnit, target); + e.childAtIndex(0).setSign(ExpressionNode::Sign::Positive, &context, angleUnit).shallowReduce(context, angleUnit, target); if (e.type() == ExpressionNode::Type::Cosine) { return e.shallowReduce(context, angleUnit, target); } else { @@ -198,7 +198,7 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& c { Expression newArgument; if (e.childAtIndex(0).sign() == ExpressionNode::Sign::Negative) { - newArgument = e.childAtIndex(0).setSign(ExpressionNode::Sign::Positive, context, angleUnit); + newArgument = e.childAtIndex(0).setSign(ExpressionNode::Sign::Positive, &context, angleUnit); } else { newArgument = e.childAtIndex(0); static_cast(newArgument).removeChildAtIndexInPlace(0); diff --git a/poincare/src/undefined.cpp b/poincare/src/undefined.cpp index 9b02099e6..1279a91ed 100644 --- a/poincare/src/undefined.cpp +++ b/poincare/src/undefined.cpp @@ -13,7 +13,7 @@ int UndefinedNode::polynomialDegree(Context & context, const char * symbolName) return -1; } -Expression UndefinedNode::setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) { +Expression UndefinedNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { return Undefined(); } From 476a79565fae765deca4e777f82399c4d3aed1fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 28 Nov 2018 15:00:53 +0100 Subject: [PATCH 068/373] [poincare] Number::setSign does not need a context or angleUnit --- poincare/include/poincare/decimal.h | 2 +- poincare/include/poincare/number.h | 4 +++- poincare/src/decimal.cpp | 6 +++--- poincare/src/multiplication.cpp | 4 ++-- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index 204937875..5b37b3e6d 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -101,7 +101,7 @@ private: constexpr static int k_maxMantissaLength = 20; DecimalNode * node() const { return static_cast(Number::node()); } Decimal(size_t size, const Integer & m, int e); - Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit); + Expression setSign(ExpressionNode::Sign s); // Simplification Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit); diff --git a/poincare/include/poincare/number.h b/poincare/include/poincare/number.h index dde67d910..1d6e542fd 100644 --- a/poincare/include/poincare/number.h +++ b/poincare/include/poincare/number.h @@ -46,7 +46,9 @@ public: static Number Power(const Number & i, const Number & j); static int NaturalOrder(const Number & i, const Number & j); - Number setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit) { return Expression::setSign(s, context, angleUnit).convert(); } + /* Number::setSign does not need a context or an angle unit (a number can be + * Infinity, Undefined, Float, Decimal, Rational). */ + Number setSign(ExpressionNode::Sign s) { return Expression::setSign(s, nullptr, Preferences::AngleUnit::Degree).convert(); } protected: Number() : Expression() {} NumberNode * node() const { return static_cast(Expression::node()); } diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index 1ab59a71b..736588d7d 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -57,7 +57,7 @@ size_t DecimalNode::size() const { } Expression DecimalNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { - return Decimal(this).setSign(s, context, angleUnit); + return Decimal(this).setSign(s); } int DecimalNode::simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const { @@ -336,7 +336,7 @@ Decimal::Decimal(size_t size, const Integer & m, int e) : Number(TreePool::share node()->setValue(m.digits(), m.numberOfDigits(), e, m.isNegative()); } -Expression Decimal::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit) { +Expression Decimal::setSign(ExpressionNode::Sign s) { Decimal result = *this; result.node()->setNegative(s == ExpressionNode::Sign::Negative); return result; @@ -372,7 +372,7 @@ Expression Decimal::shallowReduce(Context & context, Preferences::AngleUnit angl Expression Decimal::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { if (sign() == ExpressionNode::Sign::Negative) { - Expression abs = setSign(ExpressionNode::Sign::Positive, &context, angleUnit); + Expression abs = setSign(ExpressionNode::Sign::Positive); Opposite o; replaceWithInPlace(o); o.replaceChildAtIndexInPlace(0, abs); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 31230994f..70fc45dc1 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -664,8 +664,8 @@ void Multiplication::factorizeSineAndCosine(int i, int j, Context & context, Pre return; } Number sumPQ = Number::Addition(p, q); - Number absP = p.clone().convert().setSign(ExpressionNode::Sign::Positive, &context, angleUnit); - Number absQ = q.clone().convert().setSign(ExpressionNode::Sign::Positive, &context, angleUnit); + Number absP = p.clone().convert().setSign(ExpressionNode::Sign::Positive); + Number absQ = q.clone().convert().setSign(ExpressionNode::Sign::Positive); Expression tan = Tangent::Builder(x.clone()); if (Number::NaturalOrder(absP, absQ) < 0) { // Replace sin(x) by tan(x) or sin(x)^p by tan(x)^p From f452d8fced94d5d03c44e04e1cdac0df15359c7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 28 Nov 2018 15:14:06 +0100 Subject: [PATCH 069/373] [poincare] Fatorize code of Complex::complexToExpression in Expression::CreateComplexExpression that create the expression a+i*b or r*e^(i*th) from 2 expressions representing a & b or r & th. --- poincare/include/poincare/decimal.h | 2 + poincare/include/poincare/expression.h | 6 +++ poincare/src/complex.cpp | 73 ++++++-------------------- poincare/src/expression.cpp | 69 ++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 58 deletions(-) diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index 5b37b3e6d..4c5b2bace 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -86,6 +86,8 @@ private: class Decimal final : public Number { friend class Number; friend class DecimalNode; +template +friend class ComplexNode; public: static int Exponent(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, const char * exponent, int exponentLength, bool exponentIsNegative = false); Decimal(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, int exponent); diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index ff33fb582..2c26fc8b1 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -26,6 +26,8 @@ class Expression : public TreeHandle { friend class BinomialCoefficient; friend class Ceiling; friend class CommonLogarithm; + template + friend class ComplexNode; friend class ComplexArgument; friend class ComplexHelper; friend class ConfidenceInterval; @@ -288,6 +290,10 @@ private: Expression defaultReplaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression expression); int defaultGetPolynomialCoefficients(Context & context, const char * symbol, Expression expression[]) const; + /* Builder */ + typedef Expression (*TransformExpression)(Expression e); + static Expression CreateComplexExpression(Expression ra, Expression tb, Preferences::ComplexFormat complexFormat, bool undefined, bool isZeroRa, bool isOneRa, bool isZeroTb, bool isOneTb, bool isMinusOneTb, bool isNegativeTb, TransformExpression inverse); + /* Expression roots/extrema solver*/ constexpr static double k_solverPrecision = 1.0E-5; constexpr static double k_sqrtEps = 1.4901161193847656E-8; // sqrt(DBL_EPSILON) diff --git a/poincare/src/complex.cpp b/poincare/src/complex.cpp index 2319f2eec..76e878db4 100644 --- a/poincare/src/complex.cpp +++ b/poincare/src/complex.cpp @@ -42,67 +42,24 @@ T ComplexNode::toScalar() const { template Expression ComplexNode::complexToExpression(Preferences::ComplexFormat complexFormat) const { - if (std::isnan(this->real()) || std::isnan(this->imag())) { - return Undefined(); - } + T ra, tb; if (complexFormat == Preferences::ComplexFormat::Cartesian) { - Expression real; - Expression imag; - if (this->real() != 0 || this->imag() == 0) { - real = Number::DecimalNumber(this->real()); - } - if (this->imag() != 0) { - if (this->imag() == 1.0 || this->imag() == -1) { - imag = Constant(Ion::Charset::IComplex); - } else if (this->imag() > 0) { - imag = Multiplication(Number::DecimalNumber(this->imag()), Constant(Ion::Charset::IComplex)); - } else { - imag = Multiplication(Number::DecimalNumber(-this->imag()), Constant(Ion::Charset::IComplex)); - } - } - if (imag.isUninitialized()) { - return real; - } else if (real.isUninitialized()) { - if (this->imag() > 0) { - return imag; - } else { - return Opposite(imag); - } - return imag; - } else if (this->imag() > 0) { - return Addition(real, imag); - } else { - return Subtraction(real, imag); - } - } - assert(complexFormat == Preferences::ComplexFormat::Polar); - Expression norm; - Expression exp; - T r = std::abs(*this); - T th = std::arg(*this); - if (r != 1 || th == 0) { - norm = Number::DecimalNumber(r); - } - if (r != 0 && th != 0) { - Expression arg; - if (th == 1.0) { - arg = Constant(Ion::Charset::IComplex); - } else if (th == -1.0) { - arg = Opposite(Constant(Ion::Charset::IComplex)); - } else if (th > 0) { - arg = Multiplication(Number::DecimalNumber(th), Constant(Ion::Charset::IComplex)); - } else { - arg = Opposite(Multiplication(Number::DecimalNumber(-th), Constant(Ion::Charset::IComplex))); - } - exp = Power(Constant(Ion::Charset::Exponential), arg); - } - if (exp.isUninitialized()) { - return norm; - } else if (norm.isUninitialized()) { - return exp; + ra = this->real(); + tb = this->imag(); } else { - return Multiplication(norm, exp); + ra = std::abs(*this); + tb = std::arg(*this); } + return Expression::CreateComplexExpression( + Number::DecimalNumber(ra), + Number::DecimalNumber(tb), + complexFormat, + (std::isnan(this->real()) || std::isnan(this->imag())), + ra == 0.0, ra == 1.0, tb == 0.0, tb == 1.0, tb == -1.0, tb < 0.0, + [](Expression e) { + assert(e.type() == ExpressionNode::Type::Undefined || e.type() == ExpressionNode::Type::Rational || e.type() == ExpressionNode::Type::Float || e.type() == ExpressionNode::Type::Decimal || e.type() == ExpressionNode::Type::Infinity); + return Expression(static_cast(e).setSign(ExpressionNode::Sign::Positive)); } + ); } template diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 04adadb99..061eee666 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -455,6 +455,75 @@ U Expression::epsilon() { return epsilon; } +/* Builder */ + +Expression Expression::CreateComplexExpression(Expression ra, Expression tb, Preferences::ComplexFormat complexFormat, bool undefined, bool isZeroRa, bool isOneRa, bool isZeroTb, bool isOneTb, bool isMinusOneTb, bool isNegativeTb, TransformExpression inverse) { + if (undefined) { + return Undefined(); + } + switch (complexFormat) { + case Preferences::ComplexFormat::Cartesian: + { + Expression real; + Expression imag; + if (!isZeroRa || isZeroTb) { + real = ra; + } + if (!isZeroTb) { + if (isOneTb || isMinusOneTb) { + imag = Constant(Ion::Charset::IComplex); + } else if (isNegativeTb) { + imag = Multiplication(inverse(tb), Constant(Ion::Charset::IComplex)); + } else { + imag = Multiplication(tb , Constant(Ion::Charset::IComplex)); + } + } + if (imag.isUninitialized()) { + return real; + } else if (real.isUninitialized()) { + if (isNegativeTb) { + return Opposite(imag); + } else { + return imag; + } + } else if (isNegativeTb) { + return Subtraction(real, imag); + } else { + return Addition(real, imag); + } + } + default: + { + assert(complexFormat == Preferences::ComplexFormat::Polar); + Expression norm; + Expression exp; + if (!isOneRa || isZeroTb) { + norm = ra; + } + if (!isZeroRa && !isZeroTb) { + Expression arg; + if (isOneTb) { + arg = Constant(Ion::Charset::IComplex); + } else if (isMinusOneTb) { + arg = Opposite(Constant(Ion::Charset::IComplex)); + } else if (isNegativeTb) { + arg = Opposite(Multiplication(inverse(tb), Constant(Ion::Charset::IComplex))); + } else { + arg = Multiplication(tb, Constant(Ion::Charset::IComplex)); + } + exp = Power(Constant(Ion::Charset::Exponential), arg); + } + if (exp.isUninitialized()) { + return norm; + } else if (norm.isUninitialized()) { + return exp; + } else { + return Multiplication(norm, exp); + } + } + } +} + /* Expression roots/extrema solver*/ typename Expression::Coordinate2D Expression::nextMinimum(const char * symbol, double start, double step, double max, Context & context, Preferences::AngleUnit angleUnit) const { From 56c8e8b7049fe3bb7666185725e83e67782c104c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 28 Nov 2018 16:19:53 +0100 Subject: [PATCH 070/373] [poincare] Expression: create method ParseAndSimplifyForComplexFormat --- poincare/include/poincare/expression.h | 5 ++- poincare/src/expression.cpp | 50 ++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 2c26fc8b1..43017e8aa 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -180,7 +180,8 @@ public: int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const; /* Simplification */ - static Expression ParseAndSimplify(const char * text, Context & context, Preferences::AngleUnit angleUnit); + static Expression ParseAndSimplify(const char * text, Context & context, Preferences::AngleUnit angleUnit) { return ParseAndProcess(text, context, angleUnit, Preferences::ComplexFormat::Cartesian, false); } + static Expression ParseAndSimplifyForComplexFormat(const char * text, Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) { return ParseAndProcess(text, context, angleUnit, complexFormat, true); } Expression simplify(Context & context, Preferences::AngleUnit angleUnit); Expression reduce(Context & context, Preferences::AngleUnit angleUnit); static Expression ExpressionWithoutSymbols(Expression expressionWithSymbols, Context & context); @@ -275,6 +276,8 @@ private: static constexpr int k_maxSymbolReplacementsCount = 10; static bool sSymbolReplacementsCountLock; /* Simplification */ + static Expression ParseAndProcess(const char * text, Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat, bool complexSimplify); + Expression simplifyForComplexFormat(Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat); Expression deepReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); void deepReduceChildren(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { return node()->deepReduceChildren(context, angleUnit, target); diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 061eee666..a18ef9448 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -324,12 +324,12 @@ int Expression::serialize(char * buffer, int bufferSize, Preferences::PrintFloat /* Simplification */ -Expression Expression::ParseAndSimplify(const char * text, Context & context, Preferences::AngleUnit angleUnit) { +Expression Expression::ParseAndProcess(const char * text, Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat, bool complexSimplify) { Expression exp = Parse(text); if (exp.isUninitialized()) { return Undefined(); } - exp = exp.simplify(context, angleUnit); + exp = complexSimplify ? exp.simplifyForComplexFormat(context, angleUnit, complexFormat) : exp.simplify(context, angleUnit); /* simplify might have been interrupted, in which case the resulting * expression is uninitialized, so we need to check that. */ if (exp.isUninitialized()) { @@ -347,6 +347,52 @@ Expression Expression::simplify(Context & context, Preferences::AngleUnit angleU return sSimplificationHasBeenInterrupted ? Expression() : e; } +bool isZero(const Expression e) { + return e.type() == ExpressionNode::Type::Rational && static_cast(e).isZero(); +} +bool isOne(const Expression e) { + return e.type() == ExpressionNode::Type::Rational && static_cast(e).isOne(); +} +bool isMinusOne(const Expression e) { + Expression c = e.numberOfChildren() > 0 ? e.childAtIndex(0) : Expression(); + return e.type() == ExpressionNode::Type::Opposite && e.childAtIndex(0).type() == ExpressionNode::Type::Rational && static_cast(c).isOne(); +} + +Expression Expression::simplifyForComplexFormat(Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) { + sSimplificationHasBeenInterrupted = false; + Expression e = deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); + if (sSimplificationHasBeenInterrupted) { + return Expression(); + } + Expression ra = complexFormat == Preferences::ComplexFormat::Cartesian ? e.realPart(context, angleUnit) : e.complexNorm(context, angleUnit); + Expression tb = complexFormat == Preferences::ComplexFormat::Cartesian ? e.imaginaryPart(context, angleUnit) : e.complexArgument(context, angleUnit); + if (ra.isUninitialized() || tb.isUninitialized()) { + return e.deepBeautify(context, angleUnit); + } + ra = ra.simplify(context, angleUnit); + tb = tb.simplify(context, angleUnit); + if (ra.isUninitialized() || tb.isUninitialized()) { + return e.deepBeautify(context, angleUnit); + } + e = CreateComplexExpression(ra, tb, complexFormat, + ra.type() == ExpressionNode::Type::Undefined || tb.type() == ExpressionNode::Type::Undefined, + isZero(ra), isOne(ra), isZero(tb), isOne(tb), isMinusOne(tb), + tb.type() == ExpressionNode::Type::Opposite || (tb.type() == ExpressionNode::Type::Rational && tb.sign() == ExpressionNode::Sign::Negative), + [](Expression e) { + if (e.type() == ExpressionNode::Type::Opposite) { + return e.childAtIndex(0); + } else { + assert(e.type() == ExpressionNode::Type::Undefined || e.type() == ExpressionNode::Type::Rational || e.type() == ExpressionNode::Type::Float || e.type() == ExpressionNode::Type::Decimal || e.type() == ExpressionNode::Type::Infinity); + return Expression(static_cast(e).setSign(ExpressionNode::Sign::Positive)); + } + } + ); + if (sSimplificationHasBeenInterrupted) { + return Expression(); + } + return e; +} + Expression Expression::ExpressionWithoutSymbols(Expression e, Context & context) { if (e.isUninitialized()) { return e; From 79e7fb2183ce30d16d44fa28272c65b087ba8177 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 28 Nov 2018 16:20:31 +0100 Subject: [PATCH 071/373] [calculation] Use ParseAndSimplifyForComplexFormat instead of ParseAndSimplify --- apps/calculation/calculation.cpp | 2 +- apps/shared/poincare_helpers.h | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/calculation/calculation.cpp b/apps/calculation/calculation.cpp index 4e1105697..14e99efb3 100644 --- a/apps/calculation/calculation.cpp +++ b/apps/calculation/calculation.cpp @@ -41,7 +41,7 @@ void Calculation::setContent(const char * c, Context * context, Expression ansEx * to keep Ans symbol in the calculation store. */ PoincareHelpers::Serialize(input, m_inputText, sizeof(m_inputText)); } - Expression exactOutput = PoincareHelpers::ParseAndSimplify(m_inputText, *context); + Expression exactOutput = PoincareHelpers::ParseAndSimplifyForComplexFormat(m_inputText, *context); PoincareHelpers::Serialize(exactOutput, m_exactOutputText, sizeof(m_exactOutputText)); Expression approximateOutput = PoincareHelpers::Approximate(exactOutput, *context); PoincareHelpers::Serialize(approximateOutput, m_approximateOutputText, sizeof(m_approximateOutputText)); diff --git a/apps/shared/poincare_helpers.h b/apps/shared/poincare_helpers.h index a9a2b9ef6..e57f89d2b 100644 --- a/apps/shared/poincare_helpers.h +++ b/apps/shared/poincare_helpers.h @@ -41,6 +41,10 @@ inline Poincare::Expression ParseAndSimplify(const char * text, Poincare::Contex return Poincare::Expression::ParseAndSimplify(text, context, Poincare::Preferences::sharedPreferences()->angleUnit()); } +inline Poincare::Expression ParseAndSimplifyForComplexFormat(const char * text, Poincare::Context & context) { + return Poincare::Expression::ParseAndSimplifyForComplexFormat(text, context, Poincare::Preferences::sharedPreferences()->angleUnit(), Poincare::Preferences::sharedPreferences()->complexFormat()); +} + inline void Simplify(Poincare::Expression * e, Poincare::Context & context) { *e = e->simplify(context, Poincare::Preferences::sharedPreferences()->angleUnit()); } From 5dae60bc7eb34e45074acc041c9f960e03473e5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 28 Nov 2018 17:25:22 +0100 Subject: [PATCH 072/373] [poincare] Complex parts getters (realPart, imaginaryPart, complexNorm...) simplify while building the complex part --- poincare/include/poincare/complex_helper.h | 2 +- poincare/include/poincare/expression.h | 4 +-- poincare/src/addition.cpp | 2 +- poincare/src/complex_helper.cpp | 8 +++--- poincare/src/conjugate.cpp | 2 +- poincare/src/division.cpp | 29 ++++++++++++++++++--- poincare/src/expression.cpp | 8 +++--- poincare/src/expression_node.cpp | 27 +++++++++++++++---- poincare/src/multiplication.cpp | 14 +++++++--- poincare/src/nth_root.cpp | 30 +++++++++++++++++++--- poincare/src/opposite.cpp | 2 +- poincare/src/power.cpp | 20 ++++++++++++--- poincare/src/square_root.cpp | 4 +-- poincare/src/subtraction.cpp | 2 +- 14 files changed, 118 insertions(+), 36 deletions(-) diff --git a/poincare/include/poincare/complex_helper.h b/poincare/include/poincare/complex_helper.h index 96fd6079a..2bddd7719 100644 --- a/poincare/include/poincare/complex_helper.h +++ b/poincare/include/poincare/complex_helper.h @@ -14,7 +14,7 @@ public: return cartesianPartOfComplexFunction(e, context, angleUnit, false); } static Expression realPartRealFunction(const ExpressionNode * e, Context & context, Preferences::AngleUnit angleUnit) { - return Expression(e).clone(); + return Expression(e).clone().deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); } static Expression imaginaryPartRealFunction(const ExpressionNode * e, Context & context, Preferences::AngleUnit angleUnit); // static Expression realPartMatrix(const Expression e, Context & context, Preferences::AngleUnit angleUnit); diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 43017e8aa..b91f57e33 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -185,8 +185,8 @@ public: Expression simplify(Context & context, Preferences::AngleUnit angleUnit); Expression reduce(Context & context, Preferences::AngleUnit angleUnit); static Expression ExpressionWithoutSymbols(Expression expressionWithSymbols, Context & context); - Expression radianToDegree(); - Expression degreeToRadian(); + Expression radianToDegree(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression degreeToRadian(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); /* Approximation Helper */ template static U epsilon(); diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 6dfb5451e..7cbc77fee 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -40,7 +40,7 @@ Expression AdditionNode::complexPart(Context & context, Preferences::AngleUnit a } result.addChildAtIndexInPlace(part, result.numberOfChildren(), result.numberOfChildren()); } - return result; + return result.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } // Layout diff --git a/poincare/src/complex_helper.cpp b/poincare/src/complex_helper.cpp index 2d571ae8e..4ccb4f423 100644 --- a/poincare/src/complex_helper.cpp +++ b/poincare/src/complex_helper.cpp @@ -13,9 +13,7 @@ Expression ComplexHelper::cartesianPartOfComplexFunction(const ExpressionNode * return Expression(); } if (real) { - Expression result = e.clone(); - result.replaceChildAtIndexInPlace(0, e.childAtIndex(0).realPart(context, angleUnit)); - return result; + return e.clone().deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); } return Rational(0); } @@ -31,14 +29,14 @@ Expression ComplexHelper::complexCartesianPartFromPolarParts(const ExpressionNod if (r.isUninitialized() || th.isUninitialized()) { return Expression(); } - Expression argument = angleUnit == Preferences::AngleUnit::Radian ? th : th.radianToDegree(); + Expression argument = angleUnit == Preferences::AngleUnit::Radian ? th : th.radianToDegree(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); Expression trigo; if (isReal) { trigo = Cosine::Builder(argument); } else { trigo = Sine::Builder(argument); } - return Multiplication(r, trigo); + return Multiplication(r, trigo.shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation)).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); } } diff --git a/poincare/src/conjugate.cpp b/poincare/src/conjugate.cpp index 26825f9a5..2decdaf19 100644 --- a/poincare/src/conjugate.cpp +++ b/poincare/src/conjugate.cpp @@ -19,7 +19,7 @@ Expression ConjugateNode::realPart(Context & context, Preferences::AngleUnit ang Expression ConjugateNode::imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const { Expression e = childAtIndex(0)->imaginaryPart(context, angleUnit); if (!e.isUninitialized()) { - return Opposite(e); + return Opposite(e).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } return Expression(); } diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index 44dc57c59..8cdace321 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -53,7 +53,7 @@ Expression DivisionNode::complexNorm(Context & context, Preferences::AngleUnit a if (r0.isUninitialized() || r1.isUninitialized()) { return Expression(); } - return Division(r0,r1); + return Division(r0,r1).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } Expression DivisionNode::complexPart(Context & context, Preferences::AngleUnit angleUnit, bool real) const { @@ -65,11 +65,32 @@ Expression DivisionNode::complexPart(Context & context, Preferences::AngleUnit a if (a.isUninitialized() || b.isUninitialized() || c.isUninitialized() || d.isUninitialized()) { return Expression(); } - Expression denominator = Addition(Power(c.clone(), Rational(2)), Power(d.clone(), Rational(2))); + Expression denominator = + Addition( + Power( + c.clone(), + Rational(2) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Power( + d.clone(), + Rational(2) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); if (real) { - return Division(Addition(Multiplication(a, c), Multiplication(b, d)), denominator); + return Division( + Addition( + Multiplication(a, c).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Multiplication(b, d).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + denominator + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } - return Division(Subtraction(Multiplication(b, c), Multiplication(a, d)), denominator); + return Division( + Subtraction( + Multiplication(b, c).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Multiplication(a, d).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + denominator).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } template Complex DivisionNode::compute(const std::complex c, const std::complex d) { diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index a18ef9448..cfd69d964 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -424,12 +424,12 @@ Expression Expression::ExpressionWithoutSymbols(Expression e, Context & context) return e; } -Expression Expression::radianToDegree() { - return Multiplication(*this, Division(Rational(180), Constant(Ion::Charset::SmallPi))); +Expression Expression::radianToDegree(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + return Multiplication(*this, Division(Rational(180), Constant(Ion::Charset::SmallPi)).shallowReduce(context, angleUnit, target)).shallowReduce(context, angleUnit, target); } -Expression Expression::degreeToRadian( ) { - return Multiplication(*this, Division(Constant(Ion::Charset::SmallPi), Rational(180))); +Expression Expression::degreeToRadian(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + return Multiplication(*this, Division(Constant(Ion::Charset::SmallPi), Rational(180)).shallowReduce(context, angleUnit, target)).shallowReduce(context, angleUnit, target); } Expression Expression::reduce(Context & context, Preferences::AngleUnit angleUnit) { diff --git a/poincare/src/expression_node.cpp b/poincare/src/expression_node.cpp index 8b7a4bf00..9fbcca496 100644 --- a/poincare/src/expression_node.cpp +++ b/poincare/src/expression_node.cpp @@ -84,7 +84,12 @@ Expression ExpressionNode::complexNorm(Context & context, Preferences::AngleUnit Expression b = imaginaryPart(context, angleUnit); if (!a.isUninitialized() && !b.isUninitialized()) { // sqrt(a^2+b^2) - return SquareRoot::Builder(Addition(Power(a, Rational(2)), Power(b, Rational(2)))); + return SquareRoot::Builder( + Addition( + Power(a, Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Power(b, Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } return Expression(); } @@ -95,15 +100,27 @@ Expression ExpressionNode::complexArgument(Context & context, Preferences::Angle if (!a.isUninitialized() && !b.isUninitialized()) { if (b.type() != Type::Rational || !static_cast(b).isZero()) { // arctan(a/b) or (180/Pi)*arctan(a/b) - Expression arcTangent = ArcTangent::Builder(Division(a, b.clone())); + Expression arcTangent = ArcTangent::Builder(Division(a, b.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); if (angleUnit == Preferences::AngleUnit::Degree) { - arcTangent = arcTangent.degreeToRadian(); + arcTangent = arcTangent.degreeToRadian(context, angleUnit, ReductionTarget::BottomUpComputation); } // sign(b) * Pi/2 - arctan(a/b) - return Subtraction(Multiplication(SignFunction::Builder(b), Division(Constant(Ion::Charset::SmallPi), Rational(2))), arcTangent); + return Subtraction( + Multiplication( + SignFunction::Builder(b).shallowReduce(context, angleUnit), + Division(Constant(Ion::Charset::SmallPi), Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ), + arcTangent + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } else { // (1-sign(a))*Pi/2 - return Multiplication(Subtraction(Rational(1), SignFunction::Builder(a)), Division(Constant(Ion::Charset::SmallPi), Rational(2))); + return Multiplication( + Subtraction( + Rational(1), + SignFunction::Builder(a).shallowReduce(context, angleUnit) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Division(Constant(Ion::Charset::SmallPi), Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } } return Expression(); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 70fc45dc1..87304670c 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -43,8 +43,16 @@ Expression MultiplicationNode::complexCartesianPart(Context & context, Preferenc if (childReal.isUninitialized() || childImag.isUninitialized()) { return Expression(); } - Expression newReal = Subtraction(Multiplication(real.clone(), childReal.clone()), Multiplication(imag.clone(), childImag.clone())); - Expression newImag = Addition(Multiplication(real, childImag), Multiplication(imag, childReal)); + Expression newReal = + Subtraction( + Multiplication(real.clone(), childReal.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Multiplication(imag.clone(), childImag.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); + Expression newImag = + Addition( + Multiplication(real, childImag).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Multiplication(imag, childReal).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); real = newReal; imag = newImag; } @@ -61,7 +69,7 @@ Expression MultiplicationNode::complexNorm(Context & context, Preferences::Angle } norm.addChildAtIndexInPlace(r, norm.numberOfChildren(), norm.numberOfChildren()); } - return norm; + return norm.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } /*Expression MultiplicationNode::complexArgument(Context & context, Preferences::AngleUnit angleUnit) const { diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index 7aee33973..03af6b776 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -28,15 +28,39 @@ Expression NthRootNode::complexPolarPart(Context & context, Preferences::AngleUn if (r.isUninitialized() || th.isUninitialized() || c.isUninitialized() || d.isUninitialized()) { return Expression(); } - Expression denominator = Addition(Power(c.clone(), Rational(2)), Power(d.clone(), Rational(2))); + Expression denominator = + Addition( + Power(c.clone(), Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Power(d.clone(), Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); if (isNorm) { // R = e^((c*ln(r)+th*d)/(c^2+d^2)) // R = r^(c/(c^2+d^2))*e^(th*d/(c^2+d^2)) - return Multiplication(Power(r, Division(c, denominator.clone())), Power(Constant(Ion::Charset::Exponential), Division(Multiplication(d, th), denominator))); + return Multiplication( + Power( + r, + Division(c, denominator.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Power( + Constant(Ion::Charset::Exponential), + Division( + Multiplication(d, th).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + denominator) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); //return Power(Constant(Ion::Charset::Exponential), Division(Addition(Multiplication(c, NaperianLogarithm::Builder(r)), Multiplication(d, th)), denominator)); } else { // TH = (th*c-d*ln(r))/(c^2+d^2) - return Division(Subtraction(Multiplication(th, c), Multiplication(d, NaperianLogarithm::Builder(r))), denominator); + return Division( + Subtraction( + Multiplication(th, c).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Multiplication( + d, + NaperianLogarithm::Builder(r).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + denominator + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } } diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index b59a1fca5..a0884ef81 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -32,7 +32,7 @@ Expression OppositeNode::complexCartesianPart(Context & context, Preferences::An if (a.isUninitialized()) { return Expression(); } - return Opposite(a); + return Opposite(a).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } /* Layout */ diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 158b564b6..83797321a 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -94,11 +94,25 @@ Expression PowerNode::complexPolarPart(Context & context, Preferences::AngleUnit if (norm) { // R = e^(c*ln(r)-th*d) // R = r^c*e^(-th*d) - return Multiplication(Power(r, c), Power(Constant(Ion::Charset::Exponential), Opposite(Multiplication(th, d)))); + return Multiplication( + Power(r, c).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Power( + Constant(Ion::Charset::Exponential), + Opposite( + Multiplication(th, d).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); //return Power(Constant(Ion::Charset::Exponential), Subtraction(Multiplication(c, NaperianLogarithm::Builder(r)), Multiplication(d, th))); } else { // TH = d*ln(r)+c*th - return Addition(Multiplication(th, c), Multiplication(d, NaperianLogarithm::Builder(r))); + return Addition( + Multiplication(th, c).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Multiplication( + d, + NaperianLogarithm::Builder(r).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } } @@ -448,7 +462,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU /* We do not apply some rules to a^b if: * - the parent node is a logarithm of same base a. In this case there is a * simplication of form ln(e^(3^(1/2))->3^(1/2). - * - the reduction is being BottomUp. In this case, we do not yet have any + * - the reduction is being BottomUpComputation. In this case, we do not yet have any * information on the parent which could later be a logarithm of the same * base. */ diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index 1e64d7a11..fa51d5cb8 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -21,7 +21,7 @@ Expression SquareRootNode::complexNorm(Context & context, Preferences::AngleUnit return Expression(); } // R = sqrt(r) - return SquareRoot::Builder(r); + return SquareRoot::Builder(r).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } Expression SquareRootNode::complexArgument(Context & context, Preferences::AngleUnit angleUnit) const { @@ -30,7 +30,7 @@ Expression SquareRootNode::complexArgument(Context & context, Preferences::Angle return Expression(); } // TH = th/2 - return Division(th, Rational(2)); + return Division(th, Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } Layout SquareRootNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index 2c2006019..745608db4 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -30,7 +30,7 @@ Expression SubtractionNode::complexPart(Context & context, Preferences::AngleUni if (a0.isUninitialized() || a1.isUninitialized()) { return Expression(); } - return Subtraction(a0, a1); + return Subtraction(a0, a1).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } bool SubtractionNode::childNeedsParenthesis(const TreeNode * child) const { From a13246fca17447b4aaabbd9fb7c6703ff27d8727 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 30 Nov 2018 11:47:30 +0100 Subject: [PATCH 073/373] [poincare] simplifyForComplexFormat: simplify instead of reducing before extracting real and imaginary parts --- poincare/src/expression.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index cfd69d964..0f3960a31 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -360,19 +360,21 @@ bool isMinusOne(const Expression e) { Expression Expression::simplifyForComplexFormat(Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) { sSimplificationHasBeenInterrupted = false; - Expression e = deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); + // We simplify before extracting the real and imaginary part to develop expression of type (a+b*i)^3 for example + // We could have deepReduce the expression but we want to keep division which are easier to extract complex parts from + Expression e = simplify(context, angleUnit); if (sSimplificationHasBeenInterrupted) { return Expression(); } Expression ra = complexFormat == Preferences::ComplexFormat::Cartesian ? e.realPart(context, angleUnit) : e.complexNorm(context, angleUnit); Expression tb = complexFormat == Preferences::ComplexFormat::Cartesian ? e.imaginaryPart(context, angleUnit) : e.complexArgument(context, angleUnit); if (ra.isUninitialized() || tb.isUninitialized()) { - return e.deepBeautify(context, angleUnit); + return e; } ra = ra.simplify(context, angleUnit); tb = tb.simplify(context, angleUnit); if (ra.isUninitialized() || tb.isUninitialized()) { - return e.deepBeautify(context, angleUnit); + return e; } e = CreateComplexExpression(ra, tb, complexFormat, ra.type() == ExpressionNode::Type::Undefined || tb.type() == ExpressionNode::Type::Undefined, From ee0d158bd99dd5289df38ad09473f258e1519cb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 5 Dec 2018 15:13:54 +0100 Subject: [PATCH 074/373] [poincare] Add rules on cos(arcsin), cos(arctan), sin(arccos), sin(arctan), tan(arccos), tan(arcsin) --- poincare/include/poincare/trigonometry.h | 1 + poincare/src/tangent.cpp | 2 + poincare/src/trigonometry.cpp | 78 +++++++++++++++++++++++- poincare/test/trigo.cpp | 19 ++++++ 4 files changed, 98 insertions(+), 2 deletions(-) diff --git a/poincare/include/poincare/trigonometry.h b/poincare/include/poincare/trigonometry.h index 6092d0aa5..6af46cd2c 100644 --- a/poincare/include/poincare/trigonometry.h +++ b/poincare/include/poincare/trigonometry.h @@ -13,6 +13,7 @@ public: Sine = 1, }; static float characteristicXRange(const Expression & e, Context & context, Preferences::AngleUnit angleUnit); + static bool parentIsDirectTrigonometry(const Expression & e); static Expression shallowReduceDirectFunction(Expression & e, Context& context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); static Expression shallowReduceInverseFunction(Expression & e, Context& context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); static bool ExpressionIsEquivalentToTangent(const Expression & e); diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp index 7c3b496b1..dceb282df 100644 --- a/poincare/src/tangent.cpp +++ b/poincare/src/tangent.cpp @@ -55,6 +55,8 @@ Expression Tangent::shallowReduce(Context & context, Preferences::AngleUnit angl Sine s = Sine::Builder(newExpression.childAtIndex(0).clone()); Cosine c = Cosine::Builder(newExpression.childAtIndex(0)); Division d = Division(s, c); + s.shallowReduce(context, angleUnit, target); + c.shallowReduce(context, angleUnit, target); newExpression.replaceWithInPlace(d); return d.shallowReduce(context, angleUnit, target); } diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 0932b9dc2..8ea0c41f0 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include #include @@ -59,6 +61,60 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& co return result; } + // Step 3. Look for an expression of type "cos(arcsin(x))" or "sin(arccos(x)), return sqrt(1-x^2) + if ((e.type() == ExpressionNode::Type::Cosine && e.childAtIndex(0).type() == ExpressionNode::Type::ArcSine) || (e.type() == ExpressionNode::Type::Sine && e.childAtIndex(0).type() == ExpressionNode::Type::ArcCosine)) { + Expression sqrt = + Power( + Addition( + Rational(1), + Multiplication( + Rational(-1), + Power(e.childAtIndex(0).childAtIndex(0), Rational(2)) ) + ), + Rational(1,2) + ); + // reduce x^2 + sqrt.childAtIndex(0).childAtIndex(1).childAtIndex(1).shallowReduce(context, angleUnit, target); + // reduce -1*x^2 + sqrt.childAtIndex(0).childAtIndex(1).shallowReduce(context, angleUnit, target); + // reduce 1-1*x^2 + sqrt.childAtIndex(0).shallowReduce(context, angleUnit, target); + e.replaceWithInPlace(sqrt); + // reduce sqrt(1+(-1)*x^2) + return sqrt.shallowReduce(context, angleUnit, target); + } + + // Step 4. Look for an expression of type "cos(arctan(x))" or "sin(arctan(x))" + // cos(arctan(x)) --> 1/sqrt(1+x^2) + // sin(arctan(x)) --> x/sqrt(1+x^2) + if ((e.type() == ExpressionNode::Type::Cosine || e.type() == ExpressionNode::Type::Sine) && e.childAtIndex(0).type() == ExpressionNode::Type::ArcTangent) { + Expression x = e.childAtIndex(0).childAtIndex(0); + // Build 1/sqrt(1+x^2) + Expression res = + Power( + Addition( + Rational(1), + Power( + e.type() == ExpressionNode::Type::Cosine ? x : x.clone(), + Rational(2)) + ), + Rational(-1,2) + ); + + // reduce x^2 + res.childAtIndex(0).childAtIndex(1).shallowReduce(context, angleUnit, target); + // reduce 1+*x^2 + res.childAtIndex(0).shallowReduce(context, angleUnit, target); + if (e.type() == ExpressionNode::Type::Sine) { + res = Multiplication(x, res); + // reduce (1+x^2)^(-1/2) + res.childAtIndex(0).shallowReduce(context, angleUnit, target); + } + e.replaceWithInPlace(res); + // reduce (1+x^2)^(-1/2) or x*(1+x^2)^(-1/2) + return res.shallowReduce(context, angleUnit, target); + } + // Step 3. Look for an expression of type "cos(-a)", return "+/-cos(a)" if (e.childAtIndex(0).sign() == ExpressionNode::Sign::Negative) { e.childAtIndex(0).setSign(ExpressionNode::Sign::Positive, &context, angleUnit).shallowReduce(context, angleUnit, target); @@ -155,6 +211,17 @@ bool Trigonometry::ExpressionIsEquivalentToTangent(const Expression & e) { return false; } +bool Trigonometry::parentIsDirectTrigonometry(const Expression & e) { + Expression parent = e.parent(); + if (parent.isUninitialized()) { + return false; + } + if (parent.type() == ExpressionNode::Type::Cosine || parent.type() == ExpressionNode::Type::Sine || parent.type() == ExpressionNode::Type::Tangent) { + return true; + } + return false; +} + Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { assert(e.type() == ExpressionNode::Type::ArcCosine || e.type() == ExpressionNode::Type::ArcSine || e.type() == ExpressionNode::Type::ArcTangent); ExpressionNode::Type correspondingType = e.type() == ExpressionNode::Type::ArcCosine ? ExpressionNode::Type::Cosine : (e.type() == ExpressionNode::Type::ArcSine ? ExpressionNode::Type::Sine : ExpressionNode::Type::Tangent); @@ -189,12 +256,19 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& c return lookup; } + /* We do not apply some rules if: + * - the parent node is a cosine, a sine or a tangent. In this case there is a simplication of + * form f(g(x)) with f cos, sin or tan and g acos, asin or atan. + * - the reduction is being BottomUp. In this case, we do not yet have any + * information on the parent which could later be a cosine, a sine or a tangent. + */ + bool letArcFunctionAtRoot = target == ExpressionNode::ReductionTarget::BottomUpComputation || parentIsDirectTrigonometry(e); /* Step 4. Handle negative arguments: arccos(-x) = Pi-arcos(x), * arcsin(-x) = -arcsin(x), arctan(-x)= -arctan(x) */ - if (e.childAtIndex(0).sign() == ExpressionNode::Sign::Negative + if (!letArcFunctionAtRoot && (e.childAtIndex(0).sign() == ExpressionNode::Sign::Negative || (e.childAtIndex(0).type() == ExpressionNode::Type::Multiplication && e.childAtIndex(0).childAtIndex(0).type() == ExpressionNode::Type::Rational - && e.childAtIndex(0).childAtIndex(0).convert().isMinusOne())) + && e.childAtIndex(0).childAtIndex(0).convert().isMinusOne()))) { Expression newArgument; if (e.childAtIndex(0).sign() == ExpressionNode::Sign::Negative) { diff --git a/poincare/test/trigo.cpp b/poincare/test/trigo.cpp index e37543900..511896557 100644 --- a/poincare/test/trigo.cpp +++ b/poincare/test/trigo.cpp @@ -511,4 +511,23 @@ QUIZ_CASE(poincare_trigo_simplify) { assert_parsed_expression_simplify_to("atan(tan(1808))", "8", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("atan(tan(-180/7))", "-180/7", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("atan(R(3))", "60", Preferences::AngleUnit::Degree); + + // cos(arcsin) + assert_parsed_expression_simplify_to("cos(asin(x))", "R(1-x^2)", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(asin(-x))", "R(1-x^2)", Preferences::AngleUnit::Degree); + // cos(arctan) + assert_parsed_expression_simplify_to("cos(atan(x))", "1/R(1+x^2)", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(atan(-x))", "1/R(1+x^2)", Preferences::AngleUnit::Degree); + // sin(arccos) + assert_parsed_expression_simplify_to("sin(acos(x))", "R(1-x^2)", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(acos(-x))", "R(1-x^2)", Preferences::AngleUnit::Degree); + // sin(arctan) + assert_parsed_expression_simplify_to("sin(atan(x))", "x/R(1+x^2)", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(atan(-x))", "-x/R(1+x^2)", Preferences::AngleUnit::Degree); + // tan(arccos) + assert_parsed_expression_simplify_to("tan(acos(x))", "R(1-x^2)/x", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(acos(-x))", "-R(1-x^2)/x", Preferences::AngleUnit::Degree); + // tan(arcsin) + assert_parsed_expression_simplify_to("tan(asin(x))", "x/R(1-x^2)", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(asin(-x))", "-x/R(1-x^2)", Preferences::AngleUnit::Degree); } From d72b906919d5e87ddd16fbae2223c99a182bd358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 5 Dec 2018 15:48:40 +0100 Subject: [PATCH 075/373] [poincare] SquareRoot: implement realPart & imaginaryPart --- poincare/include/poincare/expression.h | 1 + poincare/include/poincare/square_root.h | 7 +++--- poincare/src/square_root.cpp | 31 +++++++++++++++++++++++++ poincare/test/complex.cpp | 3 ++- 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index b91f57e33..21b7ac11d 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -72,6 +72,7 @@ class Expression : public TreeHandle { friend class SignFunction; friend class Sine; friend class SquareRoot; + friend class SquareRootNode; friend class Store; friend class Subtraction; friend class Sum; diff --git a/poincare/include/poincare/square_root.h b/poincare/include/poincare/square_root.h index 047d8a6c9..a0e09931f 100644 --- a/poincare/include/poincare/square_root.h +++ b/poincare/include/poincare/square_root.h @@ -2,7 +2,6 @@ #define POINCARE_SQUARE_ROOT_H #include -#include #include #include @@ -23,11 +22,13 @@ public: #endif // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartFromPolarParts(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartFromPolarParts(this, context, angleUnit); } + Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPart(context, angleUnit, true); } + Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPart(context, angleUnit, false); } Expression complexNorm(Context & context, Preferences::AngleUnit angleUnit) const override; Expression complexArgument(Context & context, Preferences::AngleUnit angleUnit) const override; private: + // Complex + Expression complexPart(Context & context, Preferences::AngleUnit angleUnit, bool isReal) const; // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index fa51d5cb8..6b92dd875 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -1,10 +1,13 @@ #include #include +#include +#include #include #include #include #include #include +#include #include #include #include @@ -33,6 +36,34 @@ Expression SquareRootNode::complexArgument(Context & context, Preferences::Angle return Division(th, Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } +Expression SquareRootNode::complexPart(Context & context, Preferences::AngleUnit angleUnit, bool real) const { + // real: (1/2)*sqrt(2*(sqrt(x^2+y^2)+x)) + // imag: (1/2)*sqrt(2*(sqrt(x^2+y^2)-x)*sign(y)) + SquareRoot e(this); + Expression x = e.childAtIndex(0).realPart(context, angleUnit); + Expression y = e.childAtIndex(0).imaginaryPart(context, angleUnit); + Expression norm = e.childAtIndex(0).complexNorm(context, angleUnit); + if (x.isUninitialized() || y.isUninitialized()) { + return Expression(); + } + // a = sqrt(x^2+y^2)+x or + Expression a = real ? static_cast(Addition(norm, x)) : static_cast(Subtraction(norm, x)); + Multiplication res = + Multiplication( + Rational(1,2), + SquareRoot::Builder( + Multiplication( + Rational(2), + a.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ); + if (!real) { + res.addChildAtIndexInPlace(SignFunction::Builder(y).shallowReduce(context, angleUnit), res.numberOfChildren(), res.numberOfChildren()); + } + return res.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); +} + Layout SquareRootNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { return NthRootLayout(childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits)); } diff --git a/poincare/test/complex.cpp b/poincare/test/complex.cpp index aed432698..874f9978a 100644 --- a/poincare/test/complex.cpp +++ b/poincare/test/complex.cpp @@ -58,6 +58,7 @@ QUIZ_CASE(poincare_complex_parts) { assert_expression_has_complex_cartesian_parts("(3+I)/2", "3/2", "1/2"); assert_expression_has_complex_cartesian_parts("(3+I)/(2+I)", "7/5", "-1/5"); assert_expression_has_complex_cartesian_parts("(3+I)^(2+I)", "10*cos((-4*atan(3)+ln(2)+ln(5)+2*P)/2)*X^((2*atan(3)-P)/2)", "10*sin((-4*atan(3)+ln(2)+ln(5)+2*P)/2)*X^((2*atan(3)-P)/2)", Radian); + assert_expression_has_complex_cartesian_parts("R(1+6I)", "R(2+2*R(37))/2", "R(-2+2*R(37))/2"); assert_expression_has_complex_cartesian_parts("I!", "undef", "0"); assert_expression_has_complex_cartesian_parts("3!", "6", "0"); assert_expression_has_complex_cartesian_parts("x!", "x!", "0"); @@ -103,7 +104,7 @@ QUIZ_CASE(poincare_complex_parts) { assert_expression_has_complex_cartesian_parts("sign(x)", "sign(x)", "0"); assert_expression_has_complex_cartesian_parts("sin(23)", "sin(23)", "0"); assert_expression_has_complex_cartesian_parts("sin(23+I)", nullptr, nullptr); - assert_expression_has_complex_cartesian_parts("R(1-I)", "(root(2,4)*R(2+R(2)))/2", "-(root(2,4)*R(2-R(2)))/2"); + assert_expression_has_complex_cartesian_parts("R(1-I)", "R(2+2*R(2))/2", "-R(-2+2*R(2))/2"); assert_expression_has_complex_cartesian_parts("tan(23)", "tan(23)", "0"); assert_expression_has_complex_cartesian_parts("tan(23+I)", nullptr, nullptr); From 466efc1dbdbf25c76d247b1522294f3021191801 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 5 Dec 2018 17:56:45 +0100 Subject: [PATCH 076/373] [poincare] Trigonometry: speed up the look up in the cheat table --- poincare/src/trigonometry.cpp | 151 ++++++++++++++++++++++------------ 1 file changed, 99 insertions(+), 52 deletions(-) diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 8ea0c41f0..46ea20caf 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -299,58 +299,96 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& c return e; } -/* TODO: We use the cheat table to look for known simplifications (e.g. - * cos(0)=1). To look for a simplification, we parse, simplify and compare all - * known values to the input expression, which is slow. To make this faster, we - * have several options: - * - Compare double values instead of trees (a hash table) - * - Store parsed Trees and compare buffers: - * - By parsing all expressions at initialization and storing them (takes a - * lot of RAM) - * - By having constexpr constructor of TreeNodes (not possible because - * TreeNode has a virtual destructor) and storing Trees in Flash memory - * - Use a prefix Tree to search for a match (also called Trie) */ +/* We use the cheat table to look for known simplifications (e.g. + * cos(0)=1, cos(Pi/2)=1...). For each entry of the table, we store its + * expression and its float approximation in order to quickly scan the table + * looking for our input approximation. If one entry matches, we then check that + * the actual expression of our input is equivalent to the table expression. + */ static_assert('\x8A' == Ion::Charset::SmallPi, "Unicode error"); -constexpr const char * cheatTable[Trigonometry::k_numberOfEntries][5] = + +struct Pair { + constexpr Pair(const char * e, float v = NAN) : expression(e), value(v) {} + const char * expression; + float value; +}; +constexpr Pair cheatTable[Trigonometry::k_numberOfEntries][5] = // Angle in Radian | Angle in Degree | Cosine | Sine | Tangent -{{"-90", "\x8A*(-2)^(-1)", "", "-1", "undef"}, - {"-75", "\x8A*(-5)*12^(-1)", "", "(-1)*6^(1/2)*4^(-1)-2^(1/2)*4^(-1)", "-(3^(1/2)+2)"}, - {"-72", "\x8A*2*(-5)^(-1)", "", "-(5/8+5^(1/2)/8)^(1/2)", "-(5+2*5^(1/2))^(1/2)"}, - {"-135/2", "\x8A*(-3)*8^(-1)", "", "-(2+2^(1/2))^(1/2)*2^(-1)", "-1-2^(1/2)"}, - {"-60", "\x8A*(-3)^(-1)", "", "-3^(1/2)*2^(-1)", "-3^(1/2)"}, - {"-54", "\x8A*(-3)*10^(-1)", "", "4^(-1)*(-1-5^(1/2))", "-(1+2*5^(-1/2))^(1/2)"}, - {"-45", "\x8A*(-4)^(-1)", "", "(-1)*(2^(-1/2))", "-1"}, - {"-36", "\x8A*(-5)^(-1)", "", "-(5/8-5^(1/2)/8)^(1/2)", "-(5-2*5^(1/2))^(1/2)"}, - {"-30", "\x8A*(-6)^(-1)", "", "-0.5", "-3^(-1/2)"}, - {"-45/2", "\x8A*(-8)^(-1)", "", "(2-2^(1/2))^(1/2)*(-2)^(-1)", "1-2^(1/2)"}, - {"-18", "\x8A*(-10)^(-1)", "", "4^(-1)*(1-5^(1/2))", "-(1-2*5^(-1/2))^(1/2)"}, - {"-15", "\x8A*(-12)^(-1)", "", "-6^(1/2)*4^(-1)+2^(1/2)*4^(-1)", "3^(1/2)-2"}, - {"0", "0", "1", "0", "0"}, - {"15", "\x8A*12^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*4^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*(-4)^(-1)", "-(3^(1/2)-2)"}, - {"18", "\x8A*10^(-1)", "(5/8+5^(1/2)/8)^(1/2)", "4^(-1)*(5^(1/2)-1)", "(1-2*5^(-1/2))^(1/2)"}, - {"45/2", "\x8A*8^(-1)", "(2+2^(1/2))^(1/2)*2^(-1)", "(2-2^(1/2))^(1/2)*2^(-1)", "2^(1/2)-1"}, - {"30", "\x8A*6^(-1)", "3^(1/2)*2^(-1)", "0.5", "3^(-1/2)"}, - {"36", "\x8A*5^(-1)", "(5^(1/2)+1)*4^(-1)", "(5/8-5^(1/2)/8)^(1/2)", "(5-2*5^(1/2))^(1/2)"}, - {"45", "\x8A*4^(-1)", "2^(-1/2)", "2^(-1/2)", "1"}, - {"54", "\x8A*3*10^(-1)", "(5/8-5^(1/2)/8)^(1/2)", "4^(-1)*(5^(1/2)+1)", "(1+2*5^(-1/2))^(1/2)"}, - {"60", "\x8A*3^(-1)", "0.5", "3^(1/2)*2^(-1)", "3^(1/2)"}, - {"135/2", "\x8A*3*8^(-1)", "(2-2^(1/2))^(1/2)*2^(-1)", "(2+2^(1/2))^(1/2)*2^(-1)", "1+2^(1/2)"}, - {"72", "\x8A*2*5^(-1)", "(5^(1/2)-1)*4^(-1)", "(5/8+5^(1/2)/8)^(1/2)", "(5+2*5^(1/2))^(1/2)"}, - {"75", "\x8A*5*12^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*(-4)^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*4^(-1)", "3^(1/2)+2"}, - {"90", "\x8A*2^(-1)", "0", "1", "undef"}, - {"105", "\x8A*7*12^(-1)", "-6^(1/2)*4^(-1)+2^(1/2)*4^(-1)", "", ""}, - {"108", "\x8A*3*5^(-1)", "(1-5^(1/2))*4^(-1)", "", ""}, - {"225/2", "\x8A*5*8^(-1)", "(2-2^(1/2))^(1/2)*(-2)^(-1)", "", ""}, - {"120", "\x8A*2*3^(-1)", "-0.5", "", ""}, - {"126", "\x8A*7*10^(-1)", "-(5*8^(-1)-5^(1/2)*8^(-1))^(1/2)", "", ""}, - {"135", "\x8A*3*4^(-1)", "(-1)*(2^(-1/2))", "", ""}, - {"144", "\x8A*4*5^(-1)", "(-5^(1/2)-1)*4^(-1)", "", ""}, - {"150", "\x8A*5*6^(-1)", "-3^(1/2)*2^(-1)", "", ""}, - {"315/2", "\x8A*7*8^(-1)", "-(2+2^(1/2))^(1/2)*2^(-1)", "", ""}, - {"162", "\x8A*9*10^(-1)", "-(5*8^(-1)+5^(1/2)*8^(-1))^(1/2)", "", ""}, - {"165", "\x8A*11*12^(-1)", "(-1)*6^(1/2)*4^(-1)-2^(1/2)*4^(-1)", "", ""}, - {"180", "\x8A", "-1", "0", "0"}}; +{{Pair("-90", -90.0f), Pair("\x8A*(-2)^(-1)", -1.5707963267948966f), "", + Pair("-1",-1.0f), "undef"}, + {Pair("-75",-75.0), Pair("\x8A*(-5)*12^(-1)",-1.3089969389957472f), "", + Pair("(-1)*6^(1/2)*4^(-1)-2^(1/2)*4^(-1)",-0.9659258262890683f), Pair("-(3^(1/2)+2)",-3.7320508075688776f)}, + {Pair("-72",-72.0), Pair("\x8A*2*(-5)^(-1)",-1.2566370614359172f), "", + Pair("-(5/8+5^(1/2)/8)^(1/2)",-0.9510565162951535f), Pair("-(5+2*5^(1/2))^(1/2)",-3.077683537175253f)}, + {Pair("-135/2",67.5f), Pair("\x8A*(-3)*8^(-1)",-1.1780972450961724f), "", + Pair("-(2+2^(1/2))^(1/2)*2^(-1)",-0.9238795325112867f), Pair("-1-2^(1/2)",-2.4142135623730945f)}, + {Pair("-60",-60.0f), Pair("\x8A*(-3)^(-1)",-1.0471975511965976f), "", + Pair("-3^(1/2)*2^(-1)",-0.8660254037844386f), Pair("-3^(1/2)",-1.7320508075688767f)}, + {Pair("-54",-54.0f), Pair("\x8A*(-3)*10^(-1)",-0.9424777960769379), "", + Pair("4^(-1)*(-1-5^(1/2))",-0.8090169943749473f), Pair("-(1+2*5^(-1/2))^(1/2)",-1.3763819204711731f)}, + {Pair("-45",-45.0f), Pair("\x8A*(-4)^(-1)",-0.7853981633974483f), "", + Pair("(-1)*(2^(-1/2))",-0.7071067811865475f), Pair("-1",-1.0f)}, + {Pair("-36",-36.0f), Pair("\x8A*(-5)^(-1)",-0.6283185307179586f), "", + Pair("-(5/8-5^(1/2)/8)^(1/2)",-0.5877852522924731f), Pair("-(5-2*5^(1/2))^(1/2)",-0.7265425280053609f)}, + {Pair("-30",-30.0f), Pair("\x8A*(-6)^(-1)",-0.5235987755982988f), "", + Pair("-0.5",-0.5f), Pair("-3^(-1/2)",-0.5773502691896256f)}, + {Pair("-45/2",-22.5f), Pair("\x8A*(-8)^(-1)",-0.39269908169872414f), "", + Pair("(2-2^(1/2))^(1/2)*(-2)^(-1)",-0.3826834323650898f), Pair("1-2^(1/2)",-0.4142135623730951f)}, + {Pair("-18",-18.0f), Pair("\x8A*(-10)^(-1)",-0.3141592653589793f), "", + Pair("4^(-1)*(1-5^(1/2))",-0.3090169943749474f), Pair("-(1-2*5^(-1/2))^(1/2)",-0.3249196962329063f)}, + {Pair("-15",-15.0f), Pair("\x8A*(-12)^(-1)",-0.2617993877991494f), "", + Pair("-6^(1/2)*4^(-1)+2^(1/2)*4^(-1)",-0.25881904510252074f), Pair("3^(1/2)-2",-0.2679491924311227f)}, + {Pair("0",0.0f), Pair("0",0.0f), Pair("1",1.0f), + Pair("0",0.0f), Pair("0",0.0f)}, + {Pair("15",15.0f), Pair("\x8A*12^(-1)",0.2617993877991494f), Pair("6^(1/2)*4^(-1)+2^(1/2)*4^(-1)",0.9659258262890683f), + Pair("6^(1/2)*4^(-1)+2^(1/2)*(-4)^(-1)",0.25881904510252074f), Pair("-(3^(1/2)-2)",0.2679491924311227f)}, + {Pair("18",18.0f), Pair("\x8A*10^(-1)",0.3141592653589793f), Pair("(5/8+5^(1/2)/8)^(1/2)",0.9510565162951535f), + Pair("4^(-1)*(5^(1/2)-1)",0.3090169943749474f), Pair("(1-2*5^(-1/2))^(1/2)",0.3249196962329063f)}, + {Pair("45/2",22.5f), Pair("\x8A*8^(-1)",0.39269908169872414f), Pair("(2+2^(1/2))^(1/2)*2^(-1)",0.9238795325112867f), + Pair("(2-2^(1/2))^(1/2)*2^(-1)",0.3826834323650898f), Pair("2^(1/2)-1",0.4142135623730951f)}, + {Pair("30",30.0f), Pair("\x8A*6^(-1)",0.5235987755982988f), Pair("3^(1/2)*2^(-1)",0.8660254037844387f), + Pair("0.5",0.5f), Pair("3^(-1/2)",0.5773502691896256f)}, + {Pair("36",36.0f), Pair("\x8A*5^(-1)",0.6283185307179586f), Pair("(5^(1/2)+1)*4^(-1)",0.8090169943749475f), + Pair("(5/8-5^(1/2)/8)^(1/2)",0.5877852522924731f), Pair("(5-2*5^(1/2))^(1/2)",0.7265425280053609f)}, + {Pair("45",45.0f), Pair("\x8A*4^(-1)",0.7853981633974483f), Pair("2^(-1/2)",0.7071067811865476f), + Pair("2^(-1/2)",0.7071067811865475f), Pair("1",1.0f)}, + {Pair("54",54.0f), Pair("\x8A*3*10^(-1)",0.9424777960769379f), Pair("(5/8-5^(1/2)/8)^(1/2)",0.5877852522924732f), + Pair("4^(-1)*(5^(1/2)+1)",0.8090169943749473f), Pair("(1+2*5^(-1/2))^(1/2)",1.3763819204711731f)}, + {Pair("60",60.0f), Pair("\x8A*3^(-1)",1.0471975511965976f), Pair("0.5",0.5f), + Pair("3^(1/2)*2^(-1)",0.8660254037844386f), Pair("3^(1/2)",1.7320508075688767f)}, + {Pair("135/2",67.5f), Pair("\x8A*3*8^(-1)",1.1780972450961724f), Pair("(2-2^(1/2))^(1/2)*2^(-1)",0.38268343236508984f), + Pair("(2+2^(1/2))^(1/2)*2^(-1)",0.9238795325112867f), Pair("1+2^(1/2)",2.4142135623730945f)}, + {Pair("72",72.0f), Pair("\x8A*2*5^(-1)",1.2566370614359172f), Pair("(5^(1/2)-1)*4^(-1)",0.30901699437494745f), + Pair("(5/8+5^(1/2)/8)^(1/2)",0.9510565162951535f), Pair("(5+2*5^(1/2))^(1/2)",3.077683537175253f)}, + {Pair("75",75.0f), Pair("\x8A*5*12^(-1)",1.3089969389957472f), Pair("6^(1/2)*4^(-1)+2^(1/2)*(-4)^(-1)",0.25881904510252074f), + Pair("6^(1/2)*4^(-1)+2^(1/2)*4^(-1)",0.9659258262890683f), Pair("3^(1/2)+2",3.7320508075688776f)}, + {Pair("90",90.0f), Pair("\x8A*2^(-1)",1.5707963267948966f), Pair("0",0.0f), + Pair("1",1.0f), "undef"}, + {Pair("105",105.0f), Pair("\x8A*7*12^(-1)",1.832595714594046f), Pair("-6^(1/2)*4^(-1)+2^(1/2)*4^(-1)",-0.25881904510252063f), + "", ""}, + {Pair("108",108.0f), Pair("\x8A*3*5^(-1)",1.8849555921538759f), Pair("(1-5^(1/2))*4^(-1)",-0.30901699437494734f), + "", ""}, + {Pair("225/2",112.5f), Pair("\x8A*5*8^(-1)",1.9634954084936207f), Pair("(2-2^(1/2))^(1/2)*(-2)^(-1)",-0.3826834323650897f), + "", ""}, + {Pair("120",120.0f), Pair("\x8A*2*3^(-1)",2.0943951023931953f), Pair("-0.5",-0.5f), + "", ""}, + {Pair("126",126.0f), Pair("\x8A*7*10^(-1)",2.199114857512855f), Pair("-(5*8^(-1)-5^(1/2)*8^(-1))^(1/2)",-0.587785252292473f), + "", ""}, + {Pair("135",135.0f), Pair("\x8A*3*4^(-1)",2.356194490192345f), Pair("(-1)*(2^(-1/2))",-0.7071067811865475f), + "", ""}, + {Pair("144",144.0f), Pair("\x8A*4*5^(-1)",2.5132741228718345f), Pair("(-5^(1/2)-1)*4^(-1)",-0.8090169943749473f), + "", ""}, + {Pair("150",150.0f), Pair("\x8A*5*6^(-1)",2.6179938779914944f), Pair("-3^(1/2)*2^(-1)",-0.8660254037844387f), + "", ""}, + {Pair("315/2",157.5f), Pair("\x8A*7*8^(-1)",2.748893571891069f), Pair("-(2+2^(1/2))^(1/2)*2^(-1)",-0.9238795325112867f), + "", ""}, + {Pair("162",162.0f), Pair("\x8A*9*10^(-1)",2.827433388230814f), Pair("-(5*8^(-1)+5^(1/2)*8^(-1))^(1/2)",-0.9510565162951535f), + "", ""}, + {Pair("165",165.0f), Pair("\x8A*11*12^(-1)",2.8797932657906435f), Pair("(-1)*6^(1/2)*4^(-1)-2^(1/2)*4^(-1)",-0.9659258262890682f), + "", ""}, + {Pair("180",180.0f), Pair("\x8A",3.141592653589793f), Pair("-1",-1.0f), + Pair("0",0.0f), Pair("0",0.0f)}}; Expression Trigonometry::table(const Expression e, ExpressionNode::Type type, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { assert(type == ExpressionNode::Type::Sine @@ -375,20 +413,29 @@ Expression Trigonometry::table(const Expression e, ExpressionNode::Type type, Co if (inputIndex >1 && e.type() != ExpressionNode::Type::Rational && e.type() != ExpressionNode::Type::Multiplication && e.type() != ExpressionNode::Type::Power && e.type() != ExpressionNode::Type::Addition) { return Expression(); } + // We approximate the given expression to quickly compare it to the cheat table entries. + float eValue = e.approximateToScalar(context, angleUnit); + if (std::isnan(eValue) || std::isinf(eValue)) { + return Expression(); + } for (int i = 0; i < k_numberOfEntries; i++) { - Expression input = Expression::Parse(cheatTable[i][inputIndex]); - if (input.isUninitialized()) { + float inputValue = cheatTable[i][inputIndex].value; + if (std::isnan(inputValue) || std::fabs(inputValue-eValue) > Expression::epsilon()) { continue; } + // Our given expression approximation matches a table entry, we check that both expressions are identical + Expression input = Expression::Parse(cheatTable[i][inputIndex].expression); + assert(!input.isUninitialized()); input = input.deepReduce(context, angleUnit, target); bool rightInput = input.isIdenticalTo(e); if (rightInput) { - Expression output = Expression::Parse(cheatTable[i][outputIndex]); + Expression output = Expression::Parse(cheatTable[i][outputIndex].expression); if (output.isUninitialized()) { return Expression(); } return output.deepReduce(context, angleUnit, target); } + break; } return Expression(); } From 68367343eda3b63d55a7d270fbf1b0a7f5541895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 6 Dec 2018 16:22:04 +0100 Subject: [PATCH 077/373] [poincare] Add tests on complex extractors --- poincare/test/complex.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/poincare/test/complex.cpp b/poincare/test/complex.cpp index 874f9978a..3be1ca01c 100644 --- a/poincare/test/complex.cpp +++ b/poincare/test/complex.cpp @@ -59,6 +59,8 @@ QUIZ_CASE(poincare_complex_parts) { assert_expression_has_complex_cartesian_parts("(3+I)/(2+I)", "7/5", "-1/5"); assert_expression_has_complex_cartesian_parts("(3+I)^(2+I)", "10*cos((-4*atan(3)+ln(2)+ln(5)+2*P)/2)*X^((2*atan(3)-P)/2)", "10*sin((-4*atan(3)+ln(2)+ln(5)+2*P)/2)*X^((2*atan(3)-P)/2)", Radian); assert_expression_has_complex_cartesian_parts("R(1+6I)", "R(2+2*R(37))/2", "R(-2+2*R(37))/2"); + assert_expression_has_complex_cartesian_parts("(1+I)^2", "0", "2"); + assert_expression_has_complex_cartesian_parts("2*I", "0", "2"); assert_expression_has_complex_cartesian_parts("I!", "undef", "0"); assert_expression_has_complex_cartesian_parts("3!", "6", "0"); assert_expression_has_complex_cartesian_parts("x!", "x!", "0"); @@ -138,6 +140,8 @@ QUIZ_CASE(poincare_complex_parts) { assert_expression_has_complex_polar_parts("(3+I)/2", "R(10)/2", "(-2*atan(3)+P)/2", Radian); assert_expression_has_complex_polar_parts("(3+I)/(2+I)", "R(2)", "(2*atan(7)-P)/2", Radian); assert_expression_has_complex_polar_parts("(3+I)^(2+I)", "10*X^((2*atan(3)-P)/2)", "(-4*atan(3)+ln(2)+ln(5)+2*P)/2", Radian); + assert_expression_has_complex_polar_parts("(1+I)^2", "2", "P/2"); + assert_expression_has_complex_polar_parts("2*I", "2", "P/2"); assert_expression_has_complex_polar_parts("3!", "6", "0"); assert_expression_has_complex_polar_parts("x!", "x!", "0"); assert_expression_has_complex_polar_parts("X", "X", "0"); From f8251a74bcecbdf096b008610ef52f5603cb7db2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 6 Dec 2018 17:20:01 +0100 Subject: [PATCH 078/373] [poincare] SquareRoot: use realPart and imaginaryPart to compute the complexArgument --- poincare/include/poincare/square_root.h | 2 +- poincare/src/square_root.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/square_root.h b/poincare/include/poincare/square_root.h index a0e09931f..a31f1baeb 100644 --- a/poincare/include/poincare/square_root.h +++ b/poincare/include/poincare/square_root.h @@ -25,7 +25,7 @@ public: Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPart(context, angleUnit, true); } Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPart(context, angleUnit, false); } Expression complexNorm(Context & context, Preferences::AngleUnit angleUnit) const override; - Expression complexArgument(Context & context, Preferences::AngleUnit angleUnit) const override; + //Expression complexArgument(Context & context, Preferences::AngleUnit angleUnit) const override; private: // Complex Expression complexPart(Context & context, Preferences::AngleUnit angleUnit, bool isReal) const; diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index 6b92dd875..5d763c27b 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -27,14 +27,14 @@ Expression SquareRootNode::complexNorm(Context & context, Preferences::AngleUnit return SquareRoot::Builder(r).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } -Expression SquareRootNode::complexArgument(Context & context, Preferences::AngleUnit angleUnit) const { +/*Expression SquareRootNode::complexArgument(Context & context, Preferences::AngleUnit angleUnit) const { Expression th = childAtIndex(0)->complexArgument(context, angleUnit); if (th.isUninitialized()) { return Expression(); } // TH = th/2 return Division(th, Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); -} +}*/ Expression SquareRootNode::complexPart(Context & context, Preferences::AngleUnit angleUnit, bool real) const { // real: (1/2)*sqrt(2*(sqrt(x^2+y^2)+x)) From 8f634160979ce877725f5d9f798d527f4a9699af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 7 Dec 2018 10:15:02 +0100 Subject: [PATCH 079/373] [calculation] Fix Calculation operator == --- apps/calculation/calculation.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/calculation/calculation.cpp b/apps/calculation/calculation.cpp index 14e99efb3..da4f1319a 100644 --- a/apps/calculation/calculation.cpp +++ b/apps/calculation/calculation.cpp @@ -22,7 +22,14 @@ Calculation::Calculation() : bool Calculation::operator==(const Calculation& c) { return strcmp(m_inputText, c.m_inputText) == 0 - && strcmp(m_approximateOutputText, c.m_approximateOutputText) == 0; + && strcmp(m_approximateOutputText, c.m_approximateOutputText) == 0 + /* Some calculations can make appear trigonometric functions in their + * exact output. Their argument will be different with the angle unit + * preferences but both input and approximate output will be the same. + * For example, i^(sqrt(3)) = cos(sqrt(3)*pi/2)+i*sin(sqrt(3)*pi/2) if + * angle unit is radian and i^(sqrt(3)) = cos(sqrt(3)*90+i*sin(sqrt(3)*90) + * in degree. */ + && strcmp(m_exactOutputText, c.m_exactOutputText) == 0; } void Calculation::reset() { From be741415b01afa179165260214e81112a869d619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 10 Dec 2018 11:29:46 +0100 Subject: [PATCH 080/373] [poincare] Fix comment --- poincare/src/expression_node.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/expression_node.cpp b/poincare/src/expression_node.cpp index 9fbcca496..cc5c0432f 100644 --- a/poincare/src/expression_node.cpp +++ b/poincare/src/expression_node.cpp @@ -99,7 +99,7 @@ Expression ExpressionNode::complexArgument(Context & context, Preferences::Angle Expression b = imaginaryPart(context, angleUnit); if (!a.isUninitialized() && !b.isUninitialized()) { if (b.type() != Type::Rational || !static_cast(b).isZero()) { - // arctan(a/b) or (180/Pi)*arctan(a/b) + // arctan(a/b) or (Pi/180)*arctan(a/b) Expression arcTangent = ArcTangent::Builder(Division(a, b.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); if (angleUnit == Preferences::AngleUnit::Degree) { arcTangent = arcTangent.degreeToRadian(context, angleUnit, ReductionTarget::BottomUpComputation); From cc83fec322f248535e7660e384481c0aaa1ea5cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 10 Dec 2018 11:29:56 +0100 Subject: [PATCH 081/373] [poincare} Power::complexPolarPart: avoid an extra shallowReduce by inserting *(-1) instead of an OppositeNode --- poincare/src/power.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 83797321a..5b6bf0420 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -98,12 +98,9 @@ Expression PowerNode::complexPolarPart(Context & context, Preferences::AngleUnit Power(r, c).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), Power( Constant(Ion::Charset::Exponential), - Opposite( - Multiplication(th, d).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + Multiplication(Rational(-1), th, d).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); - //return Power(Constant(Ion::Charset::Exponential), Subtraction(Multiplication(c, NaperianLogarithm::Builder(r)), Multiplication(d, th))); } else { // TH = d*ln(r)+c*th return Addition( From 9e2b709fcba1f0007c9ad3877171d6066219ab69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 12 Dec 2018 15:16:31 +0100 Subject: [PATCH 082/373] [poincare] Change sign() signature to sign(context, angleUnit) --- poincare/include/poincare/absolute_value.h | 2 +- poincare/include/poincare/constant.h | 2 +- poincare/include/poincare/decimal.h | 2 +- poincare/include/poincare/expression.h | 4 +- poincare/include/poincare/expression_node.h | 2 +- poincare/include/poincare/factorial.h | 2 +- poincare/include/poincare/float.h | 2 +- poincare/include/poincare/function.h | 1 - poincare/include/poincare/infinity.h | 2 +- poincare/include/poincare/multiplication.h | 2 +- poincare/include/poincare/number.h | 5 ++- poincare/include/poincare/opposite.h | 2 +- poincare/include/poincare/power.h | 2 +- poincare/include/poincare/random.h | 2 +- poincare/include/poincare/rational.h | 2 +- poincare/include/poincare/sign_function.h | 2 +- poincare/include/poincare/symbol_abstract.h | 4 ++ poincare/include/poincare/undefined.h | 1 + poincare/src/absolute_value.cpp | 4 +- poincare/src/addition.cpp | 4 +- poincare/src/constant.cpp | 2 +- poincare/src/decimal.cpp | 2 +- poincare/src/division.cpp | 2 +- poincare/src/expression.cpp | 2 +- poincare/src/factorial.cpp | 2 +- poincare/src/float.cpp | 4 +- poincare/src/logarithm.cpp | 6 +-- poincare/src/multiplication.cpp | 19 +++++---- poincare/src/number.cpp | 2 +- poincare/src/opposite.cpp | 10 ++--- poincare/src/power.cpp | 44 +++++++++++---------- poincare/src/rational.cpp | 6 +-- poincare/src/sign_function.cpp | 8 ++-- poincare/src/subtraction.cpp | 2 +- poincare/src/symbol.cpp | 2 +- poincare/src/symbol_abstract.cpp | 17 ++++++++ poincare/src/trigonometry.cpp | 6 +-- poincare/src/undefined.cpp | 2 +- poincare/test/complex.cpp | 6 +-- poincare/test/properties.cpp | 3 +- 40 files changed, 114 insertions(+), 82 deletions(-) diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 14fd29977..2aad1feed 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -21,7 +21,7 @@ public: // Properties Type type() const override { return Type::AbsoluteValue; } - Sign sign() const override { return Sign::Positive; } + Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override { return Sign::Positive; } Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; // Complex diff --git a/poincare/include/poincare/constant.h b/poincare/include/poincare/constant.h index 5b3bfdb84..bd104b05b 100644 --- a/poincare/include/poincare/constant.h +++ b/poincare/include/poincare/constant.h @@ -23,7 +23,7 @@ public: // Expression Properties Type type() const override { return Type::Constant; } - Sign sign() const override; + Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override; /* Layout */ Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index 4c5b2bace..e3da48d30 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -48,7 +48,7 @@ public: // Properties Type type() const override { return Type::Decimal; } - Sign sign() const override { return m_negative ? Sign::Negative : Sign::Positive; } + Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override { return m_negative ? Sign::Negative : Sign::Positive; } Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; // Approximation diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 21b7ac11d..38f6c47d5 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -65,6 +65,7 @@ class Expression : public TreeHandle { friend class Parenthesis; friend class PermuteCoefficient; friend class Power; + friend class PowerNode; friend class PredictionInterval; friend class Product; friend class RealPart; @@ -77,6 +78,7 @@ class Expression : public TreeHandle { friend class Subtraction; friend class Sum; friend class Symbol; + friend class SymbolAbstractNode; friend class Tangent; friend class Trigonometry; @@ -116,7 +118,7 @@ public: /* Properties */ ExpressionNode::Type type() const { return node()->type(); } - ExpressionNode::Sign sign() const { return node()->sign(); } + ExpressionNode::Sign sign(Context * context, Preferences::AngleUnit angleUnit) const { return node()->sign(context, angleUnit); } bool isUndefined() const { return node()->type() == ExpressionNode::Type::Undefined; } bool isNumber() const { return node()->isNumber(); } bool isRationalZero() const; diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index 248d2211e..d3595c54c 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -102,7 +102,7 @@ public: Unknown = 0, Positive = 1 }; - virtual Sign sign() const { return Sign::Unknown; } + virtual Sign sign(Context * context, Preferences::AngleUnit angleUnit) const { return Sign::Unknown; } virtual bool isNumber() const { return false; } /*!*/ virtual Expression replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression); /*!*/ virtual Expression replaceUnknown(const Symbol & symbol); diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index 83a6a5b3c..62440a1b5 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -21,7 +21,7 @@ public: // Properties Type type() const override { return Type::Factorial; } - Sign sign() const override { return Sign::Positive; } + Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override { return Sign::Positive; } Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; // Complex diff --git a/poincare/include/poincare/float.h b/poincare/include/poincare/float.h index b999e61d2..66fc7a68c 100644 --- a/poincare/include/poincare/float.h +++ b/poincare/include/poincare/float.h @@ -39,7 +39,7 @@ public: // Properties Type type() const override { return Type::Float; } - Sign sign() const override { return m_value < 0 ? Sign::Negative : Sign::Positive; } + Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override { return m_value < 0 ? Sign::Negative : Sign::Positive; } Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override; diff --git a/poincare/include/poincare/function.h b/poincare/include/poincare/function.h index e032befc1..c942bf062 100644 --- a/poincare/include/poincare/function.h +++ b/poincare/include/poincare/function.h @@ -21,7 +21,6 @@ public: // Properties Type type() const override { return Type::Function; } - Sign sign() const override { return Sign::Unknown; } Expression replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression) override; int polynomialDegree(Context & context, const char * symbolName) const override; int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const override; diff --git a/poincare/include/poincare/infinity.h b/poincare/include/poincare/infinity.h index fb24216c2..6887fa08f 100644 --- a/poincare/include/poincare/infinity.h +++ b/poincare/include/poincare/infinity.h @@ -24,7 +24,7 @@ public: // Properties Type type() const override { return Type::Infinity; } - Sign sign() const override { return m_negative ? Sign::Negative : Sign::Positive; } + Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override { return m_negative ? Sign::Negative : Sign::Positive; } // Approximation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index e56aa87d8..5ba4c954b 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -21,7 +21,7 @@ public: // Properties Type type() const override { return Type::Multiplication; } - Sign sign() const override; + Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override; int polynomialDegree(Context & context, const char * symbolName) const override; int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const override; diff --git a/poincare/include/poincare/number.h b/poincare/include/poincare/number.h index 1d6e542fd..7e1041bad 100644 --- a/poincare/include/poincare/number.h +++ b/poincare/include/poincare/number.h @@ -46,8 +46,9 @@ public: static Number Power(const Number & i, const Number & j); static int NaturalOrder(const Number & i, const Number & j); - /* Number::setSign does not need a context or an angle unit (a number can be - * Infinity, Undefined, Float, Decimal, Rational). */ + /* Number::sign() or Number::setSign does not need a context or an angle unit + * (a number can be Infinity, Undefined, Float, Decimal, Rational). */ + ExpressionNode::Sign sign() { return Expression::sign(nullptr, Preferences::AngleUnit::Degree); } Number setSign(ExpressionNode::Sign s) { return Expression::setSign(s, nullptr, Preferences::AngleUnit::Degree).convert(); } protected: Number() : Expression() {} diff --git a/poincare/include/poincare/opposite.h b/poincare/include/poincare/opposite.h index 96f3300be..174a173dd 100644 --- a/poincare/include/poincare/opposite.h +++ b/poincare/include/poincare/opposite.h @@ -25,7 +25,7 @@ public: // Properties Type type() const override { return Type::Opposite; } int polynomialDegree(Context & context, const char * symbolName) const override; - Sign sign() const override; + Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override; // Complex Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexCartesianPart(context, angleUnit, true); } diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index cce1d3050..a7fcf22eb 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -29,7 +29,7 @@ public: // Properties Type type() const override { return Type::Power; } - Sign sign() const override; + Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override; Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; int polynomialDegree(Context & context, const char * symbolName) const override; diff --git a/poincare/include/poincare/random.h b/poincare/include/poincare/random.h index f84453a84..9b218d408 100644 --- a/poincare/include/poincare/random.h +++ b/poincare/include/poincare/random.h @@ -25,7 +25,7 @@ public: // Properties Type type() const override { return Type::Random; } - Sign sign() const override { return Sign::Positive; } + Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override { return Sign::Positive; } Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; private: // Layout diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index 46aab0b6e..9daab1b3b 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -36,7 +36,7 @@ public: // Expression subclassing Type type() const override { return Type::Rational; } - Sign sign() const override { return m_negative ? Sign::Negative : Sign::Positive; } + Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override { return m_negative ? Sign::Negative : Sign::Positive; } // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/sign_function.h b/poincare/include/poincare/sign_function.h index 85a76663c..dbe336d2a 100644 --- a/poincare/include/poincare/sign_function.h +++ b/poincare/include/poincare/sign_function.h @@ -21,7 +21,7 @@ public: // Properties Type type() const override { return Type::SignFunction; } - Sign sign() const override; + Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override; Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; // Complex diff --git a/poincare/include/poincare/symbol_abstract.h b/poincare/include/poincare/symbol_abstract.h index 04580b1c0..b6656b9f0 100644 --- a/poincare/include/poincare/symbol_abstract.h +++ b/poincare/include/poincare/symbol_abstract.h @@ -34,6 +34,10 @@ public: // ExpressionNode int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override; + // Property + Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override; + Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit) override; + // TreeNode #if POINCARE_TREE_LOG virtual void logNodeName(std::ostream & stream) const override { diff --git a/poincare/include/poincare/undefined.h b/poincare/include/poincare/undefined.h index 915d9e594..c434f8630 100644 --- a/poincare/include/poincare/undefined.h +++ b/poincare/include/poincare/undefined.h @@ -43,6 +43,7 @@ private: class Undefined final : public Number { public: Undefined() : Number(TreePool::sharedPool()->createTreeNode()) {} + Undefined(const UndefinedNode * n) : Number(n) {} static const char * Name() { return "undef"; } diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 1cc856463..0270ba146 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -46,11 +46,11 @@ Expression AbsoluteValue::shallowReduce(Context & context, Preferences::AngleUni } #endif #endif - if (c.sign() == ExpressionNode::Sign::Positive) { + if (c.sign(&context, angleUnit) == ExpressionNode::Sign::Positive) { replaceWithInPlace(c); return c; } - if (c.sign() == ExpressionNode::Sign::Negative) { + if (c.sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { Expression result = c.setSign(ExpressionNode::Sign::Positive, &context, angleUnit); replaceWithInPlace(result); return result; diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 7cbc77fee..0d2a7a023 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -46,7 +46,7 @@ Expression AdditionNode::complexPart(Context & context, Preferences::AngleUnit a // Layout bool AdditionNode::childNeedsParenthesis(const TreeNode * child) const { if (((static_cast(child)->isNumber() - && static_cast(child)->sign() == Sign::Negative) + && Number(static_cast(child)).sign() == Sign::Negative) || static_cast(child)->type() == Type::Opposite) && child != childAtIndex(0)) { @@ -118,7 +118,7 @@ Expression Addition::shallowBeautify(Context & context, Preferences::AngleUnit a Expression childI = childAtIndex(i); if (childI.type() != ExpressionNode::Type::Multiplication || !childI.childAtIndex(0).isNumber() - || childI.childAtIndex(0).sign() != ExpressionNode::Sign::Negative) + || childI.childAtIndex(0).sign(&context, angleUnit) != ExpressionNode::Sign::Negative) { // Ignore terms which are not like "(-r)*a" continue; diff --git a/poincare/src/constant.cpp b/poincare/src/constant.cpp index f2b8f15ef..15fef166d 100644 --- a/poincare/src/constant.cpp +++ b/poincare/src/constant.cpp @@ -9,7 +9,7 @@ namespace Poincare { -ExpressionNode::Sign ConstantNode::sign() const { +ExpressionNode::Sign ConstantNode::sign(Context * context, Preferences::AngleUnit angleUnit) const { if (isPi() || isExponential()) { return Sign::Positive; } diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index 736588d7d..06d9a6b63 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -82,7 +82,7 @@ int DecimalNode::simplificationOrderSameType(const ExpressionNode * e, bool canB double approx1 = other->templatedApproximate(); return (approx0 == approx1 ? 0 : (approx0 < approx1 ? -1 : 1)); } - return ((int)sign())*unsignedComparison; + return ((int)Number(this).sign())*unsignedComparison; } Expression DecimalNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index 8cdace321..b87dd0c71 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -22,7 +22,7 @@ int DivisionNode::polynomialDegree(Context & context, const char * symbolName) c } bool DivisionNode::childNeedsParenthesis(const TreeNode * child) const { - if (static_cast(child)->isNumber() && static_cast(child)->sign() == Sign::Negative) { + if (static_cast(child)->isNumber() && Number(static_cast(child)).sign() == Sign::Negative) { return true; } if (static_cast(child)->type() == Type::Rational && !static_cast(child)->denominator().isOne()) { diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 0f3960a31..1b58f1aef 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -379,7 +379,7 @@ Expression Expression::simplifyForComplexFormat(Context & context, Preferences:: e = CreateComplexExpression(ra, tb, complexFormat, ra.type() == ExpressionNode::Type::Undefined || tb.type() == ExpressionNode::Type::Undefined, isZero(ra), isOne(ra), isZero(tb), isOne(tb), isMinusOne(tb), - tb.type() == ExpressionNode::Type::Opposite || (tb.type() == ExpressionNode::Type::Rational && tb.sign() == ExpressionNode::Sign::Negative), + tb.type() == ExpressionNode::Type::Opposite || (tb.type() == ExpressionNode::Type::Rational && tb.sign(&context, angleUnit) == ExpressionNode::Sign::Negative), [](Expression e) { if (e.type() == ExpressionNode::Type::Opposite) { return e.childAtIndex(0); diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index c2cbd0c04..74cddfdf9 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -22,7 +22,7 @@ Expression FactorialNode::setSign(Sign s, Context * context, Preferences::AngleU // Layout bool FactorialNode::childNeedsParenthesis(const TreeNode * child) const { - if (static_cast(child)->isNumber() && static_cast(child)->sign() == Sign::Negative) { + if (static_cast(child)->isNumber() && Number(static_cast(child)).sign() == Sign::Negative) { return true; } if (static_cast(child)->type() == Type::Rational && !static_cast(child)->denominator().isOne()) { diff --git a/poincare/src/float.cpp b/poincare/src/float.cpp index c1c144996..a2039d714 100644 --- a/poincare/src/float.cpp +++ b/poincare/src/float.cpp @@ -5,8 +5,10 @@ namespace Poincare { template Expression FloatNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { + assert(s != Sign::Unknown); + Sign currentSign = m_value < 0 ? Sign::Negative : Sign::Positive; Expression thisExpr = Number(this); - Expression result = Float(-m_value); + Expression result = Float(s == currentSign ? m_value : -m_value); thisExpr.replaceWithInPlace(result); return result; } diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 0c7f7cf1f..958014e2d 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -120,7 +120,7 @@ Expression Logarithm::shallowReduce(Context & context, Preferences::AngleUnit an } #endif #endif - if (c.sign() == ExpressionNode::Sign::Negative || childAtIndex(1).sign() == ExpressionNode::Sign::Negative) { + if (c.sign(&context, angleUnit) == ExpressionNode::Sign::Negative || childAtIndex(1).sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { return *this; } Expression f = simpleShallowReduce(context, angleUnit); @@ -136,7 +136,7 @@ Expression Logarithm::shallowReduce(Context & context, Preferences::AngleUnit an */ bool letLogAtRoot = target == ExpressionNode::ReductionTarget::BottomUpComputation || parentIsAPowerOfSameBase(); // log(x^y, b)->y*log(x, b) if x>0 - if (!letLogAtRoot && c.type() == ExpressionNode::Type::Power && c.childAtIndex(0).sign() == ExpressionNode::Sign::Positive) { + if (!letLogAtRoot && c.type() == ExpressionNode::Type::Power && c.childAtIndex(0).sign(&context, angleUnit) == ExpressionNode::Sign::Positive) { Power p = static_cast(c); Expression x = p.childAtIndex(0); Expression y = p.childAtIndex(1); @@ -152,7 +152,7 @@ Expression Logarithm::shallowReduce(Context & context, Preferences::AngleUnit an Addition a = Addition(); for (int i = 0; i < c.numberOfChildren()-1; i++) { Expression factor = c.childAtIndex(i); - if (factor.sign() == ExpressionNode::Sign::Positive) { + if (factor.sign(&context, angleUnit) == ExpressionNode::Sign::Positive) { Expression newLog = clone(); static_cast(c).removeChildInPlace(factor, factor.numberOfChildren()); newLog.replaceChildAtIndexInPlace(0, factor); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 87304670c..9d512436f 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -17,13 +17,16 @@ namespace Poincare { -ExpressionNode::Sign MultiplicationNode::sign() const { +ExpressionNode::Sign MultiplicationNode::sign(Context * context, Preferences::AngleUnit angleUnit) const { if (numberOfChildren() == 0) { return Sign::Unknown; } int sign = 1; for (ExpressionNode * c : children()) { - sign *= (int)(c->sign()); + sign *= (int)(c->sign(context, angleUnit)); + } + if (sign == 0) { + return ExpressionNode::sign(context, angleUnit); } return (Sign)sign; } @@ -125,7 +128,7 @@ Expression MultiplicationNode::setSign(Sign s, Context * context, Preferences::A } bool MultiplicationNode::childNeedsParenthesis(const TreeNode * child) const { - if ((static_cast(child)->isNumber() && static_cast(child)->sign() == Sign::Negative) + if ((static_cast(child)->isNumber() && Number(static_cast(child)).sign() == Sign::Negative) || static_cast(child)->type() == ExpressionNode::Type::Opposite) { if (child == childAtIndex(0)) { @@ -179,7 +182,7 @@ void Multiplication::computeOnArrays(T * m, T * n, T * result, int mNumberOfColu Expression Multiplication::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit) { assert(s == ExpressionNode::Sign::Positive); for (int i = 0; i < numberOfChildren(); i++) { - if (childAtIndex(i).sign() == ExpressionNode::Sign::Negative) { + if (childAtIndex(i).sign(context, angleUnit) == ExpressionNode::Sign::Negative) { replaceChildAtIndexInPlace(i, childAtIndex(i).setSign(s, context, angleUnit)); } } @@ -199,7 +202,7 @@ Expression Multiplication::shallowBeautify(Context & context, Preferences::Angle // Step 1: Turn -n*A into -(n*A) Expression child0 = childAtIndex(0); - if (child0.isNumber() && child0.sign() == ExpressionNode::Sign::Negative) { + if (child0.isNumber() && child0.sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { if (child0.type() == ExpressionNode::Type::Rational && static_cast(child0).isMinusOne()) { removeChildAtIndexInPlace(0); } else { @@ -639,7 +642,7 @@ void Multiplication::addMissingFactors(Expression factor, Context & context, Pre for (int i = 0; i < numberOfChildren(); i++) { if (TermsHaveIdenticalBase(childAtIndex(i), factor)) { Expression sub = Subtraction(CreateExponent(childAtIndex(i)), CreateExponent(factor)).deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); - if (sub.sign() == ExpressionNode::Sign::Negative) { // index[0] < index[1] + if (sub.sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { // index[0] < index[1] sub = Opposite(sub); if (factor.type() == ExpressionNode::Type::Power) { factor.replaceChildAtIndexInPlace(1, sub); @@ -648,7 +651,7 @@ void Multiplication::addMissingFactors(Expression factor, Context & context, Pre } sub.shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); mergeInChildByFactorizingBase(i, factor, context, angleUnit, ExpressionNode::ReductionTarget::User); - } else if (sub.sign() == ExpressionNode::Sign::Unknown) { + } else if (sub.sign(&context, angleUnit) == ExpressionNode::Sign::Unknown) { mergeInChildByFactorizingBase(i, factor, context, angleUnit, ExpressionNode::ReductionTarget::User); } return; @@ -759,7 +762,7 @@ Expression Multiplication::mergeNegativePower(Context & context, Preferences::An } int i = 0; while (i < numberOfChildren()) { - if (childAtIndex(i).type() == ExpressionNode::Type::Power && childAtIndex(i).childAtIndex(1).sign() == ExpressionNode::Sign::Negative) { + if (childAtIndex(i).type() == ExpressionNode::Type::Power && childAtIndex(i).childAtIndex(1).sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { Expression e = childAtIndex(i); e.childAtIndex(1).setSign(ExpressionNode::Sign::Positive, &context, angleUnit); removeChildAtIndexInPlace(i); diff --git a/poincare/src/number.cpp b/poincare/src/number.cpp index 0b0138c40..18875ba11 100644 --- a/poincare/src/number.cpp +++ b/poincare/src/number.cpp @@ -19,7 +19,7 @@ double NumberNode::doubleApproximation() const { case Type::Undefined: return NAN; case Type::Infinity: - return sign() == Sign::Negative ? -INFINITY : INFINITY; + return Number(this).sign() == Sign::Negative ? -INFINITY : INFINITY; case Type::Float: if (size() == sizeof(FloatNode)) { return static_cast *>(this)->value(); diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index a0884ef81..489beac27 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -17,14 +17,14 @@ int OppositeNode::polynomialDegree(Context & context, const char * symbolName) c return childAtIndex(0)->polynomialDegree(context, symbolName); } -ExpressionNode::Sign OppositeNode::sign() const { - if (childAtIndex(0)->sign() == Sign::Positive) { +ExpressionNode::Sign OppositeNode::sign(Context * context, Preferences::AngleUnit angleUnit) const { + if (childAtIndex(0)->sign(context, angleUnit) == Sign::Positive) { return Sign::Negative; } - if (childAtIndex(0)->sign() == Sign::Negative) { + if (childAtIndex(0)->sign(context, angleUnit) == Sign::Negative) { return Sign::Positive; } - return Sign::Unknown; + return ExpressionNode::sign(context,angleUnit); } Expression OppositeNode::complexCartesianPart(Context & context, Preferences::AngleUnit angleUnit, bool real) const { @@ -38,7 +38,7 @@ Expression OppositeNode::complexCartesianPart(Context & context, Preferences::An /* Layout */ bool OppositeNode::childNeedsParenthesis(const TreeNode * child) const { - if (static_cast(child)->isNumber() && static_cast(child)->sign() == Sign::Negative) { + if (static_cast(child)->isNumber() && Number(static_cast(child)).sign() == Sign::Negative) { return true; } Type types[] = {Type::Addition, Type::Subtraction, Type::Opposite}; diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 5b6bf0420..db2abd165 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -26,14 +26,14 @@ namespace Poincare { // Properties -ExpressionNode::Sign PowerNode::sign() const { +ExpressionNode::Sign PowerNode::sign(Context * context, Preferences::AngleUnit angleUnit) const { if (Expression::shouldStopProcessing()) { return Sign::Unknown; } - if (childAtIndex(0)->sign() == Sign::Positive && childAtIndex(1)->sign() != Sign::Unknown) { + if (childAtIndex(0)->sign(context, angleUnit) == Sign::Positive && childAtIndex(1)->sign(context, angleUnit) != Sign::Unknown) { return Sign::Positive; } - if (childAtIndex(0)->sign() == Sign::Negative && childAtIndex(1)->type() == ExpressionNode::Type::Rational) { + if (childAtIndex(0)->sign(context, angleUnit) == Sign::Negative && childAtIndex(1)->type() == ExpressionNode::Type::Rational) { RationalNode * r = static_cast(childAtIndex(1)); if (r->denominator().isOne()) { assert(!Integer::Division(r->signedNumerator(), Integer(2)).remainder.isInfinity()); @@ -62,7 +62,7 @@ int PowerNode::polynomialDegree(Context & context, const char * symbolName) cons } if (childAtIndex(1)->type() == ExpressionNode::Type::Rational) { RationalNode * r = static_cast(childAtIndex(1)); - if (!r->denominator().isOne() || r->sign() == Sign::Negative) { + if (!r->denominator().isOne() || Number(r).sign() == Sign::Negative) { return -1; } Integer numeratorInt = r->signedNumerator(); @@ -163,7 +163,7 @@ Layout PowerNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int // Serialize bool PowerNode::childNeedsParenthesis(const TreeNode * child) const { - if (static_cast(child)->isNumber() && static_cast(child)->sign() == Sign::Negative) { + if (static_cast(child)->isNumber() && Number(static_cast(child)).sign() == Sign::Negative) { return true; } if (static_cast(child)->type() == Type::Rational && !static_cast(child)->denominator().isOne()) { @@ -257,10 +257,12 @@ Power::Power(Expression base, Expression exponent) : Expression(TreePool::shared Expression Power::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit) { assert(s == ExpressionNode::Sign::Positive); - assert(childAtIndex(0).sign() == ExpressionNode::Sign::Negative); - Expression result = Power(childAtIndex(0).setSign(ExpressionNode::Sign::Positive, context, angleUnit), childAtIndex(1)); - replaceWithInPlace(result); - return result; + if (childAtIndex(0).sign(context, angleUnit) == ExpressionNode::Sign::Negative) { + Expression result = Power(childAtIndex(0).setSign(ExpressionNode::Sign::Positive, context, angleUnit), childAtIndex(1)); + replaceWithInPlace(result); + return result; + } + return *this; } int Power::getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const { @@ -395,12 +397,12 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU Rational a = childAtIndex(0).convert(); // 0^x if (a.isZero()) { - if (childAtIndex(1).sign() == ExpressionNode::Sign::Positive) { + if (childAtIndex(1).sign(&context, angleUnit) == ExpressionNode::Sign::Positive) { Expression result = Rational(0); replaceWithInPlace(result); return result; } - if (childAtIndex(1).sign() == ExpressionNode::Sign::Negative) { + if (childAtIndex(1).sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { Expression result = Undefined(); replaceWithInPlace(result); return result; @@ -437,13 +439,13 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU // (±inf)^x if (childAtIndex(0).type() == ExpressionNode::Type::Infinity) { Expression result; - if (childAtIndex(1).sign() == ExpressionNode::Sign::Negative) { + if (childAtIndex(1).sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { // --> 0 if x < 0 result = Rational(0); - } else if (childAtIndex(1).sign() == ExpressionNode::Sign::Positive) { + } else if (childAtIndex(1).sign(&context, angleUnit) == ExpressionNode::Sign::Positive) { // --> (±inf) if x > 0 result = Infinity(false); - if (childAtIndex(0).sign() == ExpressionNode::Sign::Negative) { + if (childAtIndex(0).sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { // (-inf)^x --> (-1)^x*inf Power p(Rational(-1), childAtIndex(1)); result = Multiplication(p, result); @@ -515,7 +517,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU if (childAtIndex(1).type() == ExpressionNode::Type::Logarithm) { if (childAtIndex(1).numberOfChildren() == 2 && childAtIndex(0).isIdenticalTo(childAtIndex(1).childAtIndex(1))) { // y > 0 - if (childAtIndex(1).childAtIndex(0).sign() == ExpressionNode::Sign::Positive) { + if (childAtIndex(1).childAtIndex(0).sign(&context, angleUnit) == ExpressionNode::Sign::Positive) { Expression result = childAtIndex(1).childAtIndex(0); replaceWithInPlace(result); return result; @@ -535,7 +537,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU if (childAtIndex(0).type() == ExpressionNode::Type::Power) { Power p = childAtIndex(0).convert(); // Check if a > 0 or c is Integer - if (p.childAtIndex(0).sign() == ExpressionNode::Sign::Positive + if (p.childAtIndex(0).sign(&context, angleUnit) == ExpressionNode::Sign::Positive || (childAtIndex(1).type() == ExpressionNode::Type::Rational && childAtIndex(1).convert().integerDenominator().isOne())) { @@ -552,7 +554,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU // (a*b*...)^r -> |a|^r*(sign(a)*b*...)^r if a not -1 for (int i = 0; i < m.numberOfChildren(); i++) { // a is signed and a != -1 - if (m.childAtIndex(i).sign() != ExpressionNode::Sign::Unknown + if (m.childAtIndex(i).sign(&context, angleUnit) != ExpressionNode::Sign::Unknown && (m.childAtIndex(i).type() != ExpressionNode::Type::Rational || !m.childAtIndex(i).convert().isMinusOne())) { @@ -561,7 +563,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU Expression factor = m.childAtIndex(i); // (sign(a)*b*...)^r - if (factor.sign() == ExpressionNode::Sign::Negative) { + if (factor.sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { m.replaceChildAtIndexInPlace(i, Rational(-1)); factor = factor.setSign(ExpressionNode::Sign::Positive, &context, angleUnit); } else { @@ -695,7 +697,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU a->addOperand(m); m->shallowReduce(context, angleUnit, target); } - if (nr->sign() == Sign::Negative) { + if (nr->sign(&context, angleUnit) == Sign::Negative) { nr->replaceWith(new Rational(-1), true); childAtIndex(0)->replaceWith(a, true)->shallowReduce(context, angleUnit, target); return shallowReduce(context, angleUnit, target); @@ -709,7 +711,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU Expression Power::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { // X^-y -> 1/(X->shallowBeautify)^y - if (childAtIndex(1).sign() == ExpressionNode::Sign::Negative) { + if (childAtIndex(1).sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { Expression p = denominator(context, angleUnit); Division d = Division(Rational(1), p); p.shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); @@ -742,7 +744,7 @@ Expression Power::shallowBeautify(Context & context, Preferences::AngleUnit angl // Simplification Expression Power::denominator(Context & context, Preferences::AngleUnit angleUnit) const { - if (childAtIndex(1).sign() == ExpressionNode::Sign::Negative) { + if (childAtIndex(1).sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { Expression positivePowerClone = Power(childAtIndex(0).clone(), childAtIndex(1).clone().setSign(ExpressionNode::Sign::Positive, &context, angleUnit)); if (positivePowerClone.childAtIndex(1).type() == ExpressionNode::Type::Rational && positivePowerClone.childAtIndex(1).convert().isOne()) { return positivePowerClone.childAtIndex(0); diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index 7edd58ac1..3141e8090 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -124,10 +124,10 @@ template T RationalNode::templatedApproximate() const { // Comparison int RationalNode::NaturalOrder(const RationalNode * i, const RationalNode * j) { - if (i->sign() == Sign::Negative && j->sign() == Sign::Positive) { + if (Number(i).sign() == Sign::Negative && Number(j).sign() == Sign::Positive) { return -1; } - if (i->sign() == Sign::Positive && j->sign() == Sign::Negative) { + if (Number(i).sign() == Sign::Positive && Number(j).sign() == Sign::Negative) { return 1; } Integer i1 = Integer::Multiplication(i->signedNumerator(), j->denominator()); @@ -247,7 +247,7 @@ Expression Rational::shallowReduce(Context & context, Preferences::AngleUnit ang // Turn into Infinite if the numerator is too big. if (unsignedIntegerNumerator().isInfinity()) { assert(false); - return Infinity(sign() == ExpressionNode::Sign::Negative); + return Infinity(sign(&context, angleUnit) == ExpressionNode::Sign::Negative); } // Turn into 0 if the denominator is too big. if (integerDenominator().isInfinity()) { diff --git a/poincare/src/sign_function.cpp b/poincare/src/sign_function.cpp index e1534f65e..7b4e3acd1 100644 --- a/poincare/src/sign_function.cpp +++ b/poincare/src/sign_function.cpp @@ -12,8 +12,8 @@ constexpr Expression::FunctionHelper SignFunction::s_functionHelper; int SignFunctionNode::numberOfChildren() const { return SignFunction::s_functionHelper.numberOfChildren(); } -ExpressionNode::Sign SignFunctionNode::sign() const { - return childAtIndex(0)->sign(); +ExpressionNode::Sign SignFunctionNode::sign(Context * context, Preferences::AngleUnit angleUnit) const { + return childAtIndex(0)->sign(context, angleUnit); } Expression SignFunctionNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { @@ -59,8 +59,8 @@ Expression SignFunction::shallowReduce(Context & context, Preferences::AngleUnit } #endif Rational one(1); - if (childAtIndex(0).sign() != ExpressionNode::Sign::Unknown) { - if (childAtIndex(0).sign() == ExpressionNode::Sign::Negative) { + if (childAtIndex(0).sign(&context, angleUnit) != ExpressionNode::Sign::Unknown) { + if (childAtIndex(0).sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { one = Rational(-1); } } else { diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index 745608db4..d3ae99576 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -37,7 +37,7 @@ bool SubtractionNode::childNeedsParenthesis(const TreeNode * child) const { if (child == childAtIndex(0)) { return false; } - if (static_cast(child)->isNumber() && static_cast(child)->sign() == Sign::Negative) { + if (static_cast(child)->isNumber() && Number(static_cast(child)).sign() == Sign::Negative) { return true; } Type types[] = {Type::Subtraction, Type::Opposite, Type::Addition}; diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index b2250df25..89739f680 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -15,7 +15,7 @@ namespace Poincare { constexpr char Symbol::k_ans[]; -/*ExpressionNode::Sign SymbolNode::sign() const { +/*ExpressionNode::Sign SymbolNode::sign(Context * context, Preferences::AngleUnit angleUnit) const { TODO: Maybe, we will want to know that from a context given in parameter: if (context.expressionForSymbol(this, false) != nullptr) { return context.expressionForSymbol(this, false)->sign(context); diff --git a/poincare/src/symbol_abstract.cpp b/poincare/src/symbol_abstract.cpp index 3bc67899a..fa9576989 100644 --- a/poincare/src/symbol_abstract.cpp +++ b/poincare/src/symbol_abstract.cpp @@ -26,6 +26,23 @@ void SymbolAbstractNode::initToMatchSize(size_t goalSize) { assert(size() == goalSize); } +ExpressionNode::Sign SymbolAbstractNode::sign(Context * context, Preferences::AngleUnit angleUnit) const { + SymbolAbstract s(this); + Expression e = SymbolAbstract::Expand(s, *context, false); + if (e.isUninitialized()) { + return Sign::Unknown; + } + return e.sign(context, angleUnit); +} + +Expression SymbolAbstractNode::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit) { + SymbolAbstract sa(this); + Expression e = SymbolAbstract::Expand(sa, *context, true); + assert(!e.isUninitialized()); + sa.replaceWithInPlace(e); + return e.setSign(s, context, angleUnit); +} + int SymbolAbstractNode::simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const { assert(type() == e->type()); return strcmp(name(), static_cast(e)->name()); diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 46ea20caf..412facb69 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -116,7 +116,7 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& co } // Step 3. Look for an expression of type "cos(-a)", return "+/-cos(a)" - if (e.childAtIndex(0).sign() == ExpressionNode::Sign::Negative) { + if (e.childAtIndex(0).sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { e.childAtIndex(0).setSign(ExpressionNode::Sign::Positive, &context, angleUnit).shallowReduce(context, angleUnit, target); if (e.type() == ExpressionNode::Type::Cosine) { return e.shallowReduce(context, angleUnit, target); @@ -265,13 +265,13 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& c bool letArcFunctionAtRoot = target == ExpressionNode::ReductionTarget::BottomUpComputation || parentIsDirectTrigonometry(e); /* Step 4. Handle negative arguments: arccos(-x) = Pi-arcos(x), * arcsin(-x) = -arcsin(x), arctan(-x)= -arctan(x) */ - if (!letArcFunctionAtRoot && (e.childAtIndex(0).sign() == ExpressionNode::Sign::Negative + if (!letArcFunctionAtRoot && (e.childAtIndex(0).sign(&context, angleUnit) == ExpressionNode::Sign::Negative || (e.childAtIndex(0).type() == ExpressionNode::Type::Multiplication && e.childAtIndex(0).childAtIndex(0).type() == ExpressionNode::Type::Rational && e.childAtIndex(0).childAtIndex(0).convert().isMinusOne()))) { Expression newArgument; - if (e.childAtIndex(0).sign() == ExpressionNode::Sign::Negative) { + if (e.childAtIndex(0).sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { newArgument = e.childAtIndex(0).setSign(ExpressionNode::Sign::Positive, &context, angleUnit); } else { newArgument = e.childAtIndex(0); diff --git a/poincare/src/undefined.cpp b/poincare/src/undefined.cpp index 1279a91ed..020657a86 100644 --- a/poincare/src/undefined.cpp +++ b/poincare/src/undefined.cpp @@ -14,7 +14,7 @@ int UndefinedNode::polynomialDegree(Context & context, const char * symbolName) } Expression UndefinedNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { - return Undefined(); + return Undefined(this); } Layout UndefinedNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { diff --git a/poincare/test/complex.cpp b/poincare/test/complex.cpp index 3be1ca01c..d47451641 100644 --- a/poincare/test/complex.cpp +++ b/poincare/test/complex.cpp @@ -93,9 +93,9 @@ QUIZ_CASE(poincare_complex_parts) { // TODO: dim is not simplified yet //assert_expression_has_complex_cartesian_parts("dim(x)", "dim(x)", "0"); - assert_expression_has_complex_cartesian_parts("root(2,I)", "cos(-ln(2))", "sin(-ln(2))", Radian); - assert_expression_has_complex_cartesian_parts("root(2,I+1)", "R(2)*cos(-(90*ln(2))/P)", "R(2)*sin(-(90*ln(2))/P)"); - assert_expression_has_complex_cartesian_parts("root(2,I+1)", "R(2)*cos(-ln(2)/2)", "R(2)*sin(-ln(2)/2)", Radian); + assert_expression_has_complex_cartesian_parts("root(2,I)", "cos(ln(2))", "-sin(ln(2))", Radian); + assert_expression_has_complex_cartesian_parts("root(2,I+1)", "R(2)*cos((90*ln(2))/P)", "-R(2)*sin((90*ln(2))/P)"); + assert_expression_has_complex_cartesian_parts("root(2,I+1)", "R(2)*cos(ln(2)/2)", "-R(2)*sin(ln(2)/2)", Radian); assert_expression_has_complex_cartesian_parts("permute(10, 4)", "5040", "0"); // TODO: prediction is not simplified yet //assert_expression_has_complex_cartesian_parts("prediction(-2,-3)", "prediction(-2)", "0"); diff --git a/poincare/test/properties.cpp b/poincare/test/properties.cpp index 126477ef6..33548c961 100644 --- a/poincare/test/properties.cpp +++ b/poincare/test/properties.cpp @@ -16,7 +16,7 @@ void assert_parsed_expression_sign(const char * expression, Poincare::Expression Expression e = parse_expression(expression); quiz_assert(!e.isUninitialized()); e = e.simplify(globalContext, Degree); - quiz_assert(e.sign() == sign); + quiz_assert(e.sign(&globalContext, Degree) == sign); } QUIZ_CASE(poincare_sign) { @@ -25,6 +25,7 @@ QUIZ_CASE(poincare_sign) { assert_parsed_expression_sign("-2.345E-23", Negative); assert_parsed_expression_sign("2*(-3)*abs(-32)", Negative); assert_parsed_expression_sign("2*(-3)*abs(-32)*cos(3)", Unknown); + assert_parsed_expression_sign("x", Unknown); assert_parsed_expression_sign("2^(-abs(3))", Positive); assert_parsed_expression_sign("(-2)^4", Positive); assert_parsed_expression_sign("(-2)^3", Negative); From 2f8ede54f205c47014116e4800e65fefab3b7588 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 12 Dec 2018 15:23:10 +0100 Subject: [PATCH 083/373] [poincare] The sign function was used to decide wether an expression was of form -x. However, ln(0.3) has a negative sign but is not of form -x. This commit fixes the misuse of ExpressionNode::Sign::negative. For example, we do not turn sin(tan(9)) in -sin(-tan(9)) or arcsin(sin(12)) in -arcsin(-sin(12) because tan(9)<0 and sin(12)<0 --- poincare/include/poincare/expression.h | 6 +++ poincare/src/addition.cpp | 19 +++----- poincare/src/expression.cpp | 24 +++++++++- poincare/src/multiplication.cpp | 41 +++++++++-------- poincare/src/power.cpp | 26 +++++++---- poincare/src/trigonometry.cpp | 61 ++++++++++++-------------- poincare/test/simplify_mix.cpp | 2 +- 7 files changed, 104 insertions(+), 75 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 38f6c47d5..db45bb33c 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -269,6 +269,12 @@ protected: Expression defaultReplaceReplaceableSymbols(Context & context); /* Simplification */ + /* makePositiveAnyNegativeNumeralFactor looks for: + * - a negative numeral + * - a multiplication who has one numeral child whose is negative + * and turns the negative factor into a positive one + */ + Expression makePositiveAnyNegativeNumeralFactor(Context & context, Preferences::AngleUnit angleUnit); Expression denominator(Context & context, Preferences::AngleUnit angleUnit) const { return node()->denominator(context, angleUnit); } Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { return node()->shallowReduce(context, angleUnit, target); } Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { return node()->shallowBeautify(context, angleUnit); } diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 0d2a7a023..5b613dde1 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -115,24 +115,15 @@ Expression Addition::shallowBeautify(Context & context, Preferences::AngleUnit a * since we may remove some during the process. */ for (int i = 0; i < numberOfChildren(); i++) { - Expression childI = childAtIndex(i); - if (childI.type() != ExpressionNode::Type::Multiplication - || !childI.childAtIndex(0).isNumber() - || childI.childAtIndex(0).sign(&context, angleUnit) != ExpressionNode::Sign::Negative) + // Try to make the child i positive if any negative numeral factor is found + Expression subtractant = childAtIndex(i).makePositiveAnyNegativeNumeralFactor(context, angleUnit); + if (subtractant.isUninitialized()) { - // Ignore terms which are not like "(-r)*a" + // if subtractant is not initialized, it means the child i had no negative numeral factor + // we ignore terms which are not like "(-r)*a" continue; } - Multiplication m = static_cast(childI); - - if (m.childAtIndex(0).type() == ExpressionNode::Type::Rational && m.childAtIndex(0).convert().isMinusOne()) { - m.removeChildAtIndexInPlace(0); - } else { - m.childAtIndex(0).setSign(ExpressionNode::Sign::Positive, &context, angleUnit); - } - Expression subtractant = m.squashUnaryHierarchyInPlace(); - if (i == 0) { Opposite o = Opposite(subtractant); replaceChildAtIndexInPlace(i, o); diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 1b58f1aef..c66ccf34b 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -248,6 +248,28 @@ Expression Expression::defaultReplaceReplaceableSymbols(Context & context) { return *this; } +Expression Expression::makePositiveAnyNegativeNumeralFactor(Context & context, Preferences::AngleUnit angleUnit) { + // The expression is a negative number + if (isNumber() && sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { + return setSign(ExpressionNode::Sign::Positive, &context, angleUnit); + } + // The expression is a multiplication whose numeral factor is negative + if (type() == ExpressionNode::Type::Multiplication && numberOfChildren() > 0 && childAtIndex(0).isNumber() && childAtIndex(0).sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { + Multiplication m = convert(); + if (m.childAtIndex(0).type() == ExpressionNode::Type::Rational && m.childAtIndex(0).convert().isMinusOne()) { + // The negative numeral factor is -1, we just remove it + m.removeChildAtIndexInPlace(0); + // The multiplication can have only one child after removing -1 + return m.squashUnaryHierarchyInPlace(); + } else { + // Otherwise, we make it positive + m.childAtIndex(0).setSign(ExpressionNode::Sign::Positive, &context, angleUnit); + } + return m; + } + return Expression(); +} + template Evaluation Expression::approximateToEvaluation(Context& context, Preferences::AngleUnit angleUnit) const { // Reset interrupting flag because some evaluation methods use it @@ -379,7 +401,7 @@ Expression Expression::simplifyForComplexFormat(Context & context, Preferences:: e = CreateComplexExpression(ra, tb, complexFormat, ra.type() == ExpressionNode::Type::Undefined || tb.type() == ExpressionNode::Type::Undefined, isZero(ra), isOne(ra), isZero(tb), isOne(tb), isMinusOne(tb), - tb.type() == ExpressionNode::Type::Opposite || (tb.type() == ExpressionNode::Type::Rational && tb.sign(&context, angleUnit) == ExpressionNode::Sign::Negative), + tb.type() == ExpressionNode::Type::Opposite, [](Expression e) { if (e.type() == ExpressionNode::Type::Opposite) { return e.childAtIndex(0); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 9d512436f..ca4e9accd 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -201,17 +201,12 @@ Expression Multiplication::shallowBeautify(Context & context, Preferences::Angle * shall become a/b) or a non-integer rational term (3/2*a -> (3*a)/2). */ // Step 1: Turn -n*A into -(n*A) - Expression child0 = childAtIndex(0); - if (child0.isNumber() && child0.sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { - if (child0.type() == ExpressionNode::Type::Rational && static_cast(child0).isMinusOne()) { - removeChildAtIndexInPlace(0); - } else { - child0.setSign(ExpressionNode::Sign::Positive, &context, angleUnit); - } - Expression e = squashUnaryHierarchyInPlace(); + Expression noNegativeNumeral = makePositiveAnyNegativeNumeralFactor(context, angleUnit); + // If one negative numeral factor was made positive, we turn the expression in an Opposite + if (!noNegativeNumeral.isUninitialized()) { Opposite o = Opposite(); - e.replaceWithInPlace(o); - o.replaceChildAtIndexInPlace(0, e); + noNegativeNumeral.replaceWithInPlace(o); + o.replaceChildAtIndexInPlace(0, noNegativeNumeral); return o; } @@ -749,6 +744,8 @@ bool Multiplication::TermHasNumeralExponent(const Expression & e) { } Expression Multiplication::mergeNegativePower(Context & context, Preferences::AngleUnit angleUnit) { + /* mergeNegativePower groups all factors that are power of form a^(-b) together + * for instance, a^(-1)*b^(-c)*c = c*(a*b^c)^(-1) */ Multiplication m; // Special case for rational p/q: if q != 1, q should be at denominator if (childAtIndex(0).type() == ExpressionNode::Type::Rational && !childAtIndex(0).convert().integerDenominator().isOne()) { @@ -761,16 +758,24 @@ Expression Multiplication::mergeNegativePower(Context & context, Preferences::An } } int i = 0; + // Look for power of form a^(-b) while (i < numberOfChildren()) { - if (childAtIndex(i).type() == ExpressionNode::Type::Power && childAtIndex(i).childAtIndex(1).sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { - Expression e = childAtIndex(i); - e.childAtIndex(1).setSign(ExpressionNode::Sign::Positive, &context, angleUnit); - removeChildAtIndexInPlace(i); - m.addChildAtIndexInPlace(e, m.numberOfChildren(), m.numberOfChildren()); - e.shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); - } else { - i++; + if (childAtIndex(i).type() == ExpressionNode::Type::Power) { + Expression p = childAtIndex(i); + Expression positivePIndex = p.childAtIndex(1).makePositiveAnyNegativeNumeralFactor(context, angleUnit); + if (!positivePIndex.isUninitialized()) { + // Remove a^(-b) from the Multiplication + removeChildAtIndexInPlace(i); + // Add a^b to m + m.addChildAtIndexInPlace(p, m.numberOfChildren(), m.numberOfChildren()); + if (p.childAtIndex(1).isRationalOne()) { + p.replaceWithInPlace(p.childAtIndex(0)); + } + // We do not increment i because we removed one child from the Multiplication + continue; + } } + i++; } if (m.numberOfChildren() == 0) { return *this; diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index db2abd165..fbcac4be8 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -710,16 +710,19 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU } Expression Power::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { - // X^-y -> 1/(X->shallowBeautify)^y - if (childAtIndex(1).sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { - Expression p = denominator(context, angleUnit); + // Step 1: X^-y -> 1/(X->shallowBeautify)^y + Expression p = denominator(context, angleUnit); + // If the denominator is initialized, the index of the power is of form -y + if (!p.isUninitialized()) { Division d = Division(Rational(1), p); p.shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); replaceWithInPlace(d); return d.shallowBeautify(context, angleUnit); } + // Step 2: Turn a^(1/n) into root(a, n) if (childAtIndex(1).type() == ExpressionNode::Type::Rational && childAtIndex(1).convert().signedIntegerNumerator().isOne()) { Integer index = childAtIndex(1).convert().integerDenominator(); + // Special case: a^(1/2) --> sqrt(a) if (index.isEqualTo(Integer(2))) { Expression result = SquareRoot::Builder(childAtIndex(0)); replaceWithInPlace(result); @@ -730,7 +733,7 @@ Expression Power::shallowBeautify(Context & context, Preferences::AngleUnit angl return result; } - // +(a,b)^c ->(+(a,b))^c and *(a,b)^c ->(*(a,b))^c + // Step 3: +(a,b)^c ->(+(a,b))^c and *(a,b)^c ->(*(a,b))^c if (childAtIndex(0).type() == ExpressionNode::Type::Addition || childAtIndex(0).type() == ExpressionNode::Type::Multiplication) { @@ -744,12 +747,17 @@ Expression Power::shallowBeautify(Context & context, Preferences::AngleUnit angl // Simplification Expression Power::denominator(Context & context, Preferences::AngleUnit angleUnit) const { - if (childAtIndex(1).sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { - Expression positivePowerClone = Power(childAtIndex(0).clone(), childAtIndex(1).clone().setSign(ExpressionNode::Sign::Positive, &context, angleUnit)); - if (positivePowerClone.childAtIndex(1).type() == ExpressionNode::Type::Rational && positivePowerClone.childAtIndex(1).convert().isOne()) { - return positivePowerClone.childAtIndex(0); + // Clone the power + Expression clone = Power(childAtIndex(0).clone(), childAtIndex(1).clone()); + // If the power is of form x^(-y), denominator should be x^y + Expression positiveIndex = clone.childAtIndex(1).makePositiveAnyNegativeNumeralFactor(context, angleUnit); + if (!positiveIndex.isUninitialized()) { + // if y was -1, clone is now x^1, denominator is then only x + // we cannot shallowReduce the clone as it is not attached to its parent yet + if (positiveIndex.isRationalOne()) { + return clone.childAtIndex(0); } - return positivePowerClone; + return clone; } return Expression(); } diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 412facb69..c7dc75ba2 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -116,11 +116,14 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& co } // Step 3. Look for an expression of type "cos(-a)", return "+/-cos(a)" - if (e.childAtIndex(0).sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { - e.childAtIndex(0).setSign(ExpressionNode::Sign::Positive, &context, angleUnit).shallowReduce(context, angleUnit, target); + Expression positiveArg = e.childAtIndex(0).makePositiveAnyNegativeNumeralFactor(context, angleUnit); + if (!positiveArg.isUninitialized()) { + // The argument was of form cos(-a) if (e.type() == ExpressionNode::Type::Cosine) { + // cos(-a) = cos(a) return e.shallowReduce(context, angleUnit, target); } else { + // sin(-a) = -sin(a) or tan(-a) = -tan(a) Multiplication m(Rational(-1)); e.replaceWithInPlace(m); m.addChildAtIndexInPlace(e, 1, 1); @@ -263,36 +266,30 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& c * information on the parent which could later be a cosine, a sine or a tangent. */ bool letArcFunctionAtRoot = target == ExpressionNode::ReductionTarget::BottomUpComputation || parentIsDirectTrigonometry(e); - /* Step 4. Handle negative arguments: arccos(-x) = Pi-arcos(x), - * arcsin(-x) = -arcsin(x), arctan(-x)= -arctan(x) */ - if (!letArcFunctionAtRoot && (e.childAtIndex(0).sign(&context, angleUnit) == ExpressionNode::Sign::Negative - || (e.childAtIndex(0).type() == ExpressionNode::Type::Multiplication - && e.childAtIndex(0).childAtIndex(0).type() == ExpressionNode::Type::Rational - && e.childAtIndex(0).childAtIndex(0).convert().isMinusOne()))) - { - Expression newArgument; - if (e.childAtIndex(0).sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { - newArgument = e.childAtIndex(0).setSign(ExpressionNode::Sign::Positive, &context, angleUnit); - } else { - newArgument = e.childAtIndex(0); - static_cast(newArgument).removeChildAtIndexInPlace(0); - } - newArgument = newArgument.shallowReduce(context, angleUnit, target); - if (e.type() == ExpressionNode::Type::ArcCosine) { - // Do the reduction after the if case, or it might change the result! - Expression pi = angleUnit == Preferences::AngleUnit::Radian ? static_cast(Constant(Ion::Charset::SmallPi)) : static_cast(Rational(180)); - Subtraction s; - e.replaceWithInPlace(s); - s.replaceChildAtIndexInPlace(0, pi); - s.replaceChildAtIndexInPlace(1, e); - e.shallowReduce(context, angleUnit, target); - return s.shallowReduce(context, angleUnit, target); - } else { - Multiplication m(Rational(-1)); - e.replaceWithInPlace(m); - m.addChildAtIndexInPlace(e, 1, 1); - e.shallowReduce(context, angleUnit, target); - return m.shallowReduce(context, angleUnit, target); + /* Step 4. Handle opposite argument: arccos(-x) = Pi-arcos(x), + * arcsin(-x) = -arcsin(x), arctan(-x)= -arctan(x) * + */ + if (!letArcFunctionAtRoot) { + Expression positiveArg = e.childAtIndex(0).makePositiveAnyNegativeNumeralFactor(context, angleUnit); + if (!positiveArg.isUninitialized()) { + // The argument was made positive + // acos(-x) = pi-acos(x) + if (e.type() == ExpressionNode::Type::ArcCosine) { + Expression pi = angleUnit == Preferences::AngleUnit::Radian ? static_cast(Constant(Ion::Charset::SmallPi)) : static_cast(Rational(180)); + Subtraction s; + e.replaceWithInPlace(s); + s.replaceChildAtIndexInPlace(0, pi); + s.replaceChildAtIndexInPlace(1, e); + e.shallowReduce(context, angleUnit, target); + return s.shallowReduce(context, angleUnit, target); + } else { + // asin(-x) = -asin(x) or atan(-x) = -atan(x) + Multiplication m(Rational(-1)); + e.replaceWithInPlace(m); + m.addChildAtIndexInPlace(e, 1, 1); + e.shallowReduce(context, angleUnit, target); + return m.shallowReduce(context, angleUnit, target); + } } } diff --git a/poincare/test/simplify_mix.cpp b/poincare/test/simplify_mix.cpp index 4db707824..6385daa73 100644 --- a/poincare/test/simplify_mix.cpp +++ b/poincare/test/simplify_mix.cpp @@ -45,7 +45,7 @@ QUIZ_CASE(poincare_simplify_mix) { assert_parsed_expression_simplify_to("R(-I)", "R(-I)"); assert_parsed_expression_simplify_to("A*cos(9)IIln(2)", "-cos(9)*ln(2)*A"); assert_parsed_expression_simplify_to("(R(2)+R(2)*I)/2(R(2)+R(2)*I)/2(R(2)+R(2)*I)/2", "(R(2)-R(2)*I)/32"); - assert_parsed_expression_simplify_to("root(5^((-I)3^9),I)", "(5^(-19683*I))^(-I)"); + assert_parsed_expression_simplify_to("root(5^((-I)3^9),I)", "1/(1/5^(19683*I))^I"); assert_parsed_expression_simplify_to("I^I", "I^I"); //assert_parsed_expression_simplify_to("log(cos(9)^ln(6), cos(9))", "ln(2)+ln(3)"); // TODO: for this to work, we must know the sign of cos(9) From 64aebcf16d3de92ed26a8bc205aa602b5504f2bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 7 Dec 2018 16:51:15 +0100 Subject: [PATCH 084/373] [poincare] Implement shallowReduce of ComplexArgument, AbsoluteValue, RealPart and ImaginaryPart --- poincare/include/poincare/absolute_value.h | 2 +- poincare/include/poincare/complex_argument.h | 2 +- poincare/include/poincare/imaginary_part.h | 2 +- poincare/include/poincare/real_part.h | 2 +- poincare/src/absolute_value.cpp | 19 ++++++++----------- poincare/src/complex_argument.cpp | 11 ++++++++--- poincare/src/expression_node.cpp | 2 +- poincare/src/imaginary_part.cpp | 9 +++++++-- poincare/src/real_part.cpp | 9 +++++++-- poincare/test/complex.cpp | 10 +++++----- poincare/test/function.cpp | 4 ++++ 11 files changed, 44 insertions(+), 28 deletions(-) diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 2aad1feed..357198c54 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -55,7 +55,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("abs", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit AbsoluteValue(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/complex_argument.h b/poincare/include/poincare/complex_argument.h index 014b8956d..9040a8b62 100644 --- a/poincare/include/poincare/complex_argument.h +++ b/poincare/include/poincare/complex_argument.h @@ -47,7 +47,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("arg", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit ComplexArgument(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/imaginary_part.h b/poincare/include/poincare/imaginary_part.h index 8b40bfdd8..80da8e387 100644 --- a/poincare/include/poincare/imaginary_part.h +++ b/poincare/include/poincare/imaginary_part.h @@ -50,7 +50,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("im", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit ImaginaryPart(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/real_part.h b/poincare/include/poincare/real_part.h index e719175cd..f1d99b93d 100644 --- a/poincare/include/poincare/real_part.h +++ b/poincare/include/poincare/real_part.h @@ -50,7 +50,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("re", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit RealPart(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 0270ba146..4e2655683 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -25,7 +26,7 @@ int AbsoluteValueNode::serialize(char * buffer, int bufferSize, Preferences::Pri } Expression AbsoluteValueNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return AbsoluteValue(this).shallowReduce(context, angleUnit); + return AbsoluteValue(this).shallowReduce(context, angleUnit, target); } Expression AbsoluteValue::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit) { @@ -33,12 +34,11 @@ Expression AbsoluteValue::setSign(ExpressionNode::Sign s, Context * context, Pre return *this; } -Expression AbsoluteValue::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression AbsoluteValue::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { Expression e = Expression::defaultShallowReduce(context, angleUnit); if (e.isUndefined()) { return e; } - Expression c = childAtIndex(0); #if MATRIX_EXACT_REDUCING #if 0 if (c->type() == Type::Matrix) { @@ -46,14 +46,11 @@ Expression AbsoluteValue::shallowReduce(Context & context, Preferences::AngleUni } #endif #endif - if (c.sign(&context, angleUnit) == ExpressionNode::Sign::Positive) { - replaceWithInPlace(c); - return c; - } - if (c.sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { - Expression result = c.setSign(ExpressionNode::Sign::Positive, &context, angleUnit); - replaceWithInPlace(result); - return result; + Expression c = childAtIndex(0); + Expression norm = c.complexNorm(context, angleUnit); + if (!norm.isUninitialized()) { + replaceWithInPlace(norm); + return norm.deepReduce(context, angleUnit, target); } return *this; } diff --git a/poincare/src/complex_argument.cpp b/poincare/src/complex_argument.cpp index c7d6d0396..01893996b 100644 --- a/poincare/src/complex_argument.cpp +++ b/poincare/src/complex_argument.cpp @@ -22,7 +22,7 @@ int ComplexArgumentNode::serialize(char * buffer, int bufferSize, Preferences::P } Expression ComplexArgumentNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return ComplexArgument(this).shallowReduce(context, angleUnit); + return ComplexArgument(this).shallowReduce(context, angleUnit, target); } template @@ -30,19 +30,24 @@ Complex ComplexArgumentNode::computeOnComplex(const std::complex c, Prefer return Complex(std::arg(c)); } -Expression ComplexArgument::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression ComplexArgument::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { Expression e = Expression::defaultShallowReduce(context, angleUnit); if (e.isUndefined()) { return e; } } -#if MATRIX_EXACT_REDUCING Expression c = childAtIndex(0); +#if MATRIX_EXACT_REDUCING if (c.type() == ExpressionNode::Type::Matrix) { return SimplificationHelper::Map(*this, context, angleUnit); } #endif + Expression arg = c.complexArgument(context, angleUnit); + if (!arg.isUninitialized()) { + replaceWithInPlace(arg); + return arg.deepReduce(context, angleUnit, target); + } return *this; } diff --git a/poincare/src/expression_node.cpp b/poincare/src/expression_node.cpp index cc5c0432f..9541ee766 100644 --- a/poincare/src/expression_node.cpp +++ b/poincare/src/expression_node.cpp @@ -109,7 +109,7 @@ Expression ExpressionNode::complexArgument(Context & context, Preferences::Angle Multiplication( SignFunction::Builder(b).shallowReduce(context, angleUnit), Division(Constant(Ion::Charset::SmallPi), Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ), + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), arcTangent ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } else { diff --git a/poincare/src/imaginary_part.cpp b/poincare/src/imaginary_part.cpp index 2a5c3ae43..9379d5ec4 100644 --- a/poincare/src/imaginary_part.cpp +++ b/poincare/src/imaginary_part.cpp @@ -20,10 +20,10 @@ int ImaginaryPartNode::serialize(char * buffer, int bufferSize, Preferences::Pri } Expression ImaginaryPartNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return ImaginaryPart(this).shallowReduce(context, angleUnit); + return ImaginaryPart(this).shallowReduce(context, angleUnit, target); } -Expression ImaginaryPart::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression ImaginaryPart::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { Expression e = Expression::defaultShallowReduce(context, angleUnit); if (e.isUndefined()) { @@ -41,6 +41,11 @@ Expression ImaginaryPart::shallowReduce(Context & context, Preferences::AngleUni replaceWithInPlace(result); return result; } + Expression im = c.imaginaryPart(context, angleUnit); + if (!im.isUninitialized()) { + replaceWithInPlace(im); + return im.deepReduce(context, angleUnit, target); + } return *this; } diff --git a/poincare/src/real_part.cpp b/poincare/src/real_part.cpp index b4fdf9e88..e599dce38 100644 --- a/poincare/src/real_part.cpp +++ b/poincare/src/real_part.cpp @@ -20,10 +20,10 @@ int RealPartNode::serialize(char * buffer, int bufferSize, Preferences::PrintFlo } Expression RealPartNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return RealPart(this).shallowReduce(context, angleUnit); + return RealPart(this).shallowReduce(context, angleUnit, target); } -Expression RealPart::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression RealPart::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { Expression e = Expression::defaultShallowReduce(context, angleUnit); if (e.isUndefined()) { @@ -40,6 +40,11 @@ Expression RealPart::shallowReduce(Context & context, Preferences::AngleUnit ang replaceWithInPlace(c); return c; } + Expression re = c.realPart(context, angleUnit); + if (!re.isUninitialized()) { + replaceWithInPlace(re); + return re.deepReduce(context, angleUnit, target); + } return *this; } diff --git a/poincare/test/complex.cpp b/poincare/test/complex.cpp index d47451641..e86e56afb 100644 --- a/poincare/test/complex.cpp +++ b/poincare/test/complex.cpp @@ -69,12 +69,12 @@ QUIZ_CASE(poincare_complex_parts) { assert_expression_has_complex_cartesian_parts("I", "0", "1"); assert_expression_has_complex_cartesian_parts("abs(-3)", "3", "0"); - assert_expression_has_complex_cartesian_parts("abs(-3+I)", "abs(-3+I)", "0"); + assert_expression_has_complex_cartesian_parts("abs(-3+I)", "R(10)", "0"); assert_expression_has_complex_cartesian_parts("atan(2)", "atan(2)", "0"); assert_expression_has_complex_cartesian_parts("atan(2+I)", nullptr, nullptr); assert_expression_has_complex_cartesian_parts("binomial(10, 4)", "210", "0"); assert_expression_has_complex_cartesian_parts("ceil(-1.3)", "-1", "0"); - assert_expression_has_complex_cartesian_parts("arg(-2)", "arg(-2)", "0"); + assert_expression_has_complex_cartesian_parts("arg(-2)", "P", "0"); // TODO: confidence is not simplified yet //assert_expression_has_complex_cartesian_parts("confidence(-2,-3)", "confidence(-2)", "0"); assert_expression_has_complex_cartesian_parts("conj(-2)", "-2", "0"); @@ -87,7 +87,7 @@ QUIZ_CASE(poincare_complex_parts) { assert_expression_has_complex_cartesian_parts("floor(x)", "floor(x)", "0"); assert_expression_has_complex_cartesian_parts("frac(x)", "frac(x)", "0"); assert_expression_has_complex_cartesian_parts("gcd(x,y)", "gcd(x,y)", "0"); - assert_expression_has_complex_cartesian_parts("im(x)", "im(x)", "0"); + assert_expression_has_complex_cartesian_parts("im(1+I)", "1", "0"); assert_expression_has_complex_cartesian_parts("int(x^2, x, 1, 2)", "int(x^2,x,1,2)", "0"); assert_expression_has_complex_cartesian_parts("lcm(x,y)", "lcm(x,y)", "0"); // TODO: dim is not simplified yet @@ -101,7 +101,7 @@ QUIZ_CASE(poincare_complex_parts) { //assert_expression_has_complex_cartesian_parts("prediction(-2,-3)", "prediction(-2)", "0"); assert_expression_has_complex_cartesian_parts("randint(2,4)", "randint(2,4)", "0"); assert_expression_has_complex_cartesian_parts("random()", "random()", "0"); - assert_expression_has_complex_cartesian_parts("re(x)", "re(x)", "0"); + assert_expression_has_complex_cartesian_parts("re(x)", "x", "0"); assert_expression_has_complex_cartesian_parts("round(x,y)", "round(x,y)", "0"); assert_expression_has_complex_cartesian_parts("sign(x)", "sign(x)", "0"); assert_expression_has_complex_cartesian_parts("sin(23)", "sin(23)", "0"); @@ -148,5 +148,5 @@ QUIZ_CASE(poincare_complex_parts) { assert_expression_has_complex_polar_parts("P", "P", "0"); assert_expression_has_complex_polar_parts("I", "1", "P/2"); assert_expression_has_complex_polar_parts("abs(-3)", "3", "0"); - assert_expression_has_complex_polar_parts("abs(-3+I)", "abs(-3+I)", "0"); + assert_expression_has_complex_polar_parts("abs(-3+I)", "R(10)", "0"); } diff --git a/poincare/test/function.cpp b/poincare/test/function.cpp index 8c711a7b5..d8d9d654a 100644 --- a/poincare/test/function.cpp +++ b/poincare/test/function.cpp @@ -238,6 +238,8 @@ QUIZ_CASE(poincare_function_evaluate) { QUIZ_CASE(poincare_function_simplify) { assert_parsed_expression_simplify_to("abs(P)", "P"); assert_parsed_expression_simplify_to("abs(-P)", "P"); + assert_parsed_expression_simplify_to("abs(1+I)", "R(2)"); + assert_parsed_expression_simplify_to("arg(1+I)", "P/4"); assert_parsed_expression_simplify_to("binomial(20,3)", "1140"); assert_parsed_expression_simplify_to("binomial(20,10)", "184756"); assert_parsed_expression_simplify_to("ceil(-1.3)", "-1"); @@ -257,9 +259,11 @@ QUIZ_CASE(poincare_function_simplify) { assert_parsed_expression_simplify_to("frac(-1.3)", "7/10"); assert_parsed_expression_simplify_to("gcd(123,278)", "1"); assert_parsed_expression_simplify_to("gcd(11,121)", "11"); + assert_parsed_expression_simplify_to("im(1+5*I)", "5"); assert_parsed_expression_simplify_to("lcm(123,278)", "34194"); assert_parsed_expression_simplify_to("lcm(11,121)", "121"); assert_parsed_expression_simplify_to("R(4)", "2"); + assert_parsed_expression_simplify_to("re(1+5*I)", "1"); assert_parsed_expression_simplify_to("root(4,3)", "root(4,3)"); assert_parsed_expression_simplify_to("root(4,P)", "4^(1/P)"); assert_parsed_expression_simplify_to("root(27,3)", "3"); From 91163ae6f556921ba33a139559619dd5e2d74354 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 7 Dec 2018 16:59:18 +0100 Subject: [PATCH 085/373] [poincare] Improve complexSquareNorm thanks to sign --- poincare/src/expression_node.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/poincare/src/expression_node.cpp b/poincare/src/expression_node.cpp index 9541ee766..bb02fe3de 100644 --- a/poincare/src/expression_node.cpp +++ b/poincare/src/expression_node.cpp @@ -80,6 +80,17 @@ Expression ExpressionNode::imaginaryPart(Context & context, Preferences::AngleUn } Expression ExpressionNode::complexNorm(Context & context, Preferences::AngleUnit angleUnit) const { + Expression e(this); + Sign s = sign(&context, angleUnit); + // Case 1: the expression is positive real + if (s == ExpressionNode::Sign::Positive) { + return e.clone(); + } + // Case 2: the argument is negative real + if (s == ExpressionNode::Sign::Negative) { + return e.clone().setSign(ExpressionNode::Sign::Positive, &context, angleUnit, ReductionTarget::BottomUpComputation); + } + // Case 3: the argument is complex or of unknown approximation Expression a = realPart(context, angleUnit); Expression b = imaginaryPart(context, angleUnit); if (!a.isUninitialized() && !b.isUninitialized()) { From c62922ec5cb5d9c5a1a5e41719f760eeaafbb01f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 11 Dec 2018 09:42:47 +0100 Subject: [PATCH 086/373] [poincare] Change complex getters design: extract real and imaginary parts at the same time in complexCartesian and norm and arg in complexPolar --- poincare/include/poincare/absolute_value.h | 3 +- poincare/include/poincare/addition.h | 5 +- poincare/include/poincare/arc_tangent.h | 8 +- .../include/poincare/binomial_coefficient.h | 3 +- poincare/include/poincare/ceiling.h | 3 +- poincare/include/poincare/complex_argument.h | 3 +- poincare/include/poincare/complex_cartesian.h | 47 ++++++ poincare/include/poincare/complex_helper.h | 24 ++-- poincare/include/poincare/complex_polar.h | 47 ++++++ .../include/poincare/confidence_interval.h | 3 +- poincare/include/poincare/conjugate.h | 4 +- poincare/include/poincare/constant.h | 3 +- poincare/include/poincare/cosine.h | 3 +- poincare/include/poincare/derivative.h | 3 +- poincare/include/poincare/division.h | 10 +- poincare/include/poincare/division_quotient.h | 3 +- .../include/poincare/division_remainder.h | 3 +- poincare/include/poincare/expression.h | 6 +- poincare/include/poincare/expression_node.h | 18 ++- poincare/include/poincare/factorial.h | 3 +- poincare/include/poincare/floor.h | 3 +- poincare/include/poincare/frac_part.h | 3 +- poincare/include/poincare/function.h | 4 +- .../include/poincare/great_common_divisor.h | 3 +- poincare/include/poincare/imaginary_part.h | 3 +- poincare/include/poincare/integral.h | 3 +- .../include/poincare/least_common_multiple.h | 3 +- poincare/include/poincare/matrix_dimension.h | 3 +- poincare/include/poincare/multiplication.h | 11 +- poincare/include/poincare/nth_root.h | 8 +- poincare/include/poincare/number.h | 3 +- poincare/include/poincare/opposite.h | 7 +- poincare/include/poincare/parenthesis.h | 6 +- .../include/poincare/permute_coefficient.h | 3 +- poincare/include/poincare/power.h | 8 +- .../include/poincare/prediction_interval.h | 3 +- poincare/include/poincare/randint.h | 3 +- poincare/include/poincare/random.h | 3 +- poincare/include/poincare/real_part.h | 4 +- poincare/include/poincare/round.h | 4 +- poincare/include/poincare/sign_function.h | 3 +- poincare/include/poincare/sine.h | 3 +- poincare/include/poincare/square_root.h | 16 ++- poincare/include/poincare/subtraction.h | 6 +- poincare/include/poincare/symbol.h | 4 +- poincare/include/poincare/symbol_abstract.h | 2 + poincare/include/poincare/tangent.h | 3 +- poincare/include/poincare/undefined.h | 3 +- poincare/src/absolute_value.cpp | 10 +- poincare/src/addition.cpp | 22 ++- poincare/src/complex_argument.cpp | 10 +- poincare/src/complex_helper.cpp | 135 +++++++++++++++--- poincare/src/conjugate.cpp | 28 +++- poincare/src/constant.cpp | 13 +- poincare/src/division.cpp | 72 +++++----- poincare/src/expression.cpp | 23 ++- poincare/src/expression_node.cpp | 69 +-------- poincare/src/function.cpp | 16 +-- poincare/src/imaginary_part.cpp | 6 +- poincare/src/multiplication.cpp | 30 ++-- poincare/src/nth_root.cpp | 47 +++--- poincare/src/opposite.cpp | 26 +++- poincare/src/power.cpp | 35 +++-- poincare/src/real_part.cpp | 6 +- poincare/src/square_root.cpp | 45 +++--- poincare/src/subtraction.cpp | 15 +- poincare/src/symbol.cpp | 18 +-- poincare/src/symbol_abstract.cpp | 20 +++ poincare/src/tree_pool.cpp | 2 + poincare/test/complex.cpp | 36 ++--- 70 files changed, 576 insertions(+), 438 deletions(-) create mode 100644 poincare/include/poincare/complex_cartesian.h create mode 100644 poincare/include/poincare/complex_polar.h diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 357198c54..482508e9c 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -25,8 +25,7 @@ public: Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } // Approximation template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 2956351c5..51004ba94 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -28,8 +28,7 @@ public: int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const override; // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPart(context, angleUnit, true); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPart(context, angleUnit, false); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; // Evaluation template static Complex compute(const std::complex c, const std::complex d) { return Complex(c+d); } @@ -40,8 +39,6 @@ public: return ApproximationHelper::ElementWiseOnMatrixComplexAndComplex(m, c, compute); } private: - // Complex - Expression complexPart(Context & context, Preferences::AngleUnit angleUnit, bool real) const; // Layout bool childNeedsParenthesis(const TreeNode * child) const override; Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/arc_tangent.h b/poincare/include/poincare/arc_tangent.h index 924772deb..d6ce0f626 100644 --- a/poincare/include/poincare/arc_tangent.h +++ b/poincare/include/poincare/arc_tangent.h @@ -24,12 +24,8 @@ public: Type type() const override { return Type::ArcTangent; } // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { - return ComplexHelper::realPartOfComplexFunction(this, context, angleUnit); - } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { - return ComplexHelper::imaginaryPartOfComplexFunction(this, context, angleUnit); - } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianComplexFunction(this, context, angleUnit); } + private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/binomial_coefficient.h b/poincare/include/poincare/binomial_coefficient.h index 1b05a0fc7..fe8395167 100644 --- a/poincare/include/poincare/binomial_coefficient.h +++ b/poincare/include/poincare/binomial_coefficient.h @@ -20,8 +20,7 @@ public: #endif // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } // Properties Type type() const override{ return Type::BinomialCoefficient; } diff --git a/poincare/include/poincare/ceiling.h b/poincare/include/poincare/ceiling.h index 2d1efeeac..185d18dae 100644 --- a/poincare/include/poincare/ceiling.h +++ b/poincare/include/poincare/ceiling.h @@ -20,8 +20,7 @@ public: #endif // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } // Properties Type type() const override { return Type::Ceiling; } diff --git a/poincare/include/poincare/complex_argument.h b/poincare/include/poincare/complex_argument.h index 9040a8b62..f431b1152 100644 --- a/poincare/include/poincare/complex_argument.h +++ b/poincare/include/poincare/complex_argument.h @@ -19,8 +19,7 @@ public: } #endif // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } // Properties Type type() const override { return Type::ComplexArgument; } diff --git a/poincare/include/poincare/complex_cartesian.h b/poincare/include/poincare/complex_cartesian.h new file mode 100644 index 000000000..3f996c3ef --- /dev/null +++ b/poincare/include/poincare/complex_cartesian.h @@ -0,0 +1,47 @@ +#ifndef POINCARE_COMPLEX_CARTESIAN_H +#define POINCARE_COMPLEX_CARTESIAN_H + +#include +#include + +namespace Poincare { + +class ComplexCartesianNode : public ExpressionNode { +public: + + // TreeNode + size_t size() const override { return sizeof(ComplexCartesianNode); } + int numberOfChildren() const override { return 2; } +#if POINCARE_TREE_LOG + virtual void logNodeName(std::ostream & stream) const override { + stream << "ComplexCartesian"; + } +#endif + + // Properties + Type type() const override { return Type::ComplexCartesian; } +private: + // Layout + Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override { assert(false); return Layout(); } + // Evaluation + Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { assert(false); return Evaluation(); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { assert(false); return Evaluation(); } +}; + +class ComplexCartesian final : public Expression { +public: + ComplexCartesian() : Expression() {} + static ComplexCartesian Builder(Expression child0, Expression child1) { return ComplexCartesian(child0, child1); } + Expression real() { return childAtIndex(0); } + Expression imag() { return childAtIndex(1); } +private: + ComplexCartesian(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { + replaceChildAtIndexInPlace(0, child0); + replaceChildAtIndexInPlace(1, child1); + } +}; + + +} + +#endif diff --git a/poincare/include/poincare/complex_helper.h b/poincare/include/poincare/complex_helper.h index 2bddd7719..78553d079 100644 --- a/poincare/include/poincare/complex_helper.h +++ b/poincare/include/poincare/complex_helper.h @@ -2,29 +2,21 @@ #define POINCARE_COMPLEX_HELPER_H #include +#include +#include namespace Poincare { class ComplexHelper { public: - static Expression realPartOfComplexFunction(const ExpressionNode * e, Context & context, Preferences::AngleUnit angleUnit) { - return cartesianPartOfComplexFunction(e, context, angleUnit, true); - } - static Expression imaginaryPartOfComplexFunction(const ExpressionNode * e, Context & context, Preferences::AngleUnit angleUnit) { - return cartesianPartOfComplexFunction(e, context, angleUnit, false); - } - static Expression realPartRealFunction(const ExpressionNode * e, Context & context, Preferences::AngleUnit angleUnit) { - return Expression(e).clone().deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); - } - static Expression imaginaryPartRealFunction(const ExpressionNode * e, Context & context, Preferences::AngleUnit angleUnit); + static ComplexCartesian complexCartesianComplexFunction(const ExpressionNode * e, Context & context, Preferences::AngleUnit angleUnit); + static ComplexCartesian complexCartesianRealFunction(const ExpressionNode * e, Context & context, Preferences::AngleUnit angleUnit); // static Expression realPartMatrix(const Expression e, Context & context, Preferences::AngleUnit angleUnit); - - static Expression realPartFromPolarParts(const ExpressionNode * node, Context & context, Preferences::AngleUnit angleUnit) { return complexCartesianPartFromPolarParts(node, context, angleUnit, true); } - static Expression imaginaryPartFromPolarParts(const ExpressionNode * node, Context & context, Preferences::AngleUnit angleUnit) { return complexCartesianPartFromPolarParts(node, context, angleUnit, false); } - + static ComplexCartesian complexCartesianFromComplexPolar(const ExpressionNode * node, Context & context, Preferences::AngleUnit angleUnit); + static ComplexPolar complexPolarFromComplexCartesian(const ExpressionNode * node, Context & context, Preferences::AngleUnit angleUnit); + static Expression complexSquareNormComplexCartesian(Expression real, Expression imag, Context & context, Preferences::AngleUnit angleUnit); private: - static Expression cartesianPartOfComplexFunction(const ExpressionNode * node, Context & context, Preferences::AngleUnit angleUnit, bool real); - static Expression complexCartesianPartFromPolarParts(const ExpressionNode * node, Context & context, Preferences::AngleUnit angleUnit, bool isReal); + static Expression complexCartesianFromComplexPolarHelper(Expression norm, Expression trigo, Context & context, Preferences::AngleUnit angleUnit); }; } diff --git a/poincare/include/poincare/complex_polar.h b/poincare/include/poincare/complex_polar.h new file mode 100644 index 000000000..ff947ccf9 --- /dev/null +++ b/poincare/include/poincare/complex_polar.h @@ -0,0 +1,47 @@ +#ifndef POINCARE_COMPLEX_POLAR_H +#define POINCARE_COMPLEX_POLAR_H + +#include +#include + +namespace Poincare { + +class ComplexPolarNode : public ExpressionNode { +public: + + // TreeNode + size_t size() const override { return sizeof(ComplexPolarNode); } + int numberOfChildren() const override { return 2; } +#if POINCARE_TREE_LOG + virtual void logNodeName(std::ostream & stream) const override { + stream << "ComplexPolar"; + } +#endif + + // Properties + Type type() const override { return Type::ComplexPolar; } +private: + // Layout + Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override { assert(false); return Layout(); } + // Evaluation + Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { assert(false); return Evaluation(); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { assert(false); return Evaluation(); } +}; + +class ComplexPolar final : public Expression { +public: + ComplexPolar() : Expression() {} + static ComplexPolar Builder(Expression child0, Expression child1) { return ComplexPolar(child0, child1); } + Expression norm() { return childAtIndex(0); } + Expression arg() { return childAtIndex(1); } +private: + ComplexPolar(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { + replaceChildAtIndexInPlace(0, child0); + replaceChildAtIndexInPlace(1, child1); + } +}; + + +} + +#endif diff --git a/poincare/include/poincare/confidence_interval.h b/poincare/include/poincare/confidence_interval.h index 395c56e04..48a829d9c 100644 --- a/poincare/include/poincare/confidence_interval.h +++ b/poincare/include/poincare/confidence_interval.h @@ -21,8 +21,7 @@ public: // ExpressionNode // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } // Properties Type type() const override { return Type::ConfidenceInterval; } diff --git a/poincare/include/poincare/conjugate.h b/poincare/include/poincare/conjugate.h index c05c47e1c..4c96ccecc 100644 --- a/poincare/include/poincare/conjugate.h +++ b/poincare/include/poincare/conjugate.h @@ -18,8 +18,8 @@ public: } #endif - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override; - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override; + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; + ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override; // Properties Type type() const override { return Type::Conjugate; } diff --git a/poincare/include/poincare/constant.h b/poincare/include/poincare/constant.h index bd104b05b..4d91e8ca9 100644 --- a/poincare/include/poincare/constant.h +++ b/poincare/include/poincare/constant.h @@ -18,8 +18,7 @@ public: #endif // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override; - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override; + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; // Expression Properties Type type() const override { return Type::Constant; } diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index 83dbee238..757ca2315 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -21,8 +21,7 @@ public: #endif // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartOfComplexFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartOfComplexFunction(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianComplexFunction(this, context, angleUnit); } // Properties Type type() const override { return Type::Cosine; } diff --git a/poincare/include/poincare/derivative.h b/poincare/include/poincare/derivative.h index 62d813000..1ba1d339f 100644 --- a/poincare/include/poincare/derivative.h +++ b/poincare/include/poincare/derivative.h @@ -21,8 +21,7 @@ public: #endif // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } // Properties Type type() const override { return Type::Derivative; } diff --git a/poincare/include/poincare/division.h b/poincare/include/poincare/division.h index 85e6d6441..7533bd53c 100644 --- a/poincare/include/poincare/division.h +++ b/poincare/include/poincare/division.h @@ -23,12 +23,12 @@ public: #endif /* Property */ - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPart(context, angleUnit, true); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPart(context, angleUnit, false); } - Expression complexNorm(Context & context, Preferences::AngleUnit angleUnit) const override; + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; /* If we use the formula arg(a/b) = arg(a)-arg(b), we are likely to end up * with subtractions of arcTangent. To avoid that, we compute the argument(a/b) - * from the real and imaginary part of a/b. */ + * from the real and imaginary part of a/b. + * TODO: What about norm(a/b)? */ + //ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override; // Properties Type type() const override { return Type::Division; } @@ -57,8 +57,6 @@ public: Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; private: - // Complex - Expression complexPart(Context & context, Preferences::AngleUnit angleUnit, bool isReal) const; // Approximation template static Complex compute(const std::complex c, const std::complex d); template static MatrixComplex computeOnMatrixAndComplex(const MatrixComplex m, const std::complex c) { diff --git a/poincare/include/poincare/division_quotient.h b/poincare/include/poincare/division_quotient.h index 1a1b052cb..166b3d2c1 100644 --- a/poincare/include/poincare/division_quotient.h +++ b/poincare/include/poincare/division_quotient.h @@ -22,8 +22,7 @@ public: Type type() const override { return Type::DivisionQuotient; } // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/division_remainder.h b/poincare/include/poincare/division_remainder.h index c0a09c4e4..f7f93f467 100644 --- a/poincare/include/poincare/division_remainder.h +++ b/poincare/include/poincare/division_remainder.h @@ -23,8 +23,7 @@ public: Type type() const override { return Type::DivisionRemainder; } // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index db45bb33c..1f1904585 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -166,10 +166,8 @@ public: Expression defaultReplaceUnknown(const Symbol & symbol); /* Complex */ - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const { return node()->realPart(context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const { return node()->imaginaryPart(context, angleUnit); } - Expression complexNorm(Context & context, Preferences::AngleUnit angleUnit) const { return node()->complexNorm(context, angleUnit); } - Expression complexArgument(Context & context, Preferences::AngleUnit angleUnit) const { return node()->complexArgument(context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const; + ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const; /* Comparison */ /* isIdenticalTo is the "easy" equality, it returns true if both trees have diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index d3595c54c..39ba11fd5 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -14,6 +14,8 @@ namespace Poincare { class SymbolAbstract; class Symbol; +class ComplexCartesian; +class ComplexPolar; class ExpressionNode : public TreeNode { friend class AdditionNode; @@ -46,6 +48,8 @@ public: BinomialCoefficient, Ceiling, ComplexArgument, + ComplexCartesian, + ComplexPolar, Conjugate, Derivative, Determinant, @@ -116,10 +120,16 @@ public: bool isOfType(Type * types, int length) const; /* Complex */ - virtual Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const; - virtual Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const; - virtual Expression complexNorm(Context & context, Preferences::AngleUnit angleUnit) const; - virtual Expression complexArgument(Context & context, Preferences::AngleUnit angleUnit) const; + /* TODO: we could turn i in ComplexCartesian(0,1) in the shallowReduce applied + * to i. In this case, we would handle ComplexCartesian as a number and + * implement all computations (+, *, ^) in Number ?? We would have to handle + * ComplexCartesian in all Node::shallowReduce... We would then turn + * ComplexCartesian into something readable in the + * ComplexCartesian::shallowBeautify. This would enable us to do only one + * scan of the tree in ParseAndSimplifyForComplexFormat instead of Simplifying + * and then extracting ComplexCartesian. */ + virtual ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const; + virtual ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const; /* Simplification */ /* SimplificationOrder returns: diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index 62440a1b5..d7541205b 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -25,8 +25,7 @@ public: Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } private: // Layout bool childNeedsParenthesis(const TreeNode * child) const override; diff --git a/poincare/include/poincare/floor.h b/poincare/include/poincare/floor.h index 084683a78..5779a0fea 100644 --- a/poincare/include/poincare/floor.h +++ b/poincare/include/poincare/floor.h @@ -24,8 +24,7 @@ public: // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/frac_part.h b/poincare/include/poincare/frac_part.h index 4fd583323..45163bedd 100644 --- a/poincare/include/poincare/frac_part.h +++ b/poincare/include/poincare/frac_part.h @@ -24,8 +24,7 @@ public: // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/function.h b/poincare/include/poincare/function.h index c942bf062..95a57169b 100644 --- a/poincare/include/poincare/function.h +++ b/poincare/include/poincare/function.h @@ -28,8 +28,8 @@ public: float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override; // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override; - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override; + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; + ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override; private: char m_name[0]; // MUST be the last member variable diff --git a/poincare/include/poincare/great_common_divisor.h b/poincare/include/poincare/great_common_divisor.h index 7de2de838..dd3e6036b 100644 --- a/poincare/include/poincare/great_common_divisor.h +++ b/poincare/include/poincare/great_common_divisor.h @@ -21,8 +21,7 @@ public: // ExpressionNode Type type() const override { return Type::GreatCommonDivisor; } // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/imaginary_part.h b/poincare/include/poincare/imaginary_part.h index 80da8e387..b4d73573e 100644 --- a/poincare/include/poincare/imaginary_part.h +++ b/poincare/include/poincare/imaginary_part.h @@ -23,8 +23,7 @@ public: Type type() const override { return Type::ImaginaryPart; } // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/integral.h b/poincare/include/poincare/integral.h index 91848e280..3f0f4fee1 100644 --- a/poincare/include/poincare/integral.h +++ b/poincare/include/poincare/integral.h @@ -25,8 +25,7 @@ public: Expression replaceUnknown(const Symbol & symbol) override; // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/least_common_multiple.h b/poincare/include/poincare/least_common_multiple.h index 8ab9d7a41..e186a5faa 100644 --- a/poincare/include/poincare/least_common_multiple.h +++ b/poincare/include/poincare/least_common_multiple.h @@ -21,8 +21,7 @@ public: Type type() const override { return Type::LeastCommonMultiple; } // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } private: /* Layout */ Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/matrix_dimension.h b/poincare/include/poincare/matrix_dimension.h index 5e3555f2b..d54170778 100644 --- a/poincare/include/poincare/matrix_dimension.h +++ b/poincare/include/poincare/matrix_dimension.h @@ -22,8 +22,7 @@ public: Type type() const override { return Type::MatrixDimension; } // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 5ba4c954b..a06148859 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -26,12 +26,12 @@ public: int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const override; // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexCartesianPart(context, angleUnit, true); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexCartesianPart(context, angleUnit, false); } - Expression complexNorm(Context & context, Preferences::AngleUnit angleUnit) const override; + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; /* If we use the formula arg(a*b) = arg(a)+arg(b), we are likely to end up * with additions of arcTangent. To avoid that, we compute the argument(a*b) - * from the real and imaginary part of a*b. */ + * from the real and imaginary part of a*b. + * TODO: What about norm(a*b)? */ + //ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override; //Expression complexArgument(Context & context, Preferences::AngleUnit angleUnit) const override; // Approximation @@ -42,9 +42,6 @@ public: template static MatrixComplex computeOnMatrices(const MatrixComplex m, const MatrixComplex n); private: - // Complex - Expression complexCartesianPart(Context & context, Preferences::AngleUnit angleUnit, bool real) const; - // Property Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; diff --git a/poincare/include/poincare/nth_root.h b/poincare/include/poincare/nth_root.h index e16e7ddea..22caadc24 100644 --- a/poincare/include/poincare/nth_root.h +++ b/poincare/include/poincare/nth_root.h @@ -21,14 +21,10 @@ public: #endif // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartFromPolarParts(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartFromPolarParts(this, context, angleUnit); } - Expression complexNorm(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPolarPart(context, angleUnit, true); } - Expression complexArgument(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPolarPart(context, angleUnit, false); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianFromComplexPolar(this, context, angleUnit); } + ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override; private: - // Complex - Expression complexPolarPart(Context & context, Preferences::AngleUnit angleUnit, bool isNorm) const; // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/number.h b/poincare/include/poincare/number.h index 7e1041bad..a7242ea6f 100644 --- a/poincare/include/poincare/number.h +++ b/poincare/include/poincare/number.h @@ -24,8 +24,7 @@ public: double doubleApproximation() const; // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } }; class Number : public Expression { diff --git a/poincare/include/poincare/opposite.h b/poincare/include/poincare/opposite.h index 174a173dd..c14eb2d5a 100644 --- a/poincare/include/poincare/opposite.h +++ b/poincare/include/poincare/opposite.h @@ -28,8 +28,8 @@ public: Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override; // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexCartesianPart(context, angleUnit, true); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexCartesianPart(context, angleUnit, false); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; + ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override; // Approximation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { @@ -46,9 +46,6 @@ public: // Simplification Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; - -private: - Expression complexCartesianPart(Context & context, Preferences::AngleUnit angleUnit, bool real) const; }; class Opposite final : public Expression { diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index f29e10277..edfb3f17f 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -2,6 +2,8 @@ #define POINCARE_PARENTHESIS_H #include +#include +#include namespace Poincare { @@ -22,8 +24,8 @@ public: int polynomialDegree(Context & context, const char * symbolName) const override; // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return childAtIndex(0)->realPart(context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return childAtIndex(0)->imaginaryPart(context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return childAtIndex(0)->complexCartesian(context, angleUnit); } + ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override { return childAtIndex(0)->complexPolar(context, angleUnit); } // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/permute_coefficient.h b/poincare/include/poincare/permute_coefficient.h index a4477cdcc..a87a5b165 100644 --- a/poincare/include/poincare/permute_coefficient.h +++ b/poincare/include/poincare/permute_coefficient.h @@ -26,8 +26,7 @@ public: // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index a7fcf22eb..996260f6c 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -22,10 +22,8 @@ public: #endif // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartFromPolarParts(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartFromPolarParts(this, context, angleUnit); } - Expression complexNorm(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPolarPart(context, angleUnit, true); } - Expression complexArgument(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPolarPart(context, angleUnit, false); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianFromComplexPolar(this, context, angleUnit); } + ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override; // Properties Type type() const override { return Type::Power; } @@ -40,8 +38,6 @@ public: private: constexpr static int k_maxApproximatePowerMatrix = 1000; - // Complex - Expression complexPolarPart(Context & context, Preferences::AngleUnit angleUnit, bool norm) const; // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/prediction_interval.h b/poincare/include/poincare/prediction_interval.h index d1250e089..273eadaa2 100644 --- a/poincare/include/poincare/prediction_interval.h +++ b/poincare/include/poincare/prediction_interval.h @@ -21,8 +21,7 @@ public: // ExpressionNode // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } // Properties Type type() const override { return Type::PredictionInterval; } diff --git a/poincare/include/poincare/randint.h b/poincare/include/poincare/randint.h index 650648a5c..c42eb76cf 100644 --- a/poincare/include/poincare/randint.h +++ b/poincare/include/poincare/randint.h @@ -22,8 +22,7 @@ public: Type type() const override { return Type::Randint; } // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } private: // Layout diff --git a/poincare/include/poincare/random.h b/poincare/include/poincare/random.h index 9b218d408..e5ff18916 100644 --- a/poincare/include/poincare/random.h +++ b/poincare/include/poincare/random.h @@ -20,8 +20,7 @@ public: #endif // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } // Properties Type type() const override { return Type::Random; } diff --git a/poincare/include/poincare/real_part.h b/poincare/include/poincare/real_part.h index f1d99b93d..a376d5efc 100644 --- a/poincare/include/poincare/real_part.h +++ b/poincare/include/poincare/real_part.h @@ -23,8 +23,8 @@ public: Type type() const override { return Type::RealPart; } // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } + private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/round.h b/poincare/include/poincare/round.h index 4e798e5dd..8d2572c93 100644 --- a/poincare/include/poincare/round.h +++ b/poincare/include/poincare/round.h @@ -20,9 +20,7 @@ public: #endif // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } - + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } // Properties Type type() const override { return Type::Round; } diff --git a/poincare/include/poincare/sign_function.h b/poincare/include/poincare/sign_function.h index dbe336d2a..6c17d83a5 100644 --- a/poincare/include/poincare/sign_function.h +++ b/poincare/include/poincare/sign_function.h @@ -25,8 +25,7 @@ public: Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartRealFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartRealFunction(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } private: // Layout diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index afdf44bf0..044551f3d 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -21,8 +21,7 @@ public: #endif // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartOfComplexFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartOfComplexFunction(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianComplexFunction(this, context, angleUnit); } // Properties Type type() const override { return Type::Sine; } diff --git a/poincare/include/poincare/square_root.h b/poincare/include/poincare/square_root.h index a31f1baeb..872465227 100644 --- a/poincare/include/poincare/square_root.h +++ b/poincare/include/poincare/square_root.h @@ -3,6 +3,7 @@ #include #include +#include #include namespace Poincare { @@ -22,13 +23,16 @@ public: #endif // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPart(context, angleUnit, true); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPart(context, angleUnit, false); } - Expression complexNorm(Context & context, Preferences::AngleUnit angleUnit) const override; - //Expression complexArgument(Context & context, Preferences::AngleUnit angleUnit) const override; + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; + /* If we use the formula arg(sqrt(a)) = arg(a)/2, we are likely to end up + * with half arcTangent. To avoid that, we compute the argument(sqrt(a)) + * from the real and imaginary part of sqrt(a). + * TODO: What about norm(sqrt(a))? */ + //ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override; + private: - // Complex - Expression complexPart(Context & context, Preferences::AngleUnit angleUnit, bool isReal) const; + //Complex + static Multiplication complexCartesianHelper(Expression e, Context & context, Preferences::AngleUnit angleUnit); // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/subtraction.h b/poincare/include/poincare/subtraction.h index 9a03ff8cd..b0334b825 100644 --- a/poincare/include/poincare/subtraction.h +++ b/poincare/include/poincare/subtraction.h @@ -25,8 +25,7 @@ public: int polynomialDegree(Context & context, const char * symbolName) const override; // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPart(context, angleUnit, true); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return complexPart(context, angleUnit, false); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; // Approximation template static Complex compute(const std::complex c, const std::complex d) { return Complex(c - d); } @@ -46,9 +45,6 @@ public: Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; private: - // Complex - Expression complexPart(Context & context, Preferences::AngleUnit angleUnit, bool real) const; - /* Evaluation */ template static MatrixComplex computeOnMatrixAndComplex(const MatrixComplex m, const std::complex c) { return ApproximationHelper::ElementWiseOnMatrixComplexAndComplex(m, c, compute); diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index 2def334c4..ec529e55a 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -27,8 +27,8 @@ public: float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override; // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override; - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override; + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; + ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override; /* Layout */ Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/symbol_abstract.h b/poincare/include/poincare/symbol_abstract.h index b6656b9f0..97a264760 100644 --- a/poincare/include/poincare/symbol_abstract.h +++ b/poincare/include/poincare/symbol_abstract.h @@ -80,6 +80,8 @@ protected: SymbolAbstractNode * node() const { return static_cast(Expression::node()); } private: static Expression Expand(const SymbolAbstract & symbol, Context & context, bool clone); + static ComplexCartesian complexCartesian(const SymbolAbstract & symbol, Context & context, Preferences::AngleUnit angleUnit); + static ComplexPolar complexPolar(const SymbolAbstract & symbol, Context & context, Preferences::AngleUnit angleUnit); static size_t AlignedNodeSize(size_t nameLength, size_t nodeSize); }; diff --git a/poincare/include/poincare/tangent.h b/poincare/include/poincare/tangent.h index a97d08da2..901303708 100644 --- a/poincare/include/poincare/tangent.h +++ b/poincare/include/poincare/tangent.h @@ -24,8 +24,7 @@ public: float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override; // Complex - Expression realPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::realPartOfComplexFunction(this, context, angleUnit); } - Expression imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::imaginaryPartOfComplexFunction(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianComplexFunction(this, context, angleUnit); } private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/undefined.h b/poincare/include/poincare/undefined.h index c434f8630..6d3588686 100644 --- a/poincare/include/poincare/undefined.h +++ b/poincare/include/poincare/undefined.h @@ -17,8 +17,7 @@ public: #endif // Complex - using ExpressionNode::realPart; - using ExpressionNode::imaginaryPart; + using ExpressionNode::complexCartesian; // Properties Type type() const override { return Type::Undefined; } diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 4e2655683..0a27a5718 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -47,10 +47,12 @@ Expression AbsoluteValue::shallowReduce(Context & context, Preferences::AngleUni #endif #endif Expression c = childAtIndex(0); - Expression norm = c.complexNorm(context, angleUnit); - if (!norm.isUninitialized()) { - replaceWithInPlace(norm); - return norm.deepReduce(context, angleUnit, target); + ComplexPolar polar = c.complexPolar(context, angleUnit); + if (!polar.isUninitialized()) { + Expression n = polar.norm(); + replaceWithInPlace(n); + // We have to deepReduce because the complexPolar function returns an Expression reduced only BottomUp + return n.deepReduce(context, angleUnit, target); } return *this; } diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 5b613dde1..54ae2353a 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -29,18 +29,26 @@ int AdditionNode::getPolynomialCoefficients(Context & context, const char * symb // Private -Expression AdditionNode::complexPart(Context & context, Preferences::AngleUnit angleUnit, bool real) const { +ComplexCartesian AdditionNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { Expression e(this); - Addition result; + Addition real; + Addition imag; int nbOfChildren = e.numberOfChildren(); for (int i = 0; i < nbOfChildren; i++) { - Expression part = real ? e.childAtIndex(i).realPart(context, angleUnit) : e.childAtIndex(i).imaginaryPart(context, angleUnit); - if (part.isUninitialized()) { - return Expression(); + ComplexCartesian cartesianParts = e.childAtIndex(i).complexCartesian(context, angleUnit); + if (cartesianParts.isUninitialized()) { + return ComplexCartesian(); } - result.addChildAtIndexInPlace(part, result.numberOfChildren(), result.numberOfChildren()); + Expression a = cartesianParts.real(); + Expression b = cartesianParts.imag(); + assert(!a.isUninitialized() && !b.isUninitialized()); + real.addChildAtIndexInPlace(a, real.numberOfChildren(), real.numberOfChildren()); + imag.addChildAtIndexInPlace(b, imag.numberOfChildren(), imag.numberOfChildren()); } - return result.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); + return ComplexCartesian::Builder( + real.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + imag.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ); } // Layout diff --git a/poincare/src/complex_argument.cpp b/poincare/src/complex_argument.cpp index 01893996b..8e70e417c 100644 --- a/poincare/src/complex_argument.cpp +++ b/poincare/src/complex_argument.cpp @@ -43,10 +43,12 @@ Expression ComplexArgument::shallowReduce(Context & context, Preferences::AngleU return SimplificationHelper::Map(*this, context, angleUnit); } #endif - Expression arg = c.complexArgument(context, angleUnit); - if (!arg.isUninitialized()) { - replaceWithInPlace(arg); - return arg.deepReduce(context, angleUnit, target); + ComplexPolar polar = c.complexPolar(context, angleUnit); + if (!polar.isUninitialized()) { + Expression a = polar.arg(); + replaceWithInPlace(a); + // We have to deepReduce because the complexPolar function returns an Expression reduced only BottomUp + return a.deepReduce(context, angleUnit, target); } return *this; } diff --git a/poincare/src/complex_helper.cpp b/poincare/src/complex_helper.cpp index 4ccb4f423..f7de5efc2 100644 --- a/poincare/src/complex_helper.cpp +++ b/poincare/src/complex_helper.cpp @@ -1,42 +1,135 @@ #include +#include +#include #include -#include +#include +#include #include #include +#include +#include +#include +#include +#include namespace Poincare { -Expression ComplexHelper::cartesianPartOfComplexFunction(const ExpressionNode * node, Context & context, Preferences::AngleUnit angleUnit, bool real) { +ComplexCartesian ComplexHelper::complexCartesianComplexFunction(const ExpressionNode * node, Context & context, Preferences::AngleUnit angleUnit) { Expression e(node); - Expression opImaginaryPart = e.childAtIndex(0).imaginaryPart(context, angleUnit); - if (opImaginaryPart.isUninitialized() || opImaginaryPart.type() != ExpressionNode::Type::Rational || !static_cast(opImaginaryPart).isZero()) { - return Expression(); + ComplexCartesian complexChild = e.childAtIndex(0).complexCartesian(context, angleUnit); + if (complexChild.isUninitialized()) { + return ComplexCartesian(); } - if (real) { - return e.clone().deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); + Expression childImaginaryPart = complexChild.imag(); + assert(!childImaginaryPart.isUninitialized()); + if (childImaginaryPart.type() != ExpressionNode::Type::Rational || !static_cast(childImaginaryPart).isZero()) { + return ComplexCartesian(); } - return Rational(0); + return ComplexCartesian::Builder( + e.clone(), + Rational(0) + ); } -Expression ComplexHelper::imaginaryPartRealFunction(const ExpressionNode * e, Context & context, Preferences::AngleUnit angleUnit) { - return Rational(0); +ComplexCartesian ComplexHelper::complexCartesianRealFunction(const ExpressionNode * e, Context & context, Preferences::AngleUnit angleUnit) { + return ComplexCartesian::Builder( + Expression(e).clone(), + Rational(0) + ); } -Expression ComplexHelper::complexCartesianPartFromPolarParts(const ExpressionNode * node, Context & context, Preferences::AngleUnit angleUnit, bool isReal) { +Expression ComplexHelper::complexCartesianFromComplexPolarHelper(Expression norm, Expression trigo, Context & context, Preferences::AngleUnit angleUnit) { + return Multiplication(norm, trigo.shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation)).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); +} + +ComplexCartesian ComplexHelper::complexCartesianFromComplexPolar(const ExpressionNode * node, Context & context, Preferences::AngleUnit angleUnit) { Expression e(node); - Expression r = e.complexNorm(context, angleUnit); - Expression th = e.complexArgument(context, angleUnit); - if (r.isUninitialized() || th.isUninitialized()) { - return Expression(); + ComplexPolar polar = e.complexPolar(context, angleUnit); + if (polar.isUninitialized()) { + return ComplexCartesian(); } + Expression r = polar.norm(); + Expression th = polar.arg(); + assert(!r.isUninitialized() && !th.isUninitialized()); Expression argument = angleUnit == Preferences::AngleUnit::Radian ? th : th.radianToDegree(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); - Expression trigo; - if (isReal) { - trigo = Cosine::Builder(argument); - } else { - trigo = Sine::Builder(argument); + return ComplexCartesian::Builder( + complexCartesianFromComplexPolarHelper(r.clone(), Cosine::Builder(argument.clone()), context, angleUnit), + complexCartesianFromComplexPolarHelper(r, Sine::Builder(argument), context, angleUnit) + ); +} + +ComplexPolar ComplexHelper::complexPolarFromComplexCartesian(const ExpressionNode * node, Context & context, Preferences::AngleUnit angleUnit) { + Expression e(node); + ComplexCartesian cartesian = e.complexCartesian(context, angleUnit); + if (cartesian.isUninitialized()) { + return ComplexPolar(); } - return Multiplication(r, trigo.shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation)).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); + Expression a = cartesian.real(); + Expression b = cartesian.imag(); + assert(!a.isUninitialized() && !b.isUninitialized()); + // Step 1: find norm + Expression norm; + ExpressionNode::Sign s = e.sign(&context, angleUnit); + if (s == ExpressionNode::Sign::Positive) { + // Case 1: the expression is positive real + norm = e.clone(); + } else if (s == ExpressionNode::Sign::Negative) { + // Case 2: the argument is negative real + norm = e.clone().setSign(ExpressionNode::Sign::Positive, &context, angleUnit); + } else { + // Case 3: the argument is complex or of unknown approximation + // sqrt(a^2+b^2) + norm = SquareRoot::Builder( + Addition( + Power(a.clone(), Rational(2)).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation), + Power(b.clone(), Rational(2)).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); + } + // Step 2: find the argument + Expression argument; + float bApprox = b.approximateToScalar(context, angleUnit); + if (bApprox != 0.0f) { + // if b != 0, argument = sign(b) * Pi/2 - arctan(a/b) + // First, compute arctan(a/b) or (Pi/180)*arctan(a/b) + Expression arcTangent = ArcTangent::Builder(Division(a, b.clone()).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation)).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); + if (angleUnit == Preferences::AngleUnit::Degree) { + arcTangent = arcTangent.degreeToRadian(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); + } + // Then, compute sign(b) * Pi/2 - arctan(a/b) + argument = Subtraction( + Multiplication( + SignFunction::Builder(b).shallowReduce(context, angleUnit), + Division(Constant(Ion::Charset::SmallPi), Rational(2)).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation), + arcTangent + ).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); + } else { + // if b == 0, argument = (1-sign(a))*Pi/2 + argument = Multiplication( + Subtraction( + Rational(1), + SignFunction::Builder(a).shallowReduce(context, angleUnit) + ).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation), + Division(Constant(Ion::Charset::SmallPi), Rational(2)).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); + } + return ComplexPolar::Builder(norm, argument); + +} + +Expression ComplexHelper::complexSquareNormComplexCartesian(Expression real, Expression imag, Context & context, Preferences::AngleUnit angleUnit) { + assert(!real.isUninitialized() && !imag.isUninitialized()); + return Addition( + Power( + real, + Rational(2) + ).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation), + Power( + imag, + Rational(2) + ).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); } } diff --git a/poincare/src/conjugate.cpp b/poincare/src/conjugate.cpp index 2decdaf19..1ee35cf23 100644 --- a/poincare/src/conjugate.cpp +++ b/poincare/src/conjugate.cpp @@ -1,5 +1,9 @@ #include #include +#include +#include +#include +#include #include #include #include @@ -12,16 +16,26 @@ constexpr Expression::FunctionHelper Conjugate::s_functionHelper; int ConjugateNode::numberOfChildren() const { return Conjugate::s_functionHelper.numberOfChildren(); } -Expression ConjugateNode::realPart(Context & context, Preferences::AngleUnit angleUnit) const { - return childAtIndex(0)->realPart(context, angleUnit); +ComplexCartesian ConjugateNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { + ComplexCartesian childCartesian = childAtIndex(0)->complexCartesian(context, angleUnit); + if (childCartesian.isUninitialized()) { + return ComplexCartesian(); + } + return ComplexCartesian::Builder( + childCartesian.real(), + Multiplication(Rational(-1), childCartesian.imag()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ); } -Expression ConjugateNode::imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const { - Expression e = childAtIndex(0)->imaginaryPart(context, angleUnit); - if (!e.isUninitialized()) { - return Opposite(e).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); +ComplexPolar ConjugateNode::complexPolar(Context & context, Preferences::AngleUnit angleUnit) const { + ComplexPolar childPolar = childAtIndex(0)->complexPolar(context, angleUnit); + if (childPolar.isUninitialized()) { + return ComplexPolar(); } - return Expression(); + return ComplexPolar::Builder( + childPolar.norm(), + Multiplication(Rational(-1), childPolar.arg()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ); } Layout ConjugateNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { diff --git a/poincare/src/constant.cpp b/poincare/src/constant.cpp index 15fef166d..6a41326de 100644 --- a/poincare/src/constant.cpp +++ b/poincare/src/constant.cpp @@ -16,18 +16,11 @@ ExpressionNode::Sign ConstantNode::sign(Context * context, Preferences::AngleUni return Sign::Unknown; } -Expression ConstantNode::realPart(Context & context, Preferences::AngleUnit angleUnit) const { +ComplexCartesian ConstantNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { if (isIComplex()) { - return Rational(0); + return ComplexCartesian::Builder(Rational(0), Rational(1)); } - return Constant(this).clone(); -} - -Expression ConstantNode::imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const { - if (isIComplex()) { - return Rational(1); - } - return Rational(0); + return ComplexCartesian::Builder(Constant(this).clone(), Rational(0)); } Layout ConstantNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index b87dd0c71..56aa1d2af 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -46,7 +46,38 @@ Expression DivisionNode::shallowReduce(Context & context, Preferences::AngleUnit return Division(this).shallowReduce(context, angleUnit, target); } -Expression DivisionNode::complexNorm(Context & context, Preferences::AngleUnit angleUnit) const { +ComplexCartesian DivisionNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { + Division e(this); + ComplexCartesian cartesianChild0 = e.childAtIndex(0).complexCartesian(context, angleUnit); + ComplexCartesian cartesianChild1 = e.childAtIndex(1).complexCartesian(context, angleUnit); + if (cartesianChild0.isUninitialized() || cartesianChild1.isUninitialized()) { + return ComplexCartesian(); + } + Expression a = cartesianChild0.real(); + Expression b = cartesianChild0.imag(); + Expression c = cartesianChild1.real(); + Expression d = cartesianChild1.imag(); + assert(!a.isUninitialized() && !b.isUninitialized() && !c.isUninitialized() && !d.isUninitialized()); + Expression denominator = ComplexHelper::complexSquareNormComplexCartesian(c.clone(), d.clone(), context, angleUnit); + return ComplexCartesian::Builder( + Division( + Addition( + Multiplication(a.clone(), c.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Multiplication(b.clone(), d.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + denominator.clone() + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Division( + Subtraction( + Multiplication(b, c).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Multiplication(a, d).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + denominator + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ); +} + +/*ComplexPolar DivisionNode::complexPolar(Context & context, Preferences::AngleUnit angleUnit) const { Division d(this); Expression r0 = d.childAtIndex(0).complexNorm(context, angleUnit); Expression r1 = d.childAtIndex(1).complexNorm(context, angleUnit); @@ -54,44 +85,7 @@ Expression DivisionNode::complexNorm(Context & context, Preferences::AngleUnit a return Expression(); } return Division(r0,r1).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); -} - -Expression DivisionNode::complexPart(Context & context, Preferences::AngleUnit angleUnit, bool real) const { - Division e(this); - Expression a = e.childAtIndex(0).realPart(context, angleUnit); - Expression b = e.childAtIndex(0).imaginaryPart(context, angleUnit); - Expression c = e.childAtIndex(1).realPart(context, angleUnit); - Expression d = e.childAtIndex(1).imaginaryPart(context, angleUnit); - if (a.isUninitialized() || b.isUninitialized() || c.isUninitialized() || d.isUninitialized()) { - return Expression(); - } - Expression denominator = - Addition( - Power( - c.clone(), - Rational(2) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - Power( - d.clone(), - Rational(2) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); - if (real) { - return Division( - Addition( - Multiplication(a, c).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - Multiplication(b, d).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - denominator - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); - } - return Division( - Subtraction( - Multiplication(b, c).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - Multiplication(a, d).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - denominator).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); -} +}*/ template Complex DivisionNode::compute(const std::complex c, const std::complex d) { return Complex(c/d); diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index c66ccf34b..85cf6b69f 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -199,6 +199,16 @@ bool Expression::getLinearCoefficients(char * variables, int maxVariableSize, Ex return !isMultivariablePolynomial; } +/* Complex */ + +ComplexCartesian Expression::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { + return node()->complexCartesian(context, angleUnit); +} + +ComplexPolar Expression::complexPolar(Context & context, Preferences::AngleUnit angleUnit) const { + return node()->complexPolar(context, angleUnit); +} + // Private void Expression::defaultDeepReduceChildren(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { @@ -388,11 +398,18 @@ Expression Expression::simplifyForComplexFormat(Context & context, Preferences:: if (sSimplificationHasBeenInterrupted) { return Expression(); } - Expression ra = complexFormat == Preferences::ComplexFormat::Cartesian ? e.realPart(context, angleUnit) : e.complexNorm(context, angleUnit); - Expression tb = complexFormat == Preferences::ComplexFormat::Cartesian ? e.imaginaryPart(context, angleUnit) : e.complexArgument(context, angleUnit); - if (ra.isUninitialized() || tb.isUninitialized()) { + Expression complexParts = complexFormat == Preferences::ComplexFormat::Cartesian ? static_cast(e.complexCartesian(context, angleUnit)) : static_cast(e.complexPolar(context, angleUnit)); + if (complexParts.isUninitialized()) { return e; } + // Depending on the complexFormat required: + // - ra is the real part or the norm + // - tb is the imaginary part or the argument + assert(complexParts.type() == ExpressionNode::Type::ComplexCartesian || complexParts.type() == ExpressionNode::Type::ComplexPolar); + assert(complexParts.numberOfChildren() == 2); + Expression ra = complexParts.childAtIndex(0); + Expression tb = complexParts.childAtIndex(1); + assert(!ra.isUninitialized() && !tb.isUninitialized()); ra = ra.simplify(context, angleUnit); tb = tb.simplify(context, angleUnit); if (ra.isUninitialized() || tb.isUninitialized()) { diff --git a/poincare/src/expression_node.cpp b/poincare/src/expression_node.cpp index bb02fe3de..1f4fd19b2 100644 --- a/poincare/src/expression_node.cpp +++ b/poincare/src/expression_node.cpp @@ -2,6 +2,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -71,70 +74,12 @@ float ExpressionNode::characteristicXRange(Context & context, Preferences::Angle return range; } -Expression ExpressionNode::realPart(Context & context, Preferences::AngleUnit angleUnit) const { - return Expression(); +ComplexCartesian ExpressionNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { + return ComplexCartesian(); } -Expression ExpressionNode::imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const { - return Expression(); -} - -Expression ExpressionNode::complexNorm(Context & context, Preferences::AngleUnit angleUnit) const { - Expression e(this); - Sign s = sign(&context, angleUnit); - // Case 1: the expression is positive real - if (s == ExpressionNode::Sign::Positive) { - return e.clone(); - } - // Case 2: the argument is negative real - if (s == ExpressionNode::Sign::Negative) { - return e.clone().setSign(ExpressionNode::Sign::Positive, &context, angleUnit, ReductionTarget::BottomUpComputation); - } - // Case 3: the argument is complex or of unknown approximation - Expression a = realPart(context, angleUnit); - Expression b = imaginaryPart(context, angleUnit); - if (!a.isUninitialized() && !b.isUninitialized()) { - // sqrt(a^2+b^2) - return SquareRoot::Builder( - Addition( - Power(a, Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - Power(b, Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); - } - return Expression(); -} - -Expression ExpressionNode::complexArgument(Context & context, Preferences::AngleUnit angleUnit) const { - Expression a = realPart(context, angleUnit); - Expression b = imaginaryPart(context, angleUnit); - if (!a.isUninitialized() && !b.isUninitialized()) { - if (b.type() != Type::Rational || !static_cast(b).isZero()) { - // arctan(a/b) or (Pi/180)*arctan(a/b) - Expression arcTangent = ArcTangent::Builder(Division(a, b.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); - if (angleUnit == Preferences::AngleUnit::Degree) { - arcTangent = arcTangent.degreeToRadian(context, angleUnit, ReductionTarget::BottomUpComputation); - } - // sign(b) * Pi/2 - arctan(a/b) - return Subtraction( - Multiplication( - SignFunction::Builder(b).shallowReduce(context, angleUnit), - Division(Constant(Ion::Charset::SmallPi), Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - arcTangent - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); - } else { - // (1-sign(a))*Pi/2 - return Multiplication( - Subtraction( - Rational(1), - SignFunction::Builder(a).shallowReduce(context, angleUnit) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - Division(Constant(Ion::Charset::SmallPi), Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); - } - } - return Expression(); +ComplexPolar ExpressionNode::complexPolar(Context & context, Preferences::AngleUnit angleUnit) const { + return ComplexHelper::complexPolarFromComplexCartesian(this, context, angleUnit); } int ExpressionNode::SimplificationOrder(const ExpressionNode * e1, const ExpressionNode * e2, bool canBeInterrupted) { diff --git a/poincare/src/function.cpp b/poincare/src/function.cpp index f0770b2ab..9103f4a85 100644 --- a/poincare/src/function.cpp +++ b/poincare/src/function.cpp @@ -9,22 +9,14 @@ namespace Poincare { -Expression FunctionNode::realPart(Context & context, Preferences::AngleUnit angleUnit) const { +ComplexCartesian FunctionNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { Function f(this); - Expression e = SymbolAbstract::Expand(f, context, true); - if (e.isUninitialized()) { - return f.clone(); - } - return e.realPart(context, angleUnit); + return SymbolAbstract::complexCartesian(f, context, angleUnit); } -Expression FunctionNode::imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const { +ComplexPolar FunctionNode::complexPolar(Context & context, Preferences::AngleUnit angleUnit) const { Function f(this); - Expression e = SymbolAbstract::Expand(f, context, false); - if (e.isUninitialized()) { - return Rational(0); - } - return e.imaginaryPart(context, angleUnit); + return SymbolAbstract::complexPolar(f, context, angleUnit); } Expression FunctionNode::replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression) { diff --git a/poincare/src/imaginary_part.cpp b/poincare/src/imaginary_part.cpp index 9379d5ec4..4c7f494a4 100644 --- a/poincare/src/imaginary_part.cpp +++ b/poincare/src/imaginary_part.cpp @@ -41,9 +41,11 @@ Expression ImaginaryPart::shallowReduce(Context & context, Preferences::AngleUni replaceWithInPlace(result); return result; } - Expression im = c.imaginaryPart(context, angleUnit); - if (!im.isUninitialized()) { + ComplexCartesian cartesian = c.complexCartesian(context, angleUnit); + if (!cartesian.isUninitialized()) { + Expression im = cartesian.imag(); replaceWithInPlace(im); + // We have to deepReduce because the complexCartesian function returns an Expression reduced only BottomUp return im.deepReduce(context, angleUnit, target); } return *this; diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index ca4e9accd..aba35c0a9 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -31,21 +31,25 @@ ExpressionNode::Sign MultiplicationNode::sign(Context * context, Preferences::An return (Sign)sign; } -Expression MultiplicationNode::complexCartesianPart(Context & context, Preferences::AngleUnit angleUnit, bool realPart) const { +ComplexCartesian MultiplicationNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { Multiplication m(this); int nbChildren = m.numberOfChildren(); assert(nbChildren > 0); - Expression real = m.childAtIndex(0).realPart(context, angleUnit); - Expression imag = m.childAtIndex(0).imaginaryPart(context, angleUnit); + ComplexCartesian cartesian = m.childAtIndex(0).complexCartesian(context, angleUnit); + if (cartesian.isUninitialized()) { + return ComplexCartesian(); + } + Expression real = cartesian.real(); + Expression imag = cartesian.imag(); + assert(!real.isUninitialized() && !imag.isUninitialized()); for (int i = 1; i < nbChildren; i++) { - if (real.isUninitialized() || imag.isUninitialized()) { - return Expression(); - } - Expression childReal = m.childAtIndex(i).realPart(context, angleUnit); - Expression childImag = m.childAtIndex(i).imaginaryPart(context, angleUnit); - if (childReal.isUninitialized() || childImag.isUninitialized()) { - return Expression(); + ComplexCartesian childCartesian = m.childAtIndex(i).complexCartesian(context, angleUnit); + if (childCartesian.isUninitialized()) { + return ComplexCartesian(); } + Expression childReal = childCartesian.real(); + Expression childImag = childCartesian.imag(); + assert(!real.isUninitialized() && !imag.isUninitialized()); Expression newReal = Subtraction( Multiplication(real.clone(), childReal.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), @@ -59,10 +63,10 @@ Expression MultiplicationNode::complexCartesianPart(Context & context, Preferenc real = newReal; imag = newImag; } - return realPart ? real : imag; + return ComplexCartesian::Builder(real, imag); } -Expression MultiplicationNode::complexNorm(Context & context, Preferences::AngleUnit angleUnit) const { +/*Expression MultiplicationNode::complexNorm(Context & context, Preferences::AngleUnit angleUnit) const { Multiplication m(this); Multiplication norm; for (int i = 0; i < m.numberOfChildren(); i++) { @@ -75,7 +79,7 @@ Expression MultiplicationNode::complexNorm(Context & context, Preferences::Angle return norm.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } -/*Expression MultiplicationNode::complexArgument(Context & context, Preferences::AngleUnit angleUnit) const { +Expression MultiplicationNode::complexArgument(Context & context, Preferences::AngleUnit angleUnit) const { Multiplication m(this); Addition arg; for (int i = 0; i < m.numberOfChildren(); i++) { diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index 03af6b776..761c84ca2 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -18,40 +18,35 @@ constexpr Expression::FunctionHelper NthRoot::s_functionHelper; int NthRootNode::numberOfChildren() const { return NthRoot::s_functionHelper.numberOfChildren(); } -Expression NthRootNode::complexPolarPart(Context & context, Preferences::AngleUnit angleUnit, bool isNorm) const { +ComplexPolar NthRootNode::complexPolar(Context & context, Preferences::AngleUnit angleUnit) const { NthRoot e(this); - // NthRoot(r*e^(i*th), c+id) - Expression r = e.childAtIndex(0).complexNorm(context, angleUnit); - Expression th = e.childAtIndex(0).complexArgument(context, angleUnit); - Expression c = e.childAtIndex(1).realPart(context, angleUnit); - Expression d = e.childAtIndex(1).imaginaryPart(context, angleUnit); - if (r.isUninitialized() || th.isUninitialized() || c.isUninitialized() || d.isUninitialized()) { - return Expression(); + ComplexPolar polarChild0 = e.childAtIndex(0).complexPolar(context, angleUnit); + ComplexCartesian cartesianChild1 = e.childAtIndex(0).complexCartesian(context, angleUnit); + if (polarChild0.isUninitialized() || cartesianChild1.isUninitialized()) { + return ComplexPolar(); } - Expression denominator = - Addition( - Power(c.clone(), Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - Power(d.clone(), Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); - if (isNorm) { - // R = e^((c*ln(r)+th*d)/(c^2+d^2)) - // R = r^(c/(c^2+d^2))*e^(th*d/(c^2+d^2)) - return Multiplication( + // NthRoot(r*e^(i*th), c+id) + Expression r = polarChild0.norm(); + Expression th = polarChild0.arg(); + Expression c = cartesianChild1.real(); + Expression d = cartesianChild1.imag(); + assert(!r.isUninitialized() && !th.isUninitialized() && !c.isUninitialized() && !d.isUninitialized()); + Expression denominator = ComplexHelper::complexSquareNormComplexCartesian(c.clone(), d.clone(), context, angleUnit); + // R = r^(c/(c^2+d^2))*e^(th*d/(c^2+d^2)) + Expression norm = Multiplication( Power( - r, - Division(c, denominator.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + r.clone(), + Division(c.clone(), denominator.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), Power( Constant(Ion::Charset::Exponential), Division( - Multiplication(d, th).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - denominator) + Multiplication(d.clone(), th.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + denominator.clone()) ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); - //return Power(Constant(Ion::Charset::Exponential), Division(Addition(Multiplication(c, NaperianLogarithm::Builder(r)), Multiplication(d, th)), denominator)); - } else { - // TH = (th*c-d*ln(r))/(c^2+d^2) - return Division( + // TH = (th*c-d*ln(r))/(c^2+d^2) + Expression argument = Division( Subtraction( Multiplication(th, c).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), Multiplication( @@ -61,7 +56,7 @@ Expression NthRootNode::complexPolarPart(Context & context, Preferences::AngleUn ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), denominator ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); - } + return ComplexPolar::Builder(norm, argument); } Layout NthRootNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index 489beac27..aa23e6878 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -1,5 +1,7 @@ #include +#include #include +#include #include #include #include @@ -27,12 +29,26 @@ ExpressionNode::Sign OppositeNode::sign(Context * context, Preferences::AngleUni return ExpressionNode::sign(context,angleUnit); } -Expression OppositeNode::complexCartesianPart(Context & context, Preferences::AngleUnit angleUnit, bool real) const { - Expression a = real ? childAtIndex(0)->realPart(context, angleUnit) : childAtIndex(0)->imaginaryPart(context, angleUnit); - if (a.isUninitialized()) { - return Expression(); +ComplexCartesian OppositeNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { + ComplexCartesian childCartesian = childAtIndex(0)->complexCartesian(context, angleUnit); + if (childCartesian.isUninitialized()) { + return ComplexCartesian(); } - return Opposite(a).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); + return ComplexCartesian::Builder( + Multiplication(Rational(-1), childCartesian.real()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Multiplication(Rational(-1), childCartesian.imag()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ); +} + +ComplexPolar OppositeNode::complexPolar(Context & context, Preferences::AngleUnit angleUnit) const { + ComplexPolar childPolar = childAtIndex(0)->complexPolar(context, angleUnit); + if (childPolar.isUninitialized()) { + return ComplexPolar(); + } + return ComplexPolar::Builder( + childPolar.norm(), + Addition(childPolar.arg(), Constant(Ion::Charset::SmallPi)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ); } /* Layout */ diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index fbcac4be8..97eb9d6fa 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -81,36 +81,35 @@ int PowerNode::getPolynomialCoefficients(Context & context, const char * symbolN // Private -Expression PowerNode::complexPolarPart(Context & context, Preferences::AngleUnit angleUnit, bool norm) const { +ComplexPolar PowerNode::complexPolar(Context & context, Preferences::AngleUnit angleUnit) const { Power p(this); - // Power(r*e^(i*th), c+id) - Expression r = p.childAtIndex(0).complexNorm(context, angleUnit); - Expression th = p.childAtIndex(0).complexArgument(context, angleUnit); - Expression c = p.childAtIndex(1).realPart(context, angleUnit); - Expression d = p.childAtIndex(1).imaginaryPart(context, angleUnit); - if (r.isUninitialized() || th.isUninitialized() || c.isUninitialized() || d.isUninitialized()) { - return Expression(); + ComplexPolar polarChild0 = p.childAtIndex(0).complexPolar(context, angleUnit); + ComplexCartesian cartesianChild1 = p.childAtIndex(1).complexCartesian(context, angleUnit); + if (polarChild0.isUninitialized() || cartesianChild1.isUninitialized()) { + return ComplexPolar(); } - if (norm) { - // R = e^(c*ln(r)-th*d) - // R = r^c*e^(-th*d) - return Multiplication( - Power(r, c).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + // Power(r*e^(i*th), c+id) + Expression r = polarChild0.norm(); + Expression th = polarChild0.arg(); + Expression c = cartesianChild1.real(); + Expression d = cartesianChild1.imag(); + // R = r^c*e^(-th*d) + Expression norm = Multiplication( + Power(r.clone(), c.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), Power( Constant(Ion::Charset::Exponential), - Multiplication(Rational(-1), th, d).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + Multiplication(Rational(-1), th.clone(), d.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); - } else { - // TH = d*ln(r)+c*th - return Addition( + // TH = d*ln(r)+c*th + Expression argument = Addition( Multiplication(th, c).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), Multiplication( d, NaperianLogarithm::Builder(r).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); - } + return ComplexPolar::Builder(norm, argument); } template diff --git a/poincare/src/real_part.cpp b/poincare/src/real_part.cpp index e599dce38..696a09f61 100644 --- a/poincare/src/real_part.cpp +++ b/poincare/src/real_part.cpp @@ -40,9 +40,11 @@ Expression RealPart::shallowReduce(Context & context, Preferences::AngleUnit ang replaceWithInPlace(c); return c; } - Expression re = c.realPart(context, angleUnit); - if (!re.isUninitialized()) { + ComplexCartesian cartesian = c.complexCartesian(context, angleUnit); + if (!cartesian.isUninitialized()) { + Expression re = cartesian.real(); replaceWithInPlace(re); + // We have to deepReduce because the complexCartesian function returns an Expression reduced only BottomUp return re.deepReduce(context, angleUnit, target); } return *this; diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index 5d763c27b..a42e94719 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -18,14 +18,14 @@ constexpr Expression::FunctionHelper SquareRoot::s_functionHelper; int SquareRootNode::numberOfChildren() const { return SquareRoot::s_functionHelper.numberOfChildren(); } -Expression SquareRootNode::complexNorm(Context & context, Preferences::AngleUnit angleUnit) const { +/*Expression SquareRootNode::complexNorm(Context & context, Preferences::AngleUnit angleUnit) const { Expression r = childAtIndex(0)->complexNorm(context, angleUnit); if (r.isUninitialized()) { return Expression(); } // R = sqrt(r) return SquareRoot::Builder(r).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); -} +}*/ /*Expression SquareRootNode::complexArgument(Context & context, Preferences::AngleUnit angleUnit) const { Expression th = childAtIndex(0)->complexArgument(context, angleUnit); @@ -36,32 +36,37 @@ Expression SquareRootNode::complexNorm(Context & context, Preferences::AngleUnit return Division(th, Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); }*/ -Expression SquareRootNode::complexPart(Context & context, Preferences::AngleUnit angleUnit, bool real) const { - // real: (1/2)*sqrt(2*(sqrt(x^2+y^2)+x)) - // imag: (1/2)*sqrt(2*(sqrt(x^2+y^2)-x)*sign(y)) - SquareRoot e(this); - Expression x = e.childAtIndex(0).realPart(context, angleUnit); - Expression y = e.childAtIndex(0).imaginaryPart(context, angleUnit); - Expression norm = e.childAtIndex(0).complexNorm(context, angleUnit); - if (x.isUninitialized() || y.isUninitialized()) { - return Expression(); - } - // a = sqrt(x^2+y^2)+x or - Expression a = real ? static_cast(Addition(norm, x)) : static_cast(Subtraction(norm, x)); - Multiplication res = - Multiplication( +Multiplication SquareRootNode::complexCartesianHelper(Expression e, Context & context, Preferences::AngleUnit angleUnit) { + return Multiplication( Rational(1,2), SquareRoot::Builder( Multiplication( Rational(2), - a.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + e.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) ); - if (!real) { - res.addChildAtIndexInPlace(SignFunction::Builder(y).shallowReduce(context, angleUnit), res.numberOfChildren(), res.numberOfChildren()); +} +ComplexCartesian SquareRootNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { + // real: (1/2)*sqrt(2*(sqrt(x^2+y^2)+x)) + // imag: (1/2)*sqrt(2*(sqrt(x^2+y^2)-x)*sign(y)) + SquareRoot e(this); + ComplexCartesian cartesian = e.childAtIndex(0).complexCartesian(context, angleUnit); + if (cartesian.isUninitialized()) { + return ComplexCartesian(); } - return res.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); + Expression x = cartesian.real(); + Expression y = cartesian.imag(); + assert(!x.isUninitialized() && !y.isUninitialized()); + Expression norm = SquareRoot::Builder(ComplexHelper::complexSquareNormComplexCartesian(x.clone(), y.clone(), context, angleUnit)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); + // a = sqrt(x^2+y^2)+x + Multiplication real = complexCartesianHelper(Addition(norm.clone(), x.clone()), context, angleUnit); + Multiplication imag = complexCartesianHelper(Subtraction(norm, x), context, angleUnit); + imag.addChildAtIndexInPlace(SignFunction::Builder(y).shallowReduce(context, angleUnit), imag.numberOfChildren(), imag.numberOfChildren()); + return ComplexCartesian::Builder( + real.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + imag.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ); } Layout SquareRootNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index d3ae99576..541fec2b8 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -23,14 +23,17 @@ int SubtractionNode::polynomialDegree(Context & context, const char * symbolName // Private -Expression SubtractionNode::complexPart(Context & context, Preferences::AngleUnit angleUnit, bool real) const { +ComplexCartesian SubtractionNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { Subtraction e(this); - Expression a0 = real ? e.childAtIndex(0).realPart(context, angleUnit) : e.childAtIndex(0).imaginaryPart(context, angleUnit); - Expression a1 = real ? e.childAtIndex(1).realPart(context, angleUnit) : e.childAtIndex(1).imaginaryPart(context, angleUnit); - if (a0.isUninitialized() || a1.isUninitialized()) { - return Expression(); + ComplexCartesian cartesian0 = e.childAtIndex(0).complexCartesian(context, angleUnit); + ComplexCartesian cartesian1 = e.childAtIndex(1).complexCartesian(context, angleUnit); + if (cartesian0.isUninitialized() || cartesian1.isUninitialized()) { + return ComplexCartesian(); } - return Subtraction(a0, a1).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); + return ComplexCartesian::Builder( + Subtraction(cartesian0.real(), cartesian1.real()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Subtraction(cartesian0.imag(), cartesian1.imag()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ); } bool SubtractionNode::childNeedsParenthesis(const TreeNode * child) const { diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 89739f680..1e171fe8d 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -77,22 +77,14 @@ float SymbolNode::characteristicXRange(Context & context, Preferences::AngleUnit return 0.0f; } -Expression SymbolNode::realPart(Context & context, Preferences::AngleUnit angleUnit) const { +ComplexCartesian SymbolNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { Symbol s(this); - Expression e = SymbolAbstract::Expand(s, context, false); - if (e.isUninitialized()) { - return s.clone(); - } - return e.realPart(context, angleUnit); + return SymbolAbstract::complexCartesian(s, context, angleUnit); } -Expression SymbolNode::imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const { - Symbol s(this); - Expression e = SymbolAbstract::Expand(s, context, false); - if (e.isUninitialized()) { - return Rational(0); - } - return e.imaginaryPart(context, angleUnit); +ComplexPolar SymbolNode::complexPolar(Context & context, Preferences::AngleUnit angleUnit) const { + Symbol f(this); + return SymbolAbstract::complexPolar(f, context, angleUnit); } Layout SymbolNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { diff --git a/poincare/src/symbol_abstract.cpp b/poincare/src/symbol_abstract.cpp index fa9576989..faea41a33 100644 --- a/poincare/src/symbol_abstract.cpp +++ b/poincare/src/symbol_abstract.cpp @@ -1,4 +1,7 @@ #include +#include +#include +#include #include #include #include @@ -77,6 +80,23 @@ Expression SymbolAbstract::Expand(const SymbolAbstract & symbol, Context & conte return e; } +ComplexCartesian SymbolAbstract::complexCartesian(const SymbolAbstract & symbol, Context & context, Preferences::AngleUnit angleUnit) { + Expression e = SymbolAbstract::Expand(symbol, context, true); + if (e.isUninitialized()) { + return ComplexCartesian::Builder(symbol.clone(), Rational(0)); + } + return e.complexCartesian(context, angleUnit); +} + +ComplexPolar SymbolAbstract::complexPolar(const SymbolAbstract & symbol, Context & context, Preferences::AngleUnit angleUnit) { + Expression e = SymbolAbstract::Expand(symbol, context, true); + if (e.isUninitialized()) { + // sqrt(f(x)^2)*exp((1-sign(f(x))*Pi/2) + return ComplexHelper::complexPolarFromComplexCartesian(symbol.node(), context, angleUnit); + } + return e.complexPolar(context, angleUnit); +} + /* TreePool uses adresses and sizes that are multiples of 4 in order to make * node moves faster.*/ size_t SymbolAbstract::AlignedNodeSize(size_t nameLength, size_t nodeSize) { diff --git a/poincare/src/tree_pool.cpp b/poincare/src/tree_pool.cpp index 35a6ab825..4cb9f9486 100644 --- a/poincare/src/tree_pool.cpp +++ b/poincare/src/tree_pool.cpp @@ -221,6 +221,8 @@ template CeilingNode * Poincare::TreePool::createTreeNode(size_t si template OppositeNode * Poincare::TreePool::createTreeNode(size_t size); template PowerNode * Poincare::TreePool::createTreeNode(size_t size); template ComplexArgumentNode * Poincare::TreePool::createTreeNode(size_t size); +template ComplexCartesianNode * Poincare::TreePool::createTreeNode(size_t size); +template ComplexPolarNode * Poincare::TreePool::createTreeNode(size_t size); template ConfidenceIntervalNode * Poincare::TreePool::createTreeNode(size_t size); template ConjugateNode * Poincare::TreePool::createTreeNode(size_t size); template ConstantNode * Poincare::TreePool::createTreeNode(size_t size); diff --git a/poincare/test/complex.cpp b/poincare/test/complex.cpp index e86e56afb..51ae0acba 100644 --- a/poincare/test/complex.cpp +++ b/poincare/test/complex.cpp @@ -8,39 +8,31 @@ using namespace Poincare; void assert_expression_has_complex_cartesian_parts(const char * expression, const char * real, const char * imag, Preferences::AngleUnit angleUnit = Degree) { Shared::GlobalContext context; - Expression e = parse_expression(expression); - Expression r = e.realPart(context, angleUnit); - if (r.isUninitialized()) { + Expression e = parse_expression(expression).simplify(context, angleUnit); + ComplexCartesian cartesian = e.complexCartesian(context, angleUnit); + if (cartesian.isUninitialized()) { assert(real == nullptr); - } else { - r = r.simplify(context, angleUnit); - assert_parsed_expression_serialize_to(r, real); - } - Expression i = e.imaginaryPart(context, angleUnit); - if (i.isUninitialized()) { assert(imag == nullptr); } else { - i = i.simplify(context, angleUnit); - assert_parsed_expression_serialize_to(i, imag); + cartesian.real().simplify(context, angleUnit); + cartesian.imag().simplify(context, angleUnit); + assert_parsed_expression_serialize_to(cartesian.real(), real); + assert_parsed_expression_serialize_to(cartesian.imag(), imag); } } void assert_expression_has_complex_polar_parts(const char * expression, const char * norm, const char * arg, Preferences::AngleUnit angleUnit = Degree) { Shared::GlobalContext context; - Expression e = parse_expression(expression); - Expression n = e.complexNorm(context, angleUnit); - if (n.isUninitialized()) { + Expression e = parse_expression(expression).simplify(context, angleUnit); + ComplexPolar polar = e.complexPolar(context, angleUnit); + if (polar.isUninitialized()) { assert(norm == nullptr); - } else { - n = n.simplify(context, angleUnit); - assert_parsed_expression_serialize_to(n, norm); - } - Expression a = e.complexArgument(context, angleUnit); - if (a.isUninitialized()) { assert(arg == nullptr); } else { - a = a.simplify(context, angleUnit); - assert_parsed_expression_serialize_to(a, arg); + polar.norm().simplify(context, angleUnit); + polar.arg().simplify(context, angleUnit); + assert_parsed_expression_serialize_to(polar.norm(), norm); + assert_parsed_expression_serialize_to(polar.arg(), arg); } } From 7d9c49919c45be396762468152a2a5c8bb9d0a3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 11 Dec 2018 11:54:20 +0100 Subject: [PATCH 087/373] [poincare] simplifyForComplexFormat: before extracting ComplexCartesian/ComplexPolar, deepReduce instead of simplify to avoid generating uselessly big trees. To make it work, implement shortcuts for Power::complexCartesian and Power::complexPolar to return nice cartesian expression when the power index is -1, 1/2 or -1/2 --- poincare/include/poincare/power.h | 3 ++- poincare/src/expression.cpp | 9 ++++----- poincare/src/power.cpp | 28 ++++++++++++++++++++++++++++ poincare/test/complex.cpp | 2 +- 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 996260f6c..f5bd315fb 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -22,7 +22,7 @@ public: #endif // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianFromComplexPolar(this, context, angleUnit); } + ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override; // Properties @@ -89,6 +89,7 @@ private: Expression removeSquareRootsFromDenominator(Context & context, Preferences::AngleUnit angleUnit); bool parentIsALogarithmOfSameBase() const; bool isNthRootOfUnity() const; + Expression equivalentExpressionUsingStandardExpression() const; static Expression CreateComplexExponent(const Expression & r); // Returns e^(i*pi*r) static bool TermIsARationalSquareRootOrRational(const Expression& e); static const Rational RadicandInExpression(const Expression & e); diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 85cf6b69f..d372d96d3 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -392,15 +392,14 @@ bool isMinusOne(const Expression e) { Expression Expression::simplifyForComplexFormat(Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) { sSimplificationHasBeenInterrupted = false; - // We simplify before extracting the real and imaginary part to develop expression of type (a+b*i)^3 for example - // We could have deepReduce the expression but we want to keep division which are easier to extract complex parts from - Expression e = simplify(context, angleUnit); + // We deepReduce before extracting the real and imaginary part to develop expression of type (a+b*i)^3 for example + Expression e = deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); if (sSimplificationHasBeenInterrupted) { return Expression(); } Expression complexParts = complexFormat == Preferences::ComplexFormat::Cartesian ? static_cast(e.complexCartesian(context, angleUnit)) : static_cast(e.complexPolar(context, angleUnit)); if (complexParts.isUninitialized()) { - return e; + return e.simplify(context, angleUnit); } // Depending on the complexFormat required: // - ra is the real part or the norm @@ -413,7 +412,7 @@ Expression Expression::simplifyForComplexFormat(Context & context, Preferences:: ra = ra.simplify(context, angleUnit); tb = tb.simplify(context, angleUnit); if (ra.isUninitialized() || tb.isUninitialized()) { - return e; + return e.simplify(context, angleUnit); } e = CreateComplexExpression(ra, tb, complexFormat, ra.type() == ExpressionNode::Type::Undefined || tb.type() == ExpressionNode::Type::Undefined, diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 97eb9d6fa..e5845c1f3 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -81,8 +81,21 @@ int PowerNode::getPolynomialCoefficients(Context & context, const char * symbolN // Private +ComplexCartesian PowerNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { + Power p(this); + Expression e = p.equivalentExpressionUsingStandardExpression(); + if (!e.isUninitialized()) { + return e.complexCartesian(context, angleUnit); + } + return ComplexHelper::complexCartesianFromComplexPolar(this, context, angleUnit); +} + ComplexPolar PowerNode::complexPolar(Context & context, Preferences::AngleUnit angleUnit) const { Power p(this); + Expression e = p.equivalentExpressionUsingStandardExpression(); + if (!e.isUninitialized()) { + return e.complexPolar(context, angleUnit); + } ComplexPolar polarChild0 = p.childAtIndex(0).complexPolar(context, angleUnit); ComplexCartesian cartesianChild1 = p.childAtIndex(1).complexCartesian(context, angleUnit); if (polarChild0.isUninitialized() || cartesianChild1.isUninitialized()) { @@ -1026,6 +1039,21 @@ bool Power::isNthRootOfUnity() const { return false; } +Expression Power::equivalentExpressionUsingStandardExpression() const { + if (childAtIndex(1).type() == ExpressionNode::Type::Rational) { + if (childAtIndex(1).convert().isMinusOne()) { + return Division(Rational(1), childAtIndex(0).clone()); + } + if (childAtIndex(1).convert().isHalf()) { + return SquareRoot::Builder(childAtIndex(0).clone()); + } + if (childAtIndex(1).convert().isMinusHalf()) { + return Division(Rational(1), SquareRoot::Builder(childAtIndex(0).clone())); + } + } + return Expression(); +} + Expression Power::CreateComplexExponent(const Expression & r) { // Returns e^(i*pi*r) const Constant exp = Constant(Ion::Charset::Exponential); diff --git a/poincare/test/complex.cpp b/poincare/test/complex.cpp index 51ae0acba..2fb3a7d5f 100644 --- a/poincare/test/complex.cpp +++ b/poincare/test/complex.cpp @@ -8,7 +8,7 @@ using namespace Poincare; void assert_expression_has_complex_cartesian_parts(const char * expression, const char * real, const char * imag, Preferences::AngleUnit angleUnit = Degree) { Shared::GlobalContext context; - Expression e = parse_expression(expression).simplify(context, angleUnit); + Expression e = parse_expression(expression).reduce(context, angleUnit); ComplexCartesian cartesian = e.complexCartesian(context, angleUnit); if (cartesian.isUninitialized()) { assert(real == nullptr); From 2e89f8b7ded33222732b001488d310e34db2272f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 11 Dec 2018 17:57:19 +0100 Subject: [PATCH 088/373] [poincare] Expression::simplifyForComplexFormat: Use a shortcut if the expression approximation is a real pure --- poincare/include/poincare/expression.h | 1 + poincare/src/expression.cpp | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 1f1904585..0b360d769 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -166,6 +166,7 @@ public: Expression defaultReplaceUnknown(const Symbol & symbol); /* Complex */ + bool isPureReal(Context & context, Preferences::AngleUnit angleUnit) const; ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const; ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const; diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index d372d96d3..5ee49e48c 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -201,6 +201,16 @@ bool Expression::getLinearCoefficients(char * variables, int maxVariableSize, Ex /* Complex */ +bool Expression::isPureReal(Context & context, Preferences::AngleUnit angleUnit) const { + Evaluation approx = approximateToEvaluation(context, angleUnit); + if (approx.type() == EvaluationNode::Type::Complex) { + Complex approxComplex = static_cast&>(approx); + return approxComplex.imag() == 0.0f; + } + // TODO: matrix are not reduced yet so isPureReal is dummy if the approximation is a matrix + return true; +} + ComplexCartesian Expression::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { return node()->complexCartesian(context, angleUnit); } @@ -392,6 +402,9 @@ bool isMinusOne(const Expression e) { Expression Expression::simplifyForComplexFormat(Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) { sSimplificationHasBeenInterrupted = false; + if (isPureReal(context, angleUnit)) { + return simplify(context, angleUnit); + } // We deepReduce before extracting the real and imaginary part to develop expression of type (a+b*i)^3 for example Expression e = deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); if (sSimplificationHasBeenInterrupted) { From 2fe8b386c3cc2d501a604798d346124df081f572 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 12 Dec 2018 10:46:39 +0100 Subject: [PATCH 089/373] [poincare] Add tests on Complex --- poincare/test/complex.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/poincare/test/complex.cpp b/poincare/test/complex.cpp index 2fb3a7d5f..15f460e84 100644 --- a/poincare/test/complex.cpp +++ b/poincare/test/complex.cpp @@ -141,4 +141,22 @@ QUIZ_CASE(poincare_complex_parts) { assert_expression_has_complex_polar_parts("I", "1", "P/2"); assert_expression_has_complex_polar_parts("abs(-3)", "3", "0"); assert_expression_has_complex_polar_parts("abs(-3+I)", "R(10)", "0"); + assert_expression_has_complex_polar_parts("conj(2*X^(I*cos(2)))", "2", "-cos(2)"); + assert_expression_has_complex_polar_parts("-2*X^(I*cos(2))", "2", "cos(2)+P"); + + // User defined variable + assert_expression_has_complex_polar_parts("a", "R(a^2)", "(P-sign(a)*P)/2"); + // a = 2+i + assert_simplify("2+I>a"); + assert_expression_has_complex_polar_parts("a", "R(5", "(-2*atan(2)+P)/2"); + // Clean the storage for other tests + Ion::Storage::sharedStorage()->recordNamed("a.exp").destroy(); + // User defined function + assert_expression_has_complex_polar_parts("f(3)", "R(f(3)^2)", "(P-sign(f(3))*P)/2"); + // f: x -> x+1 + assert_simplify("x+1+I>f(x)"); + assert_expression_has_complex_polar_parts("f(3)", "R(17)", "(-2*atan(4)+P)/2"); + // Clean the storage for other tests + Ion::Storage::sharedStorage()->recordNamed("f.func").destroy(); + } From 9efc9e02e6f7781b14a110c21de606a608f4de58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 13 Dec 2018 10:49:03 +0100 Subject: [PATCH 090/373] [poincare] Revert simplifyForComplexFormat --- apps/calculation/calculation.cpp | 2 +- apps/shared/poincare_helpers.h | 4 -- poincare/include/poincare/expression.h | 5 +-- poincare/src/expression.cpp | 61 +------------------------- 4 files changed, 4 insertions(+), 68 deletions(-) diff --git a/apps/calculation/calculation.cpp b/apps/calculation/calculation.cpp index da4f1319a..7f07d3ed1 100644 --- a/apps/calculation/calculation.cpp +++ b/apps/calculation/calculation.cpp @@ -48,7 +48,7 @@ void Calculation::setContent(const char * c, Context * context, Expression ansEx * to keep Ans symbol in the calculation store. */ PoincareHelpers::Serialize(input, m_inputText, sizeof(m_inputText)); } - Expression exactOutput = PoincareHelpers::ParseAndSimplifyForComplexFormat(m_inputText, *context); + Expression exactOutput = PoincareHelpers::ParseAndSimplify(m_inputText, *context); PoincareHelpers::Serialize(exactOutput, m_exactOutputText, sizeof(m_exactOutputText)); Expression approximateOutput = PoincareHelpers::Approximate(exactOutput, *context); PoincareHelpers::Serialize(approximateOutput, m_approximateOutputText, sizeof(m_approximateOutputText)); diff --git a/apps/shared/poincare_helpers.h b/apps/shared/poincare_helpers.h index e57f89d2b..a9a2b9ef6 100644 --- a/apps/shared/poincare_helpers.h +++ b/apps/shared/poincare_helpers.h @@ -41,10 +41,6 @@ inline Poincare::Expression ParseAndSimplify(const char * text, Poincare::Contex return Poincare::Expression::ParseAndSimplify(text, context, Poincare::Preferences::sharedPreferences()->angleUnit()); } -inline Poincare::Expression ParseAndSimplifyForComplexFormat(const char * text, Poincare::Context & context) { - return Poincare::Expression::ParseAndSimplifyForComplexFormat(text, context, Poincare::Preferences::sharedPreferences()->angleUnit(), Poincare::Preferences::sharedPreferences()->complexFormat()); -} - inline void Simplify(Poincare::Expression * e, Poincare::Context & context) { *e = e->simplify(context, Poincare::Preferences::sharedPreferences()->angleUnit()); } diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 0b360d769..c42ef1578 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -182,8 +182,7 @@ public: int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const; /* Simplification */ - static Expression ParseAndSimplify(const char * text, Context & context, Preferences::AngleUnit angleUnit) { return ParseAndProcess(text, context, angleUnit, Preferences::ComplexFormat::Cartesian, false); } - static Expression ParseAndSimplifyForComplexFormat(const char * text, Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) { return ParseAndProcess(text, context, angleUnit, complexFormat, true); } + static Expression ParseAndSimplify(const char * text, Context & context, Preferences::AngleUnit angleUnit); Expression simplify(Context & context, Preferences::AngleUnit angleUnit); Expression reduce(Context & context, Preferences::AngleUnit angleUnit); static Expression ExpressionWithoutSymbols(Expression expressionWithSymbols, Context & context); @@ -284,8 +283,6 @@ private: static constexpr int k_maxSymbolReplacementsCount = 10; static bool sSymbolReplacementsCountLock; /* Simplification */ - static Expression ParseAndProcess(const char * text, Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat, bool complexSimplify); - Expression simplifyForComplexFormat(Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat); Expression deepReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); void deepReduceChildren(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { return node()->deepReduceChildren(context, angleUnit, target); diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 5ee49e48c..94a135825 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -366,12 +366,12 @@ int Expression::serialize(char * buffer, int bufferSize, Preferences::PrintFloat /* Simplification */ -Expression Expression::ParseAndProcess(const char * text, Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat, bool complexSimplify) { +Expression Expression::ParseAndSimplify(const char * text, Context & context, Preferences::AngleUnit angleUnit) { Expression exp = Parse(text); if (exp.isUninitialized()) { return Undefined(); } - exp = complexSimplify ? exp.simplifyForComplexFormat(context, angleUnit, complexFormat) : exp.simplify(context, angleUnit); + exp = exp.simplify(context, angleUnit); /* simplify might have been interrupted, in which case the resulting * expression is uninitialized, so we need to check that. */ if (exp.isUninitialized()) { @@ -389,63 +389,6 @@ Expression Expression::simplify(Context & context, Preferences::AngleUnit angleU return sSimplificationHasBeenInterrupted ? Expression() : e; } -bool isZero(const Expression e) { - return e.type() == ExpressionNode::Type::Rational && static_cast(e).isZero(); -} -bool isOne(const Expression e) { - return e.type() == ExpressionNode::Type::Rational && static_cast(e).isOne(); -} -bool isMinusOne(const Expression e) { - Expression c = e.numberOfChildren() > 0 ? e.childAtIndex(0) : Expression(); - return e.type() == ExpressionNode::Type::Opposite && e.childAtIndex(0).type() == ExpressionNode::Type::Rational && static_cast(c).isOne(); -} - -Expression Expression::simplifyForComplexFormat(Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) { - sSimplificationHasBeenInterrupted = false; - if (isPureReal(context, angleUnit)) { - return simplify(context, angleUnit); - } - // We deepReduce before extracting the real and imaginary part to develop expression of type (a+b*i)^3 for example - Expression e = deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); - if (sSimplificationHasBeenInterrupted) { - return Expression(); - } - Expression complexParts = complexFormat == Preferences::ComplexFormat::Cartesian ? static_cast(e.complexCartesian(context, angleUnit)) : static_cast(e.complexPolar(context, angleUnit)); - if (complexParts.isUninitialized()) { - return e.simplify(context, angleUnit); - } - // Depending on the complexFormat required: - // - ra is the real part or the norm - // - tb is the imaginary part or the argument - assert(complexParts.type() == ExpressionNode::Type::ComplexCartesian || complexParts.type() == ExpressionNode::Type::ComplexPolar); - assert(complexParts.numberOfChildren() == 2); - Expression ra = complexParts.childAtIndex(0); - Expression tb = complexParts.childAtIndex(1); - assert(!ra.isUninitialized() && !tb.isUninitialized()); - ra = ra.simplify(context, angleUnit); - tb = tb.simplify(context, angleUnit); - if (ra.isUninitialized() || tb.isUninitialized()) { - return e.simplify(context, angleUnit); - } - e = CreateComplexExpression(ra, tb, complexFormat, - ra.type() == ExpressionNode::Type::Undefined || tb.type() == ExpressionNode::Type::Undefined, - isZero(ra), isOne(ra), isZero(tb), isOne(tb), isMinusOne(tb), - tb.type() == ExpressionNode::Type::Opposite, - [](Expression e) { - if (e.type() == ExpressionNode::Type::Opposite) { - return e.childAtIndex(0); - } else { - assert(e.type() == ExpressionNode::Type::Undefined || e.type() == ExpressionNode::Type::Rational || e.type() == ExpressionNode::Type::Float || e.type() == ExpressionNode::Type::Decimal || e.type() == ExpressionNode::Type::Infinity); - return Expression(static_cast(e).setSign(ExpressionNode::Sign::Positive)); - } - } - ); - if (sSimplificationHasBeenInterrupted) { - return Expression(); - } - return e; -} - Expression Expression::ExpressionWithoutSymbols(Expression e, Context & context) { if (e.isUninitialized()) { return e; From f71469957509ae7e30fce48712c3bcc92f4a666b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 13 Dec 2018 11:05:16 +0100 Subject: [PATCH 091/373] [poincare] Clean Expression::CreateComplexExpression --- poincare/include/poincare/expression.h | 3 +-- poincare/src/complex.cpp | 9 +++------ poincare/src/expression.cpp | 13 ++++++++----- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index c42ef1578..5f850c2d9 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -299,8 +299,7 @@ private: int defaultGetPolynomialCoefficients(Context & context, const char * symbol, Expression expression[]) const; /* Builder */ - typedef Expression (*TransformExpression)(Expression e); - static Expression CreateComplexExpression(Expression ra, Expression tb, Preferences::ComplexFormat complexFormat, bool undefined, bool isZeroRa, bool isOneRa, bool isZeroTb, bool isOneTb, bool isMinusOneTb, bool isNegativeTb, TransformExpression inverse); + static Expression CreateComplexExpression(Expression ra, Expression tb, Preferences::ComplexFormat complexFormat, bool undefined, bool isZeroRa, bool isOneRa, bool isZeroTb, bool isOneTb, bool isMinusOneTb, bool isNegativeRa, bool isNegativeTb); /* Expression roots/extrema solver*/ constexpr static double k_solverPrecision = 1.0E-5; diff --git a/poincare/src/complex.cpp b/poincare/src/complex.cpp index 76e878db4..2897957a8 100644 --- a/poincare/src/complex.cpp +++ b/poincare/src/complex.cpp @@ -51,14 +51,11 @@ Expression ComplexNode::complexToExpression(Preferences::ComplexFormat comple tb = std::arg(*this); } return Expression::CreateComplexExpression( - Number::DecimalNumber(ra), - Number::DecimalNumber(tb), + Number::DecimalNumber(std::fabs(ra)), + Number::DecimalNumber(std::fabs(tb)), complexFormat, (std::isnan(this->real()) || std::isnan(this->imag())), - ra == 0.0, ra == 1.0, tb == 0.0, tb == 1.0, tb == -1.0, tb < 0.0, - [](Expression e) { - assert(e.type() == ExpressionNode::Type::Undefined || e.type() == ExpressionNode::Type::Rational || e.type() == ExpressionNode::Type::Float || e.type() == ExpressionNode::Type::Decimal || e.type() == ExpressionNode::Type::Infinity); - return Expression(static_cast(e).setSign(ExpressionNode::Sign::Positive)); } + ra == 0.0, ra == 1.0, tb == 0.0, tb == 1.0, tb == -1.0, ra < 0.0, tb < 0.0 ); } diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 94a135825..3b48ddb93 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -499,7 +499,7 @@ U Expression::epsilon() { /* Builder */ -Expression Expression::CreateComplexExpression(Expression ra, Expression tb, Preferences::ComplexFormat complexFormat, bool undefined, bool isZeroRa, bool isOneRa, bool isZeroTb, bool isOneTb, bool isMinusOneTb, bool isNegativeTb, TransformExpression inverse) { +Expression Expression::CreateComplexExpression(Expression ra, Expression tb, Preferences::ComplexFormat complexFormat, bool undefined, bool isZeroRa, bool isOneRa, bool isZeroTb, bool isOneTb, bool isMinusOneTb, bool isNegativeRa, bool isNegativeTb) { if (undefined) { return Undefined(); } @@ -509,13 +509,15 @@ Expression Expression::CreateComplexExpression(Expression ra, Expression tb, Pre Expression real; Expression imag; if (!isZeroRa || isZeroTb) { - real = ra; + if (isNegativeRa) { + real = Opposite(ra); + } else { + real = ra; + } } if (!isZeroTb) { if (isOneTb || isMinusOneTb) { imag = Constant(Ion::Charset::IComplex); - } else if (isNegativeTb) { - imag = Multiplication(inverse(tb), Constant(Ion::Charset::IComplex)); } else { imag = Multiplication(tb , Constant(Ion::Charset::IComplex)); } @@ -540,6 +542,7 @@ Expression Expression::CreateComplexExpression(Expression ra, Expression tb, Pre Expression norm; Expression exp; if (!isOneRa || isZeroTb) { + assert(!isNegativeRa); // norm cannot be negative norm = ra; } if (!isZeroRa && !isZeroTb) { @@ -549,7 +552,7 @@ Expression Expression::CreateComplexExpression(Expression ra, Expression tb, Pre } else if (isMinusOneTb) { arg = Opposite(Constant(Ion::Charset::IComplex)); } else if (isNegativeTb) { - arg = Opposite(Multiplication(inverse(tb), Constant(Ion::Charset::IComplex))); + arg = Opposite(Multiplication(tb, Constant(Ion::Charset::IComplex))); } else { arg = Multiplication(tb, Constant(Ion::Charset::IComplex)); } From e11b7ca631de9df8676e23d782151946c253c0ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 13 Dec 2018 11:07:24 +0100 Subject: [PATCH 092/373] [poincare] Power: improve shallowReduce using makePositiveAnyNegativeNumeralFactor --- poincare/src/power.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index e5845c1f3..99e99ad3a 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -492,19 +492,20 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU } // (a)^(1/2) with a < 0 --> i*(-a)^(1/2) if (!letPowerAtRoot - && nonComplexNegativeChild0 && childAtIndex(1).type() == ExpressionNode::Type::Rational && childAtIndex(1).convert().isHalf()) { - Expression m0 = Multiplication(Rational(-1), childAtIndex(0)); - replaceChildAtIndexInPlace(0, m0); - m0.shallowReduce(context, angleUnit, target); - Multiplication m1 = Multiplication(); - replaceWithInPlace(m1); - m1.addChildAtIndexInPlace(Constant(Ion::Charset::IComplex), 0, 0); - m1.addChildAtIndexInPlace(*this, 1, 1); - shallowReduce(context, angleUnit, target); - return m1.shallowReduce(context, angleUnit, target); + Expression m0 = childAtIndex(0).makePositiveAnyNegativeNumeralFactor(context, angleUnit); + if (!m0.isUninitialized()) { + replaceChildAtIndexInPlace(0, m0); + //m0.shallowReduce(context, angleUnit, target); + Multiplication m1 = Multiplication(); + replaceWithInPlace(m1); + m1.addChildAtIndexInPlace(Constant(Ion::Charset::IComplex), 0, 0); + m1.addChildAtIndexInPlace(*this, 1, 1); + shallowReduce(context, angleUnit, target); + return m1.shallowReduce(context, angleUnit, target); + } } // e^(i*Pi*r) with r rational if (!letPowerAtRoot && isNthRootOfUnity()) { From 3292bdfd44b49a42c73b1bb11d7cfb4a92c24444 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 13 Dec 2018 11:08:12 +0100 Subject: [PATCH 093/373] [poincare] Sketch of complex reduction as part of the reduce routine --- poincare/Makefile | 1 + poincare/include/poincare/absolute_value.h | 1 + poincare/include/poincare/arc_tangent.h | 1 + .../include/poincare/binomial_coefficient.h | 1 + poincare/include/poincare/ceiling.h | 1 + poincare/include/poincare/complex_argument.h | 1 + poincare/include/poincare/complex_cartesian.h | 25 +- poincare/include/poincare/constant.h | 7 + poincare/include/poincare/cosine.h | 1 + poincare/include/poincare/derivative.h | 1 + poincare/include/poincare/division_quotient.h | 2 + .../include/poincare/division_remainder.h | 2 + poincare/include/poincare/expression.h | 6 +- poincare/include/poincare/expression_node.h | 4 +- poincare/include/poincare/factorial.h | 2 + poincare/include/poincare/floor.h | 2 + poincare/include/poincare/frac_part.h | 2 + .../include/poincare/great_common_divisor.h | 2 + poincare/include/poincare/imaginary_part.h | 2 + poincare/include/poincare/integral.h | 2 + .../include/poincare/least_common_multiple.h | 2 + poincare/include/poincare/matrix_dimension.h | 1 + .../include/poincare/n_ary_expression_node.h | 8 + poincare/include/poincare/number.h | 1 + .../include/poincare/permute_coefficient.h | 2 + poincare/include/poincare/power.h | 1 + poincare/include/poincare/randint.h | 1 + poincare/include/poincare/random.h | 1 + poincare/include/poincare/real_part.h | 1 + poincare/include/poincare/round.h | 1 + poincare/include/poincare/sign_function.h | 1 + poincare/include/poincare/sine.h | 1 + poincare/include/poincare/tangent.h | 2 + poincare/src/addition.cpp | 37 ++- poincare/src/complex_cartesian.cpp | 259 ++++++++++++++++++ poincare/src/complex_helper.cpp | 5 +- poincare/src/constant.cpp | 17 ++ poincare/src/expression.cpp | 10 +- poincare/src/multiplication.cpp | 43 ++- poincare/src/n_ary_expression_node.cpp | 22 ++ poincare/src/power.cpp | 86 +++++- 41 files changed, 542 insertions(+), 26 deletions(-) create mode 100644 poincare/src/complex_cartesian.cpp diff --git a/poincare/Makefile b/poincare/Makefile index a30d17d52..17fede897 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -49,6 +49,7 @@ objs += $(addprefix poincare/src/,\ ceiling.o\ complex.o\ complex_argument.o\ + complex_cartesian.o\ complex_helper.o\ confidence_interval.o\ conjugate.o\ diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 482508e9c..7e33f4660 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -26,6 +26,7 @@ public: // Complex ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } // Approximation template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { diff --git a/poincare/include/poincare/arc_tangent.h b/poincare/include/poincare/arc_tangent.h index d6ce0f626..5175dc1c0 100644 --- a/poincare/include/poincare/arc_tangent.h +++ b/poincare/include/poincare/arc_tangent.h @@ -25,6 +25,7 @@ public: // Complex ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianComplexFunction(this, context, angleUnit); } + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return childAtIndex(0)->isReal(context, angleUnit); } private: // Layout diff --git a/poincare/include/poincare/binomial_coefficient.h b/poincare/include/poincare/binomial_coefficient.h index fe8395167..da1c17ecd 100644 --- a/poincare/include/poincare/binomial_coefficient.h +++ b/poincare/include/poincare/binomial_coefficient.h @@ -21,6 +21,7 @@ public: // Complex ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } // Properties Type type() const override{ return Type::BinomialCoefficient; } diff --git a/poincare/include/poincare/ceiling.h b/poincare/include/poincare/ceiling.h index 185d18dae..91da42199 100644 --- a/poincare/include/poincare/ceiling.h +++ b/poincare/include/poincare/ceiling.h @@ -21,6 +21,7 @@ public: // Complex ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } // Properties Type type() const override { return Type::Ceiling; } diff --git a/poincare/include/poincare/complex_argument.h b/poincare/include/poincare/complex_argument.h index f431b1152..891bd222b 100644 --- a/poincare/include/poincare/complex_argument.h +++ b/poincare/include/poincare/complex_argument.h @@ -20,6 +20,7 @@ public: #endif // Complex ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } // Properties Type type() const override { return Type::ComplexArgument; } diff --git a/poincare/include/poincare/complex_cartesian.h b/poincare/include/poincare/complex_cartesian.h index 3f996c3ef..a8f7a25c3 100644 --- a/poincare/include/poincare/complex_cartesian.h +++ b/poincare/include/poincare/complex_cartesian.h @@ -2,7 +2,7 @@ #define POINCARE_COMPLEX_CARTESIAN_H #include -#include +#include namespace Poincare { @@ -26,19 +26,42 @@ private: // Evaluation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { assert(false); return Evaluation(); } Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { assert(false); return Evaluation(); } + // Simplification + Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) override; }; class ComplexCartesian final : public Expression { public: ComplexCartesian() : Expression() {} + ComplexCartesian(const ComplexCartesianNode * node) : Expression(node) {} + static ComplexCartesian Builder() { ComplexCartesianNode * node = TreePool::sharedPool()->createTreeNode(); return ComplexCartesian(node); } static ComplexCartesian Builder(Expression child0, Expression child1) { return ComplexCartesian(child0, child1); } + + // Getters Expression real() { return childAtIndex(0); } Expression imag() { return childAtIndex(1); } + + // Simplification + Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit); + + // Common operations (done in-place) + Expression squareNorm(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression norm(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression argument(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + ComplexCartesian inverse(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + ComplexCartesian squareRoot(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + ComplexCartesian powerInteger(int n, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + ComplexCartesian multiply(ComplexCartesian & other, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + ComplexCartesian power(ComplexCartesian & other, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: ComplexCartesian(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child0); replaceChildAtIndexInPlace(1, child1); } + static Multiplication squareRootHelper(Expression e, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + static Expression powerHelper(Expression norm, Expression trigo, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); }; diff --git a/poincare/include/poincare/constant.h b/poincare/include/poincare/constant.h index 4d91e8ca9..7d7f28110 100644 --- a/poincare/include/poincare/constant.h +++ b/poincare/include/poincare/constant.h @@ -18,6 +18,7 @@ public: #endif // Complex + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override; ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; // Expression Properties @@ -36,6 +37,9 @@ public: bool isPi() const { return isConstantChar(Ion::Charset::SmallPi); } bool isExponential() const { return isConstantChar(Ion::Charset::Exponential); } bool isIComplex() const { return isConstantChar(Ion::Charset::IComplex); } + + // Simplification + Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; private: char m_name[0]; // MUST be the last member variable @@ -54,6 +58,9 @@ public: bool isExponential() const { return node()->isExponential(); } bool isIComplex() const { return node()->isIComplex(); } + // Simplification + Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + private: ConstantNode * node() const { return static_cast(Expression::node()); } }; diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index 757ca2315..5da48dacc 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -22,6 +22,7 @@ public: // Complex ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianComplexFunction(this, context, angleUnit); } + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return childAtIndex(0)->isReal(context, angleUnit); } // Properties Type type() const override { return Type::Cosine; } diff --git a/poincare/include/poincare/derivative.h b/poincare/include/poincare/derivative.h index 1ba1d339f..44c01b74f 100644 --- a/poincare/include/poincare/derivative.h +++ b/poincare/include/poincare/derivative.h @@ -22,6 +22,7 @@ public: // Complex ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } // Properties Type type() const override { return Type::Derivative; } diff --git a/poincare/include/poincare/division_quotient.h b/poincare/include/poincare/division_quotient.h index 166b3d2c1..43f1ea673 100644 --- a/poincare/include/poincare/division_quotient.h +++ b/poincare/include/poincare/division_quotient.h @@ -23,6 +23,8 @@ public: // Complex ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/division_remainder.h b/poincare/include/poincare/division_remainder.h index f7f93f467..ad6e98f88 100644 --- a/poincare/include/poincare/division_remainder.h +++ b/poincare/include/poincare/division_remainder.h @@ -24,6 +24,8 @@ public: // Complex ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 5f850c2d9..8620088b3 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -29,6 +29,7 @@ class Expression : public TreeHandle { template friend class ComplexNode; friend class ComplexArgument; + friend class ComplexCartesian; friend class ComplexHelper; friend class ConfidenceInterval; friend class Conjugate; @@ -166,6 +167,7 @@ public: Expression defaultReplaceUnknown(const Symbol & symbol); /* Complex */ + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const { return node()->isReal(context, angleUnit); } bool isPureReal(Context & context, Preferences::AngleUnit angleUnit) const; ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const; ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const; @@ -186,8 +188,8 @@ public: Expression simplify(Context & context, Preferences::AngleUnit angleUnit); Expression reduce(Context & context, Preferences::AngleUnit angleUnit); static Expression ExpressionWithoutSymbols(Expression expressionWithSymbols, Context & context); - Expression radianToDegree(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - Expression degreeToRadian(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression radianToDegree(); + Expression degreeToRadian(); /* Approximation Helper */ template static U epsilon(); diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index 39ba11fd5..409d1e1d7 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -48,7 +48,6 @@ public: BinomialCoefficient, Ceiling, ComplexArgument, - ComplexCartesian, ComplexPolar, Conjugate, Derivative, @@ -88,6 +87,8 @@ public: Symbol, Constant, + ComplexCartesian, + Matrix, ConfidenceInterval, MatrixDimension, @@ -128,6 +129,7 @@ public: * ComplexCartesian::shallowBeautify. This would enable us to do only one * scan of the tree in ParseAndSimplifyForComplexFormat instead of Simplifying * and then extracting ComplexCartesian. */ + virtual bool isReal(Context & context, Preferences::AngleUnit angleUnit) const { return false; } virtual ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const; virtual ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const; diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index d7541205b..9c4d5a4eb 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -26,6 +26,8 @@ public: // Complex ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + private: // Layout bool childNeedsParenthesis(const TreeNode * child) const override; diff --git a/poincare/include/poincare/floor.h b/poincare/include/poincare/floor.h index 5779a0fea..48e85999d 100644 --- a/poincare/include/poincare/floor.h +++ b/poincare/include/poincare/floor.h @@ -25,6 +25,8 @@ public: // Complex ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/frac_part.h b/poincare/include/poincare/frac_part.h index 45163bedd..aca4ee91c 100644 --- a/poincare/include/poincare/frac_part.h +++ b/poincare/include/poincare/frac_part.h @@ -25,6 +25,8 @@ public: // Complex ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/great_common_divisor.h b/poincare/include/poincare/great_common_divisor.h index dd3e6036b..1e1a86a08 100644 --- a/poincare/include/poincare/great_common_divisor.h +++ b/poincare/include/poincare/great_common_divisor.h @@ -22,6 +22,8 @@ public: Type type() const override { return Type::GreatCommonDivisor; } // Complex ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/imaginary_part.h b/poincare/include/poincare/imaginary_part.h index b4d73573e..bbc8bde4a 100644 --- a/poincare/include/poincare/imaginary_part.h +++ b/poincare/include/poincare/imaginary_part.h @@ -24,6 +24,8 @@ public: // Complex ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/integral.h b/poincare/include/poincare/integral.h index 3f0f4fee1..57d82309c 100644 --- a/poincare/include/poincare/integral.h +++ b/poincare/include/poincare/integral.h @@ -26,6 +26,8 @@ public: // Complex ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/least_common_multiple.h b/poincare/include/poincare/least_common_multiple.h index e186a5faa..dcbc9a0db 100644 --- a/poincare/include/poincare/least_common_multiple.h +++ b/poincare/include/poincare/least_common_multiple.h @@ -22,6 +22,8 @@ public: // Complex ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + private: /* Layout */ Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/matrix_dimension.h b/poincare/include/poincare/matrix_dimension.h index d54170778..215e89d42 100644 --- a/poincare/include/poincare/matrix_dimension.h +++ b/poincare/include/poincare/matrix_dimension.h @@ -23,6 +23,7 @@ public: // Complex ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } + private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/n_ary_expression_node.h b/poincare/include/poincare/n_ary_expression_node.h index 99fd3219f..c537c0a6c 100644 --- a/poincare/include/poincare/n_ary_expression_node.h +++ b/poincare/include/poincare/n_ary_expression_node.h @@ -18,6 +18,9 @@ public: } void eraseNumberOfChildren() override { m_numberOfChildren = 0; } + // Complex + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override; + // Comparison typedef int (*ExpressionOrder)(const ExpressionNode * e1, const ExpressionNode * e2, bool canBeInterrupted); @@ -48,6 +51,11 @@ public: Expression squashUnaryHierarchyInPlace() { return node()->squashUnaryHierarchyInPlace(); } + /* allChildrenAreReal returns: + * - 1 if all children are real + * - 0 if all non real children are ComplexCartesian + * - -1 if some chidren are non-real and non ComplexCartesian */ + int allChildrenAreReal(Context & context, Preferences::AngleUnit angleUnit) const; protected: NAryExpressionNode * node() const { return static_cast(Expression::node()); } }; diff --git a/poincare/include/poincare/number.h b/poincare/include/poincare/number.h index a7242ea6f..b2fbb08a2 100644 --- a/poincare/include/poincare/number.h +++ b/poincare/include/poincare/number.h @@ -25,6 +25,7 @@ public: // Complex ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } }; class Number : public Expression { diff --git a/poincare/include/poincare/permute_coefficient.h b/poincare/include/poincare/permute_coefficient.h index a87a5b165..00bc4e579 100644 --- a/poincare/include/poincare/permute_coefficient.h +++ b/poincare/include/poincare/permute_coefficient.h @@ -27,6 +27,8 @@ public: // Complex ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index f5bd315fb..7b1503d1a 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -22,6 +22,7 @@ public: #endif // Complex + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override; ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override; diff --git a/poincare/include/poincare/randint.h b/poincare/include/poincare/randint.h index c42eb76cf..25e5b1d95 100644 --- a/poincare/include/poincare/randint.h +++ b/poincare/include/poincare/randint.h @@ -23,6 +23,7 @@ public: // Complex ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } private: // Layout diff --git a/poincare/include/poincare/random.h b/poincare/include/poincare/random.h index e5ff18916..a78507d6d 100644 --- a/poincare/include/poincare/random.h +++ b/poincare/include/poincare/random.h @@ -21,6 +21,7 @@ public: // Complex ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } // Properties Type type() const override { return Type::Random; } diff --git a/poincare/include/poincare/real_part.h b/poincare/include/poincare/real_part.h index a376d5efc..da5a13da5 100644 --- a/poincare/include/poincare/real_part.h +++ b/poincare/include/poincare/real_part.h @@ -24,6 +24,7 @@ public: // Complex ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } private: // Layout diff --git a/poincare/include/poincare/round.h b/poincare/include/poincare/round.h index 8d2572c93..a2ae66d7a 100644 --- a/poincare/include/poincare/round.h +++ b/poincare/include/poincare/round.h @@ -21,6 +21,7 @@ public: // Complex ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } // Properties Type type() const override { return Type::Round; } diff --git a/poincare/include/poincare/sign_function.h b/poincare/include/poincare/sign_function.h index 6c17d83a5..36f476252 100644 --- a/poincare/include/poincare/sign_function.h +++ b/poincare/include/poincare/sign_function.h @@ -26,6 +26,7 @@ public: // Complex ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } private: // Layout diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index 044551f3d..d2561db0c 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -22,6 +22,7 @@ public: // Complex ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianComplexFunction(this, context, angleUnit); } + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return childAtIndex(0)->isReal(context, angleUnit); } // Properties Type type() const override { return Type::Sine; } diff --git a/poincare/include/poincare/tangent.h b/poincare/include/poincare/tangent.h index 901303708..b4c0aa747 100644 --- a/poincare/include/poincare/tangent.h +++ b/poincare/include/poincare/tangent.h @@ -25,6 +25,8 @@ public: // Complex ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianComplexFunction(this, context, angleUnit); } + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return childAtIndex(0)->isReal(context, angleUnit); } + private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 54ae2353a..9b7fbc659 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -266,8 +266,43 @@ Expression Addition::shallowReduce(Context & context, Preferences::AngleUnit ang // Step 5: Let's remove the addition altogether if it has a single child Expression result = squashUnaryHierarchyInPlace(); + if (result != *this) { + return result; + } - /* Step 6: Let's put everything under a common denominator. + /* Step 6: Let's bubble up the complex operator if possible + * 3 cases: + * - All children are real, we do nothing (allChildrenAreReal == 1) + * - One of the child is non-real and not a ComplexCartesian: it means a + * complex expression could not be resolved as a ComplexCartesian, we cannot + * do anything about it now (allChildrenAreReal == -1) + * - All children are either real or ComplexCartesian (allChildrenAreReal == 0) + * We can bubble up ComplexCartesian nodes. */ + if (allChildrenAreReal(context, angleUnit) == 0) { + Addition imag; + Addition real = *this; + i = numberOfChildren() - 1; + while (i >= 0) { + Expression c = childAtIndex(i); + if (c.type() == ExpressionNode::Type::ComplexCartesian) { + real.replaceChildAtIndexInPlace(i, c.childAtIndex(0)); + imag.addChildAtIndexInPlace(c.childAtIndex(1), imag.numberOfChildren(), imag.numberOfChildren()); + } else { + // the Addition is sorted so ComplexCartesian nodes are the last ones + break; + } + i--; + } + ComplexCartesian newComplexCartesian = ComplexCartesian::Builder(); + replaceWithInPlace(newComplexCartesian); + newComplexCartesian.replaceChildAtIndexInPlace(0, real); + newComplexCartesian.replaceChildAtIndexInPlace(1, imag); + real.shallowReduce(context, angleUnit, target); + imag.shallowReduce(context, angleUnit, target); + return newComplexCartesian.shallowReduce(context, angleUnit); + } + + /* Step 7: Let's put everything under a common denominator. * This step is done only for ReductionTarget::User if the parent expression * is not an addition. */ Expression p = result.parent(); diff --git a/poincare/src/complex_cartesian.cpp b/poincare/src/complex_cartesian.cpp new file mode 100644 index 000000000..5dafd7c4f --- /dev/null +++ b/poincare/src/complex_cartesian.cpp @@ -0,0 +1,259 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Poincare { + +Expression ComplexCartesianNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return ComplexCartesian(this).shallowReduce(context, angleUnit); +} + +Expression ComplexCartesianNode::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { + return ComplexCartesian(this).shallowBeautify(context, angleUnit); +} + + +bool isZero(const Expression e) { + return e.type() == ExpressionNode::Type::Rational && static_cast(e).isZero(); +} +bool isOne(const Expression e) { + return e.type() == ExpressionNode::Type::Rational && static_cast(e).isOne(); +} +bool isMinusOne(const Expression e) { + return e.type() == ExpressionNode::Type::Rational && static_cast(e).isMinusOne(); +} + +Expression ComplexCartesian::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { + if (imag().isRationalZero()) { + Expression r = real(); + replaceWithInPlace(r); + return r; + } + return *this; +} + +Expression ComplexCartesian::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { + Expression a = real(); + Expression b = imag(); + Expression oppositeA = a.makePositiveAnyNegativeNumeralFactor(context, angleUnit); + Expression oppositeB = b.makePositiveAnyNegativeNumeralFactor(context, angleUnit); + a = oppositeA.isUninitialized() ? a : oppositeA; + b = oppositeB.isUninitialized() ? b : oppositeB; + Expression e = Expression::CreateComplexExpression(a, b, Preferences::ComplexFormat::Cartesian, + a.type() == ExpressionNode::Type::Undefined || b.type() == ExpressionNode::Type::Undefined, + isZero(a), isOne(a), isZero(b), isOne(b), isMinusOne(b), + !oppositeA.isUninitialized(), + !oppositeB.isUninitialized() + ); + replaceWithInPlace(e); + return e; +} + +Expression ComplexCartesian::squareNorm(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + Expression a = real(); + Expression b = imag(); + Expression a2 = Power(a, Rational(2)); + Expression b2 = Power(b, Rational(2)); + Addition add(a2, b2); + a2.shallowReduce(context, angleUnit, target); + b2.shallowReduce(context, angleUnit, target); + return add; +} + +Expression ComplexCartesian::norm(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + Expression n2 = squareNorm(context, angleUnit, target); + Expression n = SquareRoot::Builder(n2); + n2.shallowReduce(context, angleUnit, target); + return n; +} + +Expression ComplexCartesian::argument(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + Expression a = real(); + Expression b = imag(); + if (!b.isRationalZero()) { + // if b != 0, argument = sign(b) * Pi/2 - arctan(a/b) + // First, compute arctan(a/b) or (Pi/180)*arctan(a/b) + Expression divab = Division(a, b.clone()); + Expression arcTangent = ArcTangent::Builder(divab); + divab.shallowReduce(context, angleUnit, target); + if (angleUnit == Preferences::AngleUnit::Degree) { + Expression temp = arcTangent.degreeToRadian(); + arcTangent.shallowReduce(context, angleUnit, target); + arcTangent = temp; + } + // Then, compute sign(b) * Pi/2 - arctan(a/b) + Expression signb = SignFunction::Builder(b); + Expression signbPi2 = Multiplication(Rational(1,2), signb, Constant(Ion::Charset::SmallPi)); + signb.shallowReduce(context, angleUnit, target); + Expression sub = Subtraction(signbPi2, arcTangent); + signbPi2.shallowReduce(context, angleUnit, target); + arcTangent.shallowReduce(context, angleUnit, target); + return sub; + } else { + // if b == 0, argument = (1-sign(a))*Pi/2 + Expression signa = SignFunction::Builder(a).shallowReduce(context, angleUnit); + Subtraction sub(Rational(1), signa); + signa.shallowReduce(context, angleUnit, target); + Multiplication mul(Rational(1,2), Constant(Ion::Charset::SmallPi), sub); + sub.shallowReduce(context, angleUnit, target); + return mul; + } +} + +ComplexCartesian ComplexCartesian::inverse(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + Expression a = real(); + Expression b = imag(); + // 1/(a+ib) = a/(a^2+b^2)+i*(-b/(a^2+b^2)) + Expression denominatorReal = clone().convert().squareNorm(context, angleUnit, target); + Expression denominatorImag = denominatorReal.clone(); + Expression denominatorRealInv = Power(denominatorReal, Rational(-1)); + denominatorReal.shallowReduce(context, angleUnit, target); + Expression denominatorImagInv = Power(denominatorImag, Rational(-1)); + denominatorImag.shallowReduce(context, angleUnit, target); + Multiplication A(a, denominatorRealInv); + denominatorRealInv.shallowReduce(context, angleUnit, target); + Expression numeratorImag = Multiplication(Rational(-1), b); + Multiplication B(numeratorImag, denominatorImagInv); + numeratorImag.shallowReduce(context, angleUnit, target); + denominatorImagInv.shallowReduce(context, angleUnit, target); + ComplexCartesian result(A,B); + A.shallowReduce(context, angleUnit, target); + B.shallowReduce(context, angleUnit, target); + return result; +} + +Multiplication ComplexCartesian::squareRootHelper(Expression e, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + //(1/2)*sqrt(2*e) + Multiplication doubleE(Rational(2), e); + e.shallowReduce(context, angleUnit, target); + Expression sqrt = SquareRoot::Builder(doubleE); + doubleE.shallowReduce(context, angleUnit, target); + Multiplication result(Rational(1,2), sqrt); + sqrt.shallowReduce(context, angleUnit, target); + return result; +} + +ComplexCartesian ComplexCartesian::squareRoot(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + Expression a = real(); + Expression b = imag(); + // A: (1/2)*sqrt(2*(sqrt(a^2+b^2)+a)) + // B: (1/2)*sqrt(2*(sqrt(a^2+b^2)-a))*sign(b) + Expression normA = clone().convert().norm(context, angleUnit, target); + Expression normB = normA.clone(); + // A = (1/2)*sqrt(2*(sqrt(a^2+b^2)+a)) + Addition normAdda(normA, a.clone()); + normA.shallowReduce(context, angleUnit, target); + Multiplication A = squareRootHelper(normAdda, context, angleUnit, target); + // B = B: (1/2)*sqrt(2*(sqrt(a^2+b^2)-a)) + Subtraction normSuba(normB, a); + normB.shallowReduce(context, angleUnit, target); + Multiplication B = squareRootHelper(normSuba, context, angleUnit, target); + // B = B: (1/2)*sqrt(2*(sqrt(a^2+b^2)-a))*sign(b) + Expression signb = SignFunction::Builder(b); + B.addChildAtIndexInPlace(signb, B.numberOfChildren(), B.numberOfChildren()); + signb.shallowReduce(context, angleUnit, target); + ComplexCartesian result = ComplexCartesian::Builder(A, B); + A.shallowReduce(context, angleUnit, target); + B.shallowReduce(context, angleUnit, target); + return result; +} + + +ComplexCartesian ComplexCartesian::powerInteger(int n, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + return ComplexCartesian(); +} + +ComplexCartesian ComplexCartesian::multiply(ComplexCartesian & other, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + Expression a = real(); + Expression b = imag(); + Expression c = other.real(); + Expression d = other.imag(); + // (a+ib) * (c+id) = (ac-bd)+i*(ad+bc) + // Compute ac-bd + Expression ac = Multiplication(a.clone(), c.clone()); + Expression bd = Multiplication(b.clone(), d.clone()); + Subtraction A(ac, bd); + ac.shallowReduce(context, angleUnit, target); + bd.shallowReduce(context, angleUnit, target); + // Compute ad+bc + Expression ad = Multiplication(a, d); + Expression bc = Multiplication(b, c); + Addition B(ad, bc); + ad.shallowReduce(context, angleUnit, target); + bc.shallowReduce(context, angleUnit, target); + ComplexCartesian result = ComplexCartesian::Builder(A, B); + A.shallowReduce(context, angleUnit, target); + B.shallowReduce(context, angleUnit, target); + return result; +} + +Expression ComplexCartesian::powerHelper(Expression norm, Expression trigo, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + Multiplication m(norm, trigo); + norm.shallowReduce(context, angleUnit, target); + trigo.shallowReduce(context, angleUnit, target); + return m; +} + +ComplexCartesian ComplexCartesian::power(ComplexCartesian & other, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + Expression r = clone().convert().norm(context, angleUnit, target); + Expression rclone = r.clone(); + Expression th = argument(context, angleUnit, target); + Expression thclone = th.clone(); + Expression c = other.real(); + Expression d = other.imag(); + // R = r^c*e^(-th*d) + Expression rpowc = Power(rclone, c); + rclone.shallowReduce(context, angleUnit, target); + Expression thmuld = Multiplication(Rational(-1), thclone, d.clone()); + thclone.shallowReduce(context, angleUnit, target); + Expression exp = Power(Constant(Ion::Charset::Exponential), thmuld); + thmuld.shallowReduce(context, angleUnit, target); + Multiplication norm(rpowc, exp); + rpowc.shallowReduce(context, angleUnit, target); + exp.shallowReduce(context, angleUnit, target); + + // TH = d*ln(r)+c*th + Expression lnr = NaperianLogarithm::Builder(r); + r.shallowReduce(context, angleUnit, target); + Multiplication dlnr(d, lnr); + lnr.shallowReduce(context, angleUnit, target); + Multiplication thc(th, c); + th.shallowReduce(context, angleUnit, target); + Expression argument = Addition(thc, dlnr); + thc.shallowReduce(context, angleUnit, target); + dlnr.shallowReduce(context, angleUnit, target); + + if (angleUnit == Preferences::AngleUnit::Degree) { + Expression temp = argument.radianToDegree(); + argument.shallowReduce(context, angleUnit, target); + argument = temp; + } + // Result = (norm*cos(argument), norm*sin(argument)) + Expression normClone = norm.clone(); + Expression argClone = argument.clone(); + Expression cos = Cosine::Builder(argClone); + argClone.shallowReduce(context, angleUnit, target); + Expression normcosarg = powerHelper(normClone, cos, context, angleUnit, target); + Expression sin = Sine::Builder(argument); + argument.shallowReduce(context, angleUnit, target); + Expression normsinarg = powerHelper(norm, sin, context, angleUnit, target); + ComplexCartesian result = ComplexCartesian::Builder(normcosarg, normsinarg); + normcosarg.shallowReduce(context, angleUnit, target); + normsinarg.shallowReduce(context, angleUnit, target); + return result; +} + +} diff --git a/poincare/src/complex_helper.cpp b/poincare/src/complex_helper.cpp index f7de5efc2..e8e0541ec 100644 --- a/poincare/src/complex_helper.cpp +++ b/poincare/src/complex_helper.cpp @@ -51,7 +51,7 @@ ComplexCartesian ComplexHelper::complexCartesianFromComplexPolar(const Expressio Expression r = polar.norm(); Expression th = polar.arg(); assert(!r.isUninitialized() && !th.isUninitialized()); - Expression argument = angleUnit == Preferences::AngleUnit::Radian ? th : th.radianToDegree(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); + Expression argument = th; return ComplexCartesian::Builder( complexCartesianFromComplexPolarHelper(r.clone(), Cosine::Builder(argument.clone()), context, angleUnit), complexCartesianFromComplexPolarHelper(r, Sine::Builder(argument), context, angleUnit) @@ -93,9 +93,6 @@ ComplexPolar ComplexHelper::complexPolarFromComplexCartesian(const ExpressionNod // if b != 0, argument = sign(b) * Pi/2 - arctan(a/b) // First, compute arctan(a/b) or (Pi/180)*arctan(a/b) Expression arcTangent = ArcTangent::Builder(Division(a, b.clone()).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation)).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); - if (angleUnit == Preferences::AngleUnit::Degree) { - arcTangent = arcTangent.degreeToRadian(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); - } // Then, compute sign(b) * Pi/2 - arctan(a/b) argument = Subtraction( Multiplication( diff --git a/poincare/src/constant.cpp b/poincare/src/constant.cpp index 6a41326de..50ec2c2cc 100644 --- a/poincare/src/constant.cpp +++ b/poincare/src/constant.cpp @@ -16,6 +16,10 @@ ExpressionNode::Sign ConstantNode::sign(Context * context, Preferences::AngleUni return Sign::Unknown; } +bool ConstantNode::isReal(Context & context, Preferences::AngleUnit angleUnit) const { + return !isIComplex(); +} + ComplexCartesian ConstantNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { if (isIComplex()) { return ComplexCartesian::Builder(Rational(0), Rational(1)); @@ -47,8 +51,21 @@ Evaluation ConstantNode::templatedApproximate(Context& context, Preferences:: return Complex(M_E); } +Expression ConstantNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Constant(this).shallowReduce(context, angleUnit); +} + Constant::Constant(char name) : SymbolAbstract(TreePool::sharedPool()->createTreeNode(SymbolAbstract::AlignedNodeSize(1, sizeof(ConstantNode)))) { node()->setName(&name, 1); } +Expression Constant::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { + if (isIComplex()) { + ComplexCartesian c = ComplexCartesian::Builder(Rational(0), Rational(1)); + replaceWithInPlace(c); + return c; + } + return *this; +} + } diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 3b48ddb93..4719db2d6 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -420,12 +420,14 @@ Expression Expression::ExpressionWithoutSymbols(Expression e, Context & context) return e; } -Expression Expression::radianToDegree(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { - return Multiplication(*this, Division(Rational(180), Constant(Ion::Charset::SmallPi)).shallowReduce(context, angleUnit, target)).shallowReduce(context, angleUnit, target); +Expression Expression::radianToDegree() { + // e*180/Pi + return Multiplication(*this, Rational(180), Power(Constant(Ion::Charset::SmallPi), Rational(-1))); } -Expression Expression::degreeToRadian(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { - return Multiplication(*this, Division(Constant(Ion::Charset::SmallPi), Rational(180)).shallowReduce(context, angleUnit, target)).shallowReduce(context, angleUnit, target); +Expression Expression::degreeToRadian() { + // e*Pi/180 + return Multiplication(*this, Power(Rational(180), Rational(-1)), Constant(Ion::Charset::SmallPi)); } Expression Expression::reduce(Context & context, Preferences::AngleUnit angleUnit) { diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index aba35c0a9..bbc7ad08d 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -522,8 +522,49 @@ Expression Multiplication::privateShallowReduce(Context & context, Preferences:: } } - // Step 8: Let's remove the multiplication altogether if it has one child + // Step 7: Let's remove the multiplication altogether if it has one child Expression result = squashUnaryHierarchyInPlace(); + if (result != *this) { + return result; + } + + /* Step 8: Let's bubble up the complex operator if possible + * 3 cases: + * - All children are real, we do nothing (allChildrenAreReal == 1) + * - One of the child is non-real and not a ComplexCartesian: it means a + * complex expression could not be resolved as a ComplexCartesian, we cannot + * do anything about it now (allChildrenAreReal == -1) + * - All children are either real or ComplexCartesian (allChildrenAreReal == 0) + * We can bubble up ComplexCartesian nodes. */ + if (allChildrenAreReal(context, angleUnit) == 0) { + int nbChildren = numberOfChildren(); + int i = nbChildren-1; + assert(childAtIndex(i).type() == ExpressionNode::Type::ComplexCartesian); + ComplexCartesian child = childAtIndex(i).convert(); + removeChildAtIndexInPlace(i); + i--; + while (i >= 0) { + Expression e = childAtIndex(i); + if (e.type() != ExpressionNode::Type::ComplexCartesian) { + // the Multiplication is sorted so ComplexCartesian nodes are the last ones + break; + } + child = child.multiply(static_cast(e), context, angleUnit, target); + removeChildAtIndexInPlace(i); + i--; + } + Multiplication real = *this; + Multiplication imag = clone().convert(); + real.addChildAtIndexInPlace(child.real(), real.numberOfChildren(), real.numberOfChildren()); + imag.addChildAtIndexInPlace(child.imag(), real.numberOfChildren(), real.numberOfChildren()); + ComplexCartesian newComplexCartesian = ComplexCartesian::Builder(); + replaceWithInPlace(newComplexCartesian); + newComplexCartesian.replaceChildAtIndexInPlace(0, real); + newComplexCartesian.replaceChildAtIndexInPlace(1, imag); + real.shallowReduce(context, angleUnit, target); + imag.shallowReduce(context, angleUnit, target); + return newComplexCartesian.shallowReduce(context, angleUnit); + } return result; } diff --git a/poincare/src/n_ary_expression_node.cpp b/poincare/src/n_ary_expression_node.cpp index b6db830f5..d50e1ca61 100644 --- a/poincare/src/n_ary_expression_node.cpp +++ b/poincare/src/n_ary_expression_node.cpp @@ -28,6 +28,10 @@ void NAryExpressionNode::sortChildrenInPlace(ExpressionOrder order, bool canBeIn } } +bool NAryExpressionNode::isReal(Context & context, Preferences::AngleUnit angleUnit) const { + return NAryExpression(this).allChildrenAreReal(context, angleUnit) == 1; +} + Expression NAryExpressionNode::squashUnaryHierarchyInPlace() { NAryExpression reference = NAryExpression(this); if (reference.numberOfChildren() == 1) { @@ -76,4 +80,22 @@ int NAryExpressionNode::simplificationOrderGreaterType(const ExpressionNode * e, return 0; } +int NAryExpression::allChildrenAreReal(Context & context, Preferences::AngleUnit angleUnit) const { + int i = 0; + /* The addition children are assumed to be sorted. ComplexCartesian children + * are supposed to be the last ones before matrices. We just test children + * to be real until we reach the first ComplexCartesian. */ + while (i < numberOfChildren()) { + Expression c = childAtIndex(i); + if (c.type() == ExpressionNode::Type::ComplexCartesian) { + return 0; + } + if (!c.isReal(context, angleUnit)) { + return -1; + } + i++; + } + return 1; +} + } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 99e99ad3a..51a6eb1c7 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -79,7 +79,13 @@ int PowerNode::getPolynomialCoefficients(Context & context, const char * symbolN return Power(this).getPolynomialCoefficients(context, symbolName, coefficients); } -// Private +bool PowerNode::isReal(Context & context, Preferences::AngleUnit angleUnit) const { + ExpressionNode * base = childAtIndex(0); + if (base->isReal(context, angleUnit) && base->sign(&context, angleUnit) == Sign::Positive && childAtIndex(1)->isReal(context, angleUnit)) { + return true; + } + return false; +} ComplexCartesian PowerNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { Power p(this); @@ -125,6 +131,8 @@ ComplexPolar PowerNode::complexPolar(Context & context, Preferences::AngleUnit a return ComplexPolar::Builder(norm, argument); } +// Private + template Complex PowerNode::compute(const std::complex c, const std::complex d) { std::complex result; @@ -359,22 +367,76 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU #endif #endif - /* Step 0: if both children are true complexes, the result is undefined. We - * can assert that evaluations are Complex, as matrix are not simplified */ - - Evaluation c0Approximated = childAtIndex(0).node()->approximate(1.0f, context, angleUnit); + // TODO: do we need this? + /*Evaluation c0Approximated = childAtIndex(0).node()->approximate(1.0f, context, angleUnit); Evaluation c1Approximated = childAtIndex(1).node()->approximate(1.0f, context, angleUnit); Complex c0 = static_cast&>(c0Approximated); Complex c1 = static_cast&>(c1Approximated); bool bothChildrenComplexes = c0.imag() != 0 && c1.imag() != 0 && !std::isnan(c0.imag()) && !std::isnan(c1.imag()); - bool nonComplexNegativeChild0 = c0.imag() == 0 && c0.real() < 0; bool nonNullChild0 = !std::isnan(c0.real()) && !std::isnan(c0.imag()) && (c0.real() > Expression::epsilon() || c0.imag() > Expression::epsilon()); if (bothChildrenComplexes) { return *this; + }*/ + + /* Step 0: if both children are true unresolved complexes, the result is not simplified. TODO? */ + + Expression power = *this; + Expression base = childAtIndex(0); + Expression index = childAtIndex(1); + /* Step 0: if both children are true unresolved complexes, the result is not simplified. TODO? */ + if (!base.isReal(context, angleUnit) && !index.isReal(context, angleUnit)) { + return *this; + } + + /* Step 1: we now bubble up ComplexCartesian, we handle different case */ + + ComplexCartesian complexBase; + ComplexCartesian complexIndex; + ComplexCartesian result; + // First, (x+iy)^q with q special values + // TODO: explain here why? + if (base.type() == ExpressionNode::Type::ComplexCartesian) { + complexBase = static_cast(base); + Integer ten(10); + if (index.type() == ExpressionNode::Type::Rational) { + Rational r = static_cast(index); + if (r.isMinusOne()) { + // (x+iy)^(-1) + result = complexBase.inverse(context, angleUnit, target); + } else if (r.isHalf()) { + // (x+iy)^(1/2) + result = complexBase.squareRoot(context, angleUnit, target); + } else if (r.isMinusHalf()) { + // (x+iy)^(-1/2) + result = complexBase.squareRoot(context, angleUnit, target).inverse(context, angleUnit, target); + } else if (r.integerDenominator().isOne() && r.unsignedIntegerNumerator().isLowerThan(ten)) { + if (r.sign() == ExpressionNode::Sign::Positive) { + // (x+iy)^n, n integer positive n < 10 + result = complexBase.powerInteger(r.unsignedIntegerNumerator().extractedInt(), context, angleUnit, target); + } else { + // (x+iy)^(-n), n integer positive n < 10 + result = complexBase.powerInteger(r.unsignedIntegerNumerator().extractedInt(), context, angleUnit, target).inverse(context, angleUnit, target); + } + } + if (!result.isUninitialized()) { + replaceWithInPlace(result); + return result.shallowReduce(context, angleUnit); + } + } + } + // All other cases where one child at least is a ComplexCartesian + if ((base.isReal(context, angleUnit) && index.type() == ExpressionNode::Type::ComplexCartesian) || + (base.type() == ExpressionNode::Type::ComplexCartesian && index.isReal(context, angleUnit)) || + (base.type() == ExpressionNode::Type::ComplexCartesian && index.type() == ExpressionNode::Type::ComplexCartesian)) { + complexBase = base.type() == ExpressionNode::Type::ComplexCartesian ? static_cast(base) : ComplexCartesian::Builder(base, Rational(0)); + complexIndex = index.type() == ExpressionNode::Type::ComplexCartesian ? static_cast(index) : ComplexCartesian::Builder(index, Rational(0)); + result = complexBase.power(complexIndex, context, angleUnit, target); + replaceWithInPlace(result); + return result.shallowReduce(context, angleUnit); } /* Step 1: We handle simple cases as x^0, x^1, 0^x and 1^x first for 2 reasons: - * - we can assert this step that there is no division by 0: + * - we can assert after this step that there is no division by 0: * for instance, 0^(-2)->undefined * - we save computational time by early escaping for these cases. */ if (childAtIndex(1).type() == ExpressionNode::Type::Rational) { @@ -388,7 +450,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU return result; } // x^0 - if (target == ExpressionNode::ReductionTarget::User || nonNullChild0) { + if (target == ExpressionNode::ReductionTarget::User || childAtIndex(0).isNumber()) { /* Warning: if the ReductionTarget is User, in all other cases but 0^0, * we replace x^0 by one. This is almost always true except when x = 0. * However, not substituting x^0 by one would prevent from simplifying @@ -437,7 +499,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU } } - if (target == ExpressionNode::ReductionTarget::User && childAtIndex(1).type() == ExpressionNode::Type::Rational) { + /*if (target == ExpressionNode::ReductionTarget::User && childAtIndex(1).type() == ExpressionNode::Type::Rational) { const Rational b = childAtIndex(1).convert(); // i^(p/q) if (childAtIndex(0).type() == ExpressionNode::Type::Constant && childAtIndex(0).convert().isIComplex()) { @@ -446,7 +508,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU replaceWithInPlace(result); return result.shallowReduce(context, angleUnit, target); } - } + }*/ // (±inf)^x if (childAtIndex(0).type() == ExpressionNode::Type::Infinity) { @@ -508,7 +570,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU } } // e^(i*Pi*r) with r rational - if (!letPowerAtRoot && isNthRootOfUnity()) { + /*if (!letPowerAtRoot && isNthRootOfUnity()) { Expression m = childAtIndex(1); Expression i = m.childAtIndex(m.numberOfChildren()-1); static_cast(m).removeChildAtIndexInPlace(m.numberOfChildren()-1); @@ -525,7 +587,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU complexPart.shallowReduce(context, angleUnit, target); replaceWithInPlace(a); return a.shallowReduce(context, angleUnit, target); - } + }*/ // x^log(y,x)->y if y > 0 if (childAtIndex(1).type() == ExpressionNode::Type::Logarithm) { if (childAtIndex(1).numberOfChildren() == 2 && childAtIndex(0).isIdenticalTo(childAtIndex(1).childAtIndex(1))) { From 76ec7d3a584a1f3a1dc24d90635ae15bfb69c405 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 13 Dec 2018 17:51:18 +0100 Subject: [PATCH 094/373] [poincare] Implement ComplexCartesian::powerInteger --- poincare/src/complex_cartesian.cpp | 34 ++++++++++- poincare/src/power.cpp | 94 +++++++++++++++--------------- 2 files changed, 80 insertions(+), 48 deletions(-) diff --git a/poincare/src/complex_cartesian.cpp b/poincare/src/complex_cartesian.cpp index 5dafd7c4f..44d826e20 100644 --- a/poincare/src/complex_cartesian.cpp +++ b/poincare/src/complex_cartesian.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -173,7 +174,38 @@ ComplexCartesian ComplexCartesian::squareRoot(Context & context, Preferences::An ComplexCartesian ComplexCartesian::powerInteger(int n, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { - return ComplexCartesian(); + Expression a = real(); + Expression b = imag(); + assert(n > 0); + // (a+ib) = a^n+i*b*a^(n-1)+(-1)*b^2*a^(n-2)+(-i)*b^3*a^(n-3)+b^3*a^(n-4)+... + // Real part: A = a^n+(-1)*b^2*a^(n-2)+... + // Imaginary part: B = b*a^(n-1) + Addition A; + Addition B; + for (int i = 0; i <= n; i++) { + BinomialCoefficient binom = BinomialCoefficient::Builder(Rational(n), Rational(i)); + Expression aclone = i == n ? a : a.clone(); + Expression bclone = i == n ? b : b.clone(); + Power apow(aclone, Rational(n-i)); + Power bpow(bclone, Rational(i)); + Multiplication m(binom, apow, bpow); + binom.shallowReduce(context, angleUnit); + apow.shallowReduce(context, angleUnit, target); + bpow.shallowReduce(context, angleUnit, target); + if (i/2%2 == 1) { + m.addChildAtIndexInPlace(Rational(-1), 0, m.numberOfChildren()); + } + if (i%2 == 0) { + A.addChildAtIndexInPlace(m, A.numberOfChildren(), A.numberOfChildren()); + } else { + B.addChildAtIndexInPlace(m, B.numberOfChildren(), B.numberOfChildren()); + } + m.shallowReduce(context, angleUnit, target); + } + ComplexCartesian result = ComplexCartesian::Builder(A, B); + A.shallowReduce(context, angleUnit, target); + B.shallowReduce(context, angleUnit, target); + return result; } ComplexCartesian ComplexCartesian::multiply(ComplexCartesian & other, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 51a6eb1c7..2b65816db 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -388,53 +388,6 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU return *this; } - /* Step 1: we now bubble up ComplexCartesian, we handle different case */ - - ComplexCartesian complexBase; - ComplexCartesian complexIndex; - ComplexCartesian result; - // First, (x+iy)^q with q special values - // TODO: explain here why? - if (base.type() == ExpressionNode::Type::ComplexCartesian) { - complexBase = static_cast(base); - Integer ten(10); - if (index.type() == ExpressionNode::Type::Rational) { - Rational r = static_cast(index); - if (r.isMinusOne()) { - // (x+iy)^(-1) - result = complexBase.inverse(context, angleUnit, target); - } else if (r.isHalf()) { - // (x+iy)^(1/2) - result = complexBase.squareRoot(context, angleUnit, target); - } else if (r.isMinusHalf()) { - // (x+iy)^(-1/2) - result = complexBase.squareRoot(context, angleUnit, target).inverse(context, angleUnit, target); - } else if (r.integerDenominator().isOne() && r.unsignedIntegerNumerator().isLowerThan(ten)) { - if (r.sign() == ExpressionNode::Sign::Positive) { - // (x+iy)^n, n integer positive n < 10 - result = complexBase.powerInteger(r.unsignedIntegerNumerator().extractedInt(), context, angleUnit, target); - } else { - // (x+iy)^(-n), n integer positive n < 10 - result = complexBase.powerInteger(r.unsignedIntegerNumerator().extractedInt(), context, angleUnit, target).inverse(context, angleUnit, target); - } - } - if (!result.isUninitialized()) { - replaceWithInPlace(result); - return result.shallowReduce(context, angleUnit); - } - } - } - // All other cases where one child at least is a ComplexCartesian - if ((base.isReal(context, angleUnit) && index.type() == ExpressionNode::Type::ComplexCartesian) || - (base.type() == ExpressionNode::Type::ComplexCartesian && index.isReal(context, angleUnit)) || - (base.type() == ExpressionNode::Type::ComplexCartesian && index.type() == ExpressionNode::Type::ComplexCartesian)) { - complexBase = base.type() == ExpressionNode::Type::ComplexCartesian ? static_cast(base) : ComplexCartesian::Builder(base, Rational(0)); - complexIndex = index.type() == ExpressionNode::Type::ComplexCartesian ? static_cast(index) : ComplexCartesian::Builder(index, Rational(0)); - result = complexBase.power(complexIndex, context, angleUnit, target); - replaceWithInPlace(result); - return result.shallowReduce(context, angleUnit); - } - /* Step 1: We handle simple cases as x^0, x^1, 0^x and 1^x first for 2 reasons: * - we can assert after this step that there is no division by 0: * for instance, 0^(-2)->undefined @@ -490,6 +443,53 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU } } + /* Step 1: we now bubble up ComplexCartesian, we handle different case */ + + ComplexCartesian complexBase; + ComplexCartesian complexIndex; + ComplexCartesian result; + // First, (x+iy)^q with q special values + // TODO: explain here why? + if (base.type() == ExpressionNode::Type::ComplexCartesian) { + complexBase = static_cast(base); + Integer ten(10); + if (index.type() == ExpressionNode::Type::Rational) { + Rational r = static_cast(index); + if (r.isMinusOne()) { + // (x+iy)^(-1) + result = complexBase.inverse(context, angleUnit, target); + } else if (r.isHalf()) { + // (x+iy)^(1/2) + result = complexBase.squareRoot(context, angleUnit, target); + } else if (r.isMinusHalf()) { + // (x+iy)^(-1/2) + result = complexBase.squareRoot(context, angleUnit, target).inverse(context, angleUnit, target); + } else if (r.integerDenominator().isOne() && r.unsignedIntegerNumerator().isLowerThan(ten)) { + if (r.sign() == ExpressionNode::Sign::Positive) { + // (x+iy)^n, n integer positive n < 10 + result = complexBase.powerInteger(r.unsignedIntegerNumerator().extractedInt(), context, angleUnit, target); + } else { + // (x+iy)^(-n), n integer positive n < 10 + result = complexBase.powerInteger(r.unsignedIntegerNumerator().extractedInt(), context, angleUnit, target).inverse(context, angleUnit, target); + } + } + if (!result.isUninitialized()) { + replaceWithInPlace(result); + return result.shallowReduce(context, angleUnit); + } + } + } + // All other cases where one child at least is a ComplexCartesian + if ((base.isReal(context, angleUnit) && index.type() == ExpressionNode::Type::ComplexCartesian) || + (base.type() == ExpressionNode::Type::ComplexCartesian && index.isReal(context, angleUnit)) || + (base.type() == ExpressionNode::Type::ComplexCartesian && index.type() == ExpressionNode::Type::ComplexCartesian)) { + complexBase = base.type() == ExpressionNode::Type::ComplexCartesian ? static_cast(base) : ComplexCartesian::Builder(base, Rational(0)); + complexIndex = index.type() == ExpressionNode::Type::ComplexCartesian ? static_cast(index) : ComplexCartesian::Builder(index, Rational(0)); + result = complexBase.power(complexIndex, context, angleUnit, target); + replaceWithInPlace(result); + return result.shallowReduce(context, angleUnit); + } + /* Step 2: We look for square root and sum of square roots (two terms maximum * so far) at the denominator and move them to the numerator. */ if (target == ExpressionNode::ReductionTarget::User) { From ced136f8432be73612ef544898d462b54a233147 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 14 Dec 2018 12:14:17 +0100 Subject: [PATCH 095/373] [poincare] Fix ComplexCartesian::powerInteger to handle pure imaginary complex --- poincare/src/complex_cartesian.cpp | 20 ++++++++++++++++++++ poincare/src/power.cpp | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/poincare/src/complex_cartesian.cpp b/poincare/src/complex_cartesian.cpp index 44d826e20..3446484cf 100644 --- a/poincare/src/complex_cartesian.cpp +++ b/poincare/src/complex_cartesian.cpp @@ -177,6 +177,26 @@ ComplexCartesian ComplexCartesian::powerInteger(int n, Context & context, Prefer Expression a = real(); Expression b = imag(); assert(n > 0); + assert(!b.isRationalZero()); + + // Special case: a == 0 (otherwise, we are going to introduce undefined expressions - a^0 = NAN) + // (b*i)^n = b^n*i^n with i^n == i, -i, 1 or -1 + if (a.isRationalZero()) { + ComplexCartesian result; + Expression bpow = Power(b, Rational(n)); + if (n/2%2 == 1) { + Expression temp = Multiplication(Rational(-1), bpow); + bpow.shallowReduce(context, angleUnit, target); + bpow = temp; + } + if (n%2 == 0) { + result = ComplexCartesian(bpow, Rational(0)); + } else { + result = ComplexCartesian(Rational(0), bpow); + } + bpow.shallowReduce(context, angleUnit, target); + return result; + } // (a+ib) = a^n+i*b*a^(n-1)+(-1)*b^2*a^(n-2)+(-i)*b^3*a^(n-3)+b^3*a^(n-4)+... // Real part: A = a^n+(-1)*b^2*a^(n-2)+... // Imaginary part: B = b*a^(n-1) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 2b65816db..cfd0076c0 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -384,7 +384,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU Expression base = childAtIndex(0); Expression index = childAtIndex(1); /* Step 0: if both children are true unresolved complexes, the result is not simplified. TODO? */ - if (!base.isReal(context, angleUnit) && !index.isReal(context, angleUnit)) { + if (!base.isReal(context, angleUnit) && base.type() != ExpressionNode::Type::ComplexCartesian && !index.isReal(context, angleUnit) && index.type() != ExpressionNode::Type::ComplexCartesian) { return *this; } From cbef3dadb91d25d54f5e255d41f37f3d4761d229 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 14 Dec 2018 13:49:39 +0100 Subject: [PATCH 096/373] [poincare] Implement real and shallowReduce of ComplexCartesian on nodes: conjugate, function, symbol --- poincare/include/poincare/conjugate.h | 3 ++- poincare/include/poincare/function.h | 1 + poincare/include/poincare/symbol.h | 1 + poincare/include/poincare/symbol_abstract.h | 1 + poincare/src/conjugate.cpp | 16 ++++++++++++++-- poincare/src/function.cpp | 5 +++++ poincare/src/symbol.cpp | 5 +++++ poincare/src/symbol_abstract.cpp | 8 ++++++++ 8 files changed, 37 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/conjugate.h b/poincare/include/poincare/conjugate.h index 4c96ccecc..7c36ee9cc 100644 --- a/poincare/include/poincare/conjugate.h +++ b/poincare/include/poincare/conjugate.h @@ -18,6 +18,7 @@ public: } #endif + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return childAtIndex(0)->isReal(context, angleUnit); } ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override; @@ -46,7 +47,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("conj", 1, &UntypedBuilder);; - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit Conjugate(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/function.h b/poincare/include/poincare/function.h index 95a57169b..aecee8ad5 100644 --- a/poincare/include/poincare/function.h +++ b/poincare/include/poincare/function.h @@ -28,6 +28,7 @@ public: float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override; // Complex + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override; ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override; diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index ec529e55a..989bfef8f 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -27,6 +27,7 @@ public: float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override; // Complex + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override; ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override; diff --git a/poincare/include/poincare/symbol_abstract.h b/poincare/include/poincare/symbol_abstract.h index 97a264760..e5ffb9c2c 100644 --- a/poincare/include/poincare/symbol_abstract.h +++ b/poincare/include/poincare/symbol_abstract.h @@ -80,6 +80,7 @@ protected: SymbolAbstractNode * node() const { return static_cast(Expression::node()); } private: static Expression Expand(const SymbolAbstract & symbol, Context & context, bool clone); + static bool isReal(const SymbolAbstract & symbol, Context & context, Preferences::AngleUnit angleUnit); static ComplexCartesian complexCartesian(const SymbolAbstract & symbol, Context & context, Preferences::AngleUnit angleUnit); static ComplexPolar complexPolar(const SymbolAbstract & symbol, Context & context, Preferences::AngleUnit angleUnit); static size_t AlignedNodeSize(size_t nameLength, size_t nodeSize); diff --git a/poincare/src/conjugate.cpp b/poincare/src/conjugate.cpp index 1ee35cf23..eae04b0ac 100644 --- a/poincare/src/conjugate.cpp +++ b/poincare/src/conjugate.cpp @@ -47,7 +47,7 @@ int ConjugateNode::serialize(char * buffer, int bufferSize, Preferences::PrintFl } Expression ConjugateNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Conjugate(this).shallowReduce(context, angleUnit); + return Conjugate(this).shallowReduce(context, angleUnit, target); } template @@ -55,7 +55,7 @@ Complex ConjugateNode::computeOnComplex(const std::complex c, Preferences: return Complex(std::conj(c)); } -Expression Conjugate::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression Conjugate::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { Expression e = Expression::defaultShallowReduce(context, angleUnit); if (e.isUndefined()) { @@ -68,6 +68,18 @@ Expression Conjugate::shallowReduce(Context & context, Preferences::AngleUnit an return SimplificationHelper::Map(*this, context, angleUnit); } #endif + if (c.isReal(context, angleUnit)) { + replaceWithInPlace(c); + return c; + } + if (c.type() == ExpressionNode::Type::ComplexCartesian) { + ComplexCartesian complexChild = static_cast(c); + Multiplication m(Rational(-1), complexChild.imag()); + complexChild.replaceChildAtIndexInPlace(1, m); + m.shallowReduce(context, angleUnit, target); + replaceWithInPlace(complexChild); + return complexChild; + } if (c.type() == ExpressionNode::Type::Rational) { replaceWithInPlace(c); return c; diff --git a/poincare/src/function.cpp b/poincare/src/function.cpp index 9103f4a85..2d6346f9f 100644 --- a/poincare/src/function.cpp +++ b/poincare/src/function.cpp @@ -14,6 +14,11 @@ ComplexCartesian FunctionNode::complexCartesian(Context & context, Preferences:: return SymbolAbstract::complexCartesian(f, context, angleUnit); } +bool FunctionNode::isReal(Context & context, Preferences::AngleUnit angleUnit) const { + Function f(this); + return SymbolAbstract::isReal(f, context, angleUnit); +} + ComplexPolar FunctionNode::complexPolar(Context & context, Preferences::AngleUnit angleUnit) const { Function f(this); return SymbolAbstract::complexPolar(f, context, angleUnit); diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 1e171fe8d..754f558cc 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -77,6 +77,11 @@ float SymbolNode::characteristicXRange(Context & context, Preferences::AngleUnit return 0.0f; } +bool SymbolNode::isReal(Context & context, Preferences::AngleUnit angleUnit) const { + Symbol s(this); + return SymbolAbstract::isReal(s, context, angleUnit); +} + ComplexCartesian SymbolNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { Symbol s(this); return SymbolAbstract::complexCartesian(s, context, angleUnit); diff --git a/poincare/src/symbol_abstract.cpp b/poincare/src/symbol_abstract.cpp index faea41a33..c8f57e0c9 100644 --- a/poincare/src/symbol_abstract.cpp +++ b/poincare/src/symbol_abstract.cpp @@ -80,6 +80,14 @@ Expression SymbolAbstract::Expand(const SymbolAbstract & symbol, Context & conte return e; } +bool SymbolAbstract::isReal(const SymbolAbstract & symbol, Context & context, Preferences::AngleUnit angleUnit) { + Expression e = SymbolAbstract::Expand(symbol, context, false); + if (e.isUninitialized()) { + return true; + } + return e.isReal(context, angleUnit); +} + ComplexCartesian SymbolAbstract::complexCartesian(const SymbolAbstract & symbol, Context & context, Preferences::AngleUnit angleUnit) { Expression e = SymbolAbstract::Expand(symbol, context, true); if (e.isUninitialized()) { From a6ac075442f679f76e3db5fa558076375457b0ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 14 Dec 2018 14:41:39 +0100 Subject: [PATCH 097/373] [poincare] Fix Expression::CreateComplexExpression --- poincare/include/poincare/expression.h | 2 +- poincare/src/complex.cpp | 2 +- poincare/src/complex_cartesian.cpp | 2 +- poincare/src/expression.cpp | 11 +++++------ 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 8620088b3..66264f43c 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -301,7 +301,7 @@ private: int defaultGetPolynomialCoefficients(Context & context, const char * symbol, Expression expression[]) const; /* Builder */ - static Expression CreateComplexExpression(Expression ra, Expression tb, Preferences::ComplexFormat complexFormat, bool undefined, bool isZeroRa, bool isOneRa, bool isZeroTb, bool isOneTb, bool isMinusOneTb, bool isNegativeRa, bool isNegativeTb); + static Expression CreateComplexExpression(Expression ra, Expression tb, Preferences::ComplexFormat complexFormat, bool undefined, bool isZeroRa, bool isOneRa, bool isZeroTb, bool isOneTb, bool isNegativeRa, bool isNegativeTb); /* Expression roots/extrema solver*/ constexpr static double k_solverPrecision = 1.0E-5; diff --git a/poincare/src/complex.cpp b/poincare/src/complex.cpp index 2897957a8..cb738432b 100644 --- a/poincare/src/complex.cpp +++ b/poincare/src/complex.cpp @@ -55,7 +55,7 @@ Expression ComplexNode::complexToExpression(Preferences::ComplexFormat comple Number::DecimalNumber(std::fabs(tb)), complexFormat, (std::isnan(this->real()) || std::isnan(this->imag())), - ra == 0.0, ra == 1.0, tb == 0.0, tb == 1.0, tb == -1.0, ra < 0.0, tb < 0.0 + ra == 0.0, std::fabs(ra) == 1.0, tb == 0.0, std::fabs(tb) == 1.0, ra < 0.0, tb < 0.0 ); } diff --git a/poincare/src/complex_cartesian.cpp b/poincare/src/complex_cartesian.cpp index 3446484cf..99d9414ec 100644 --- a/poincare/src/complex_cartesian.cpp +++ b/poincare/src/complex_cartesian.cpp @@ -55,7 +55,7 @@ Expression ComplexCartesian::shallowBeautify(Context & context, Preferences::Ang b = oppositeB.isUninitialized() ? b : oppositeB; Expression e = Expression::CreateComplexExpression(a, b, Preferences::ComplexFormat::Cartesian, a.type() == ExpressionNode::Type::Undefined || b.type() == ExpressionNode::Type::Undefined, - isZero(a), isOne(a), isZero(b), isOne(b), isMinusOne(b), + isZero(a), isOne(a), isZero(b), isOne(b), !oppositeA.isUninitialized(), !oppositeB.isUninitialized() ); diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 4719db2d6..c4b6e2340 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -501,7 +501,7 @@ U Expression::epsilon() { /* Builder */ -Expression Expression::CreateComplexExpression(Expression ra, Expression tb, Preferences::ComplexFormat complexFormat, bool undefined, bool isZeroRa, bool isOneRa, bool isZeroTb, bool isOneTb, bool isMinusOneTb, bool isNegativeRa, bool isNegativeTb) { +Expression Expression::CreateComplexExpression(Expression ra, Expression tb, Preferences::ComplexFormat complexFormat, bool undefined, bool isZeroRa, bool isOneRa, bool isZeroTb, bool isOneTb, bool isNegativeRa, bool isNegativeTb) { if (undefined) { return Undefined(); } @@ -518,7 +518,7 @@ Expression Expression::CreateComplexExpression(Expression ra, Expression tb, Pre } } if (!isZeroTb) { - if (isOneTb || isMinusOneTb) { + if (isOneTb) { imag = Constant(Ion::Charset::IComplex); } else { imag = Multiplication(tb , Constant(Ion::Charset::IComplex)); @@ -551,13 +551,12 @@ Expression Expression::CreateComplexExpression(Expression ra, Expression tb, Pre Expression arg; if (isOneTb) { arg = Constant(Ion::Charset::IComplex); - } else if (isMinusOneTb) { - arg = Opposite(Constant(Ion::Charset::IComplex)); - } else if (isNegativeTb) { - arg = Opposite(Multiplication(tb, Constant(Ion::Charset::IComplex))); } else { arg = Multiplication(tb, Constant(Ion::Charset::IComplex)); } + if (isNegativeTb) { + arg = Opposite(arg); + } exp = Power(Constant(Ion::Charset::Exponential), arg); } if (exp.isUninitialized()) { From 4b45d40bf87a5623d56713b5566af624396d40bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 14 Dec 2018 16:45:28 +0100 Subject: [PATCH 098/373] [poincare] Fix Expression::degreeToRadian --- poincare/src/expression.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index c4b6e2340..e430f174e 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -427,7 +427,7 @@ Expression Expression::radianToDegree() { Expression Expression::degreeToRadian() { // e*Pi/180 - return Multiplication(*this, Power(Rational(180), Rational(-1)), Constant(Ion::Charset::SmallPi)); + return Multiplication(*this, Rational(1, 180), Constant(Ion::Charset::SmallPi)); } Expression Expression::reduce(Context & context, Preferences::AngleUnit angleUnit) { From 383ac004cf84f69a1278b04a527e81b1821a4464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 14 Dec 2018 16:45:49 +0100 Subject: [PATCH 099/373] [poincare] Take into account complex format in simplify --- apps/calculation/calculation.cpp | 4 +-- apps/shared/poincare_helpers.h | 4 +-- apps/solver/equation_store.cpp | 2 +- poincare/include/poincare/expression.h | 9 ++++-- poincare/src/complex_cartesian.cpp | 13 +------- poincare/src/expression.cpp | 42 ++++++++++++++++++++++---- 6 files changed, 48 insertions(+), 26 deletions(-) diff --git a/apps/calculation/calculation.cpp b/apps/calculation/calculation.cpp index 7f07d3ed1..631cc295a 100644 --- a/apps/calculation/calculation.cpp +++ b/apps/calculation/calculation.cpp @@ -174,11 +174,11 @@ Calculation::EqualSign Calculation::exactAndApproximateDisplayedOutputsAreEqual( constexpr int bufferSize = Constant::MaxSerializedExpressionSize; char buffer[bufferSize]; Preferences * preferences = Preferences::sharedPreferences(); - Expression exactOutputExpression = Expression::ParseAndSimplify(m_exactOutputText, *context, preferences->angleUnit()); + Expression exactOutputExpression = PoincareHelpers::ParseAndSimplify(m_exactOutputText, *context); if (exactOutputExpression.isUninitialized()) { exactOutputExpression = Undefined(); } - m_equalSign = exactOutputExpression.isEqualToItsApproximationLayout(approximateOutput(context), buffer, bufferSize, preferences->angleUnit(), preferences->displayMode(), preferences->numberOfSignificantDigits(), *context) ? EqualSign::Equal : EqualSign::Approximation; + m_equalSign = exactOutputExpression.isEqualToItsApproximationLayout(approximateOutput(context), buffer, bufferSize, preferences->angleUnit(), preferences->complexFormat(), preferences->displayMode(), preferences->numberOfSignificantDigits(), *context) ? EqualSign::Equal : EqualSign::Approximation; return m_equalSign; } diff --git a/apps/shared/poincare_helpers.h b/apps/shared/poincare_helpers.h index a9a2b9ef6..3e89dadcf 100644 --- a/apps/shared/poincare_helpers.h +++ b/apps/shared/poincare_helpers.h @@ -38,11 +38,11 @@ inline T ApproximateToScalar(const char * text, Poincare::Context & context) { } inline Poincare::Expression ParseAndSimplify(const char * text, Poincare::Context & context) { - return Poincare::Expression::ParseAndSimplify(text, context, Poincare::Preferences::sharedPreferences()->angleUnit()); + return Poincare::Expression::ParseAndSimplify(text, context, Poincare::Preferences::sharedPreferences()->angleUnit(), Poincare::Preferences::sharedPreferences()->complexFormat()); } inline void Simplify(Poincare::Expression * e, Poincare::Context & context) { - *e = e->simplify(context, Poincare::Preferences::sharedPreferences()->angleUnit()); + *e = e->simplify(context, Poincare::Preferences::sharedPreferences()->angleUnit(), Poincare::Preferences::sharedPreferences()->complexFormat()); } } diff --git a/apps/solver/equation_store.cpp b/apps/solver/equation_store.cpp index 1dea69d30..6ad5830d5 100644 --- a/apps/solver/equation_store.cpp +++ b/apps/solver/equation_store.cpp @@ -182,7 +182,7 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) { /* Check for equality between exact and approximate layouts */ if (!m_exactSolutionIdentity[i]) { char buffer[Shared::ExpressionModel::k_expressionBufferSize]; - m_exactSolutionEquality[i] = exactSolutions[i].isEqualToItsApproximationLayout(approximate, buffer, Shared::ExpressionModel::k_expressionBufferSize, preferences->angleUnit(), preferences->displayMode(), preferences->numberOfSignificantDigits(), *context); + m_exactSolutionEquality[i] = exactSolutions[i].isEqualToItsApproximationLayout(approximate, buffer, Shared::ExpressionModel::k_expressionBufferSize, preferences->angleUnit(), preferences->complexFormat(), preferences->displayMode(), preferences->numberOfSignificantDigits(), *context); } } } diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 66264f43c..3ff918930 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -177,15 +177,15 @@ public: * same structures and all their nodes have same types and values (ie, * sqrt(pi^2) is NOT identical to pi). */ bool isIdenticalTo(const Expression e) const; - bool isEqualToItsApproximationLayout(Expression approximation, char * buffer, int bufferSize, Preferences::AngleUnit angleUnit, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits, Context & context); + bool isEqualToItsApproximationLayout(Expression approximation, char * buffer, int bufferSize, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits, Context & context); /* Layout Helper */ Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const; /* Simplification */ - static Expression ParseAndSimplify(const char * text, Context & context, Preferences::AngleUnit angleUnit); - Expression simplify(Context & context, Preferences::AngleUnit angleUnit); + static Expression ParseAndSimplify(const char * text, Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat); + Expression simplify(Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat); Expression reduce(Context & context, Preferences::AngleUnit angleUnit); static Expression ExpressionWithoutSymbols(Expression expressionWithSymbols, Context & context); Expression radianToDegree(); @@ -301,6 +301,9 @@ private: int defaultGetPolynomialCoefficients(Context & context, const char * symbol, Expression expression[]) const; /* Builder */ + static bool isZero(const Expression e); + static bool isOne(const Expression e); + static bool isMinusOne(const Expression e); static Expression CreateComplexExpression(Expression ra, Expression tb, Preferences::ComplexFormat complexFormat, bool undefined, bool isZeroRa, bool isOneRa, bool isZeroTb, bool isOneTb, bool isNegativeRa, bool isNegativeTb); /* Expression roots/extrema solver*/ diff --git a/poincare/src/complex_cartesian.cpp b/poincare/src/complex_cartesian.cpp index 99d9414ec..96274f56b 100644 --- a/poincare/src/complex_cartesian.cpp +++ b/poincare/src/complex_cartesian.cpp @@ -26,17 +26,6 @@ Expression ComplexCartesianNode::shallowBeautify(Context & context, Preferences: return ComplexCartesian(this).shallowBeautify(context, angleUnit); } - -bool isZero(const Expression e) { - return e.type() == ExpressionNode::Type::Rational && static_cast(e).isZero(); -} -bool isOne(const Expression e) { - return e.type() == ExpressionNode::Type::Rational && static_cast(e).isOne(); -} -bool isMinusOne(const Expression e) { - return e.type() == ExpressionNode::Type::Rational && static_cast(e).isMinusOne(); -} - Expression ComplexCartesian::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { if (imag().isRationalZero()) { Expression r = real(); @@ -55,7 +44,7 @@ Expression ComplexCartesian::shallowBeautify(Context & context, Preferences::Ang b = oppositeB.isUninitialized() ? b : oppositeB; Expression e = Expression::CreateComplexExpression(a, b, Preferences::ComplexFormat::Cartesian, a.type() == ExpressionNode::Type::Undefined || b.type() == ExpressionNode::Type::Undefined, - isZero(a), isOne(a), isZero(b), isOne(b), + Expression::isZero(a), Expression::isOne(a), Expression::isZero(b), Expression::isOne(b), !oppositeA.isUninitialized(), !oppositeB.isUninitialized() ); diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index e430f174e..d072da896 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -343,7 +343,7 @@ bool Expression::isIdenticalTo(const Expression e) const { return ExpressionNode::SimplificationOrder(node(), e.node(), true) == 0; } -bool Expression::isEqualToItsApproximationLayout(Expression approximation, char * buffer, int bufferSize, Preferences::AngleUnit angleUnit, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits, Context & context) { +bool Expression::isEqualToItsApproximationLayout(Expression approximation, char * buffer, int bufferSize, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits, Context & context) { approximation.serialize(buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits); /* Warning: we cannot use directly the the approximate expression but we have * to re-serialize it because the number of stored significative @@ -351,7 +351,7 @@ bool Expression::isEqualToItsApproximationLayout(Expression approximation, char * identical. (For example, 0.000025 might be displayed "0.00003" and stored * as Decimal(0.000025) and isEqualToItsApproximationLayout should return * false) */ - Expression approximateOutput = Expression::ParseAndSimplify(buffer, context, angleUnit); + Expression approximateOutput = Expression::ParseAndSimplify(buffer, context, angleUnit, complexFormat); bool equal = isIdenticalTo(approximateOutput); return equal; } @@ -366,12 +366,12 @@ int Expression::serialize(char * buffer, int bufferSize, Preferences::PrintFloat /* Simplification */ -Expression Expression::ParseAndSimplify(const char * text, Context & context, Preferences::AngleUnit angleUnit) { +Expression Expression::ParseAndSimplify(const char * text, Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) { Expression exp = Parse(text); if (exp.isUninitialized()) { return Undefined(); } - exp = exp.simplify(context, angleUnit); + exp = exp.simplify(context, angleUnit, complexFormat); /* simplify might have been interrupted, in which case the resulting * expression is uninitialized, so we need to check that. */ if (exp.isUninitialized()) { @@ -380,11 +380,31 @@ Expression Expression::ParseAndSimplify(const char * text, Context & context, Pr return exp; } -Expression Expression::simplify(Context & context, Preferences::AngleUnit angleUnit) { +void makePositive(Expression * e, bool * isNegative) { + if (e->type() == ExpressionNode::Type::Opposite) { + *isNegative = true; + *e = e->childAtIndex(0); + } +} + +Expression Expression::simplify(Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) { sSimplificationHasBeenInterrupted = false; Expression e = deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); if (!sSimplificationHasBeenInterrupted) { - e = e.deepBeautify(context, angleUnit); + if (e.type() == ExpressionNode::Type::ComplexCartesian) { + ComplexCartesian ecomplex = static_cast(e); + Expression ra = complexFormat == Preferences::ComplexFormat::Cartesian ? ecomplex.real() : ecomplex.clone().convert().norm(context, angleUnit, ExpressionNode::ReductionTarget::User).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); + Expression tb = complexFormat == Preferences::ComplexFormat::Cartesian ? ecomplex.imag() : ecomplex.argument(context, angleUnit, ExpressionNode::ReductionTarget::User).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); + ra = ra.deepBeautify(context, angleUnit); + tb = tb.deepBeautify(context, angleUnit); + bool raIsNegative = false; + bool tbIsNegative = false; + makePositive(&ra, &raIsNegative); + makePositive(&tb, &tbIsNegative); + e = CreateComplexExpression(ra, tb, complexFormat, ra.type() == ExpressionNode::Type::Undefined || tb.type() == ExpressionNode::Type::Undefined, isZero(ra), isOne(ra), isZero(tb), isOne(tb), raIsNegative, tbIsNegative); + } else { + e = e.deepBeautify(context, angleUnit); + } } return sSimplificationHasBeenInterrupted ? Expression() : e; } @@ -501,6 +521,16 @@ U Expression::epsilon() { /* Builder */ +bool Expression::isZero(const Expression e) { + return e.type() == ExpressionNode::Type::Rational && static_cast(e).isZero(); +} +bool Expression::isOne(const Expression e) { + return e.type() == ExpressionNode::Type::Rational && static_cast(e).isOne(); +} +bool Expression::isMinusOne(const Expression e) { + return e.type() == ExpressionNode::Type::Rational && static_cast(e).isMinusOne(); +} + Expression Expression::CreateComplexExpression(Expression ra, Expression tb, Preferences::ComplexFormat complexFormat, bool undefined, bool isZeroRa, bool isOneRa, bool isZeroTb, bool isOneTb, bool isNegativeRa, bool isNegativeTb) { if (undefined) { return Undefined(); From 5b782c3ff7c06f8af17aa2a4edc756d3fca194ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 17 Dec 2018 10:22:04 +0100 Subject: [PATCH 100/373] [poincare] Power: fix sqrt(-1*i) != i*sqrt(i) --- poincare/src/power.cpp | 2 ++ poincare/test/power.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index cfd0076c0..9d7de229d 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -553,7 +553,9 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU } } // (a)^(1/2) with a < 0 --> i*(-a)^(1/2) + // WARNING: this rule true only if a real (ex: (-1*i)^(1/2) != i*i^(1/2) if (!letPowerAtRoot + && childAtIndex(0).isReal(context, angleUnit) && childAtIndex(1).type() == ExpressionNode::Type::Rational && childAtIndex(1).convert().isHalf()) { diff --git a/poincare/test/power.cpp b/poincare/test/power.cpp index 50fc3871b..027d828a6 100644 --- a/poincare/test/power.cpp +++ b/poincare/test/power.cpp @@ -52,6 +52,7 @@ QUIZ_CASE(poincare_power_simplify) { assert_parsed_expression_simplify_to("(12^4*x)^(0.5)", "144*R(x)"); assert_parsed_expression_simplify_to("R(32)", "4*R(2)"); assert_parsed_expression_simplify_to("R(-1)", "I"); + assert_parsed_expression_simplify_to("R(-1*R(-1))", "R(2)/2-R(2)/2*I"); assert_parsed_expression_simplify_to("R(3^2)", "3"); assert_parsed_expression_simplify_to("2^(2+P)", "4*2^P"); assert_parsed_expression_simplify_to("R(5513219850886344455940081)", "2348024669991"); From 68b6d4211bf0a7ff46190248fd00c3f0874a70cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 17 Dec 2018 10:36:30 +0100 Subject: [PATCH 101/373] [poincare] Power: improve isReal --- poincare/src/power.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 9d7de229d..d7b4dc5b8 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -81,7 +81,14 @@ int PowerNode::getPolynomialCoefficients(Context & context, const char * symbolN bool PowerNode::isReal(Context & context, Preferences::AngleUnit angleUnit) const { ExpressionNode * base = childAtIndex(0); - if (base->isReal(context, angleUnit) && base->sign(&context, angleUnit) == Sign::Positive && childAtIndex(1)->isReal(context, angleUnit)) { + ExpressionNode * index = childAtIndex(1); + // Both base and index are real and: + // - either base > 0 + // - or index is an integer + if (base->isReal(context, angleUnit) && + index->isReal(context, angleUnit) && + (base->sign(&context, angleUnit) == Sign::Positive || + (index->type() == ExpressionNode::Type::Rational && static_cast(index)->denominator().isOne()))) { return true; } return false; From cbd4f4453956f045f08fda3eee3c0e62a5d925d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 17 Dec 2018 11:24:44 +0100 Subject: [PATCH 102/373] [poincare] SignFunction: improve shallowReduce: sign(-x) = -sign(x) --- poincare/include/poincare/sign_function.h | 2 +- poincare/src/complex_cartesian.cpp | 2 +- poincare/src/complex_helper.cpp | 4 ++-- poincare/src/sign_function.cpp | 26 +++++++++++++++++------ poincare/src/square_root.cpp | 2 +- 5 files changed, 25 insertions(+), 11 deletions(-) diff --git a/poincare/include/poincare/sign_function.h b/poincare/include/poincare/sign_function.h index 36f476252..d2a845c0d 100644 --- a/poincare/include/poincare/sign_function.h +++ b/poincare/include/poincare/sign_function.h @@ -51,7 +51,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("sign", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit SignFunction(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/src/complex_cartesian.cpp b/poincare/src/complex_cartesian.cpp index 96274f56b..289939dc0 100644 --- a/poincare/src/complex_cartesian.cpp +++ b/poincare/src/complex_cartesian.cpp @@ -94,7 +94,7 @@ Expression ComplexCartesian::argument(Context & context, Preferences::AngleUnit return sub; } else { // if b == 0, argument = (1-sign(a))*Pi/2 - Expression signa = SignFunction::Builder(a).shallowReduce(context, angleUnit); + Expression signa = SignFunction::Builder(a).shallowReduce(context, angleUnit, target); Subtraction sub(Rational(1), signa); signa.shallowReduce(context, angleUnit, target); Multiplication mul(Rational(1,2), Constant(Ion::Charset::SmallPi), sub); diff --git a/poincare/src/complex_helper.cpp b/poincare/src/complex_helper.cpp index e8e0541ec..4ad679be6 100644 --- a/poincare/src/complex_helper.cpp +++ b/poincare/src/complex_helper.cpp @@ -96,7 +96,7 @@ ComplexPolar ComplexHelper::complexPolarFromComplexCartesian(const ExpressionNod // Then, compute sign(b) * Pi/2 - arctan(a/b) argument = Subtraction( Multiplication( - SignFunction::Builder(b).shallowReduce(context, angleUnit), + SignFunction::Builder(b).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation), Division(Constant(Ion::Charset::SmallPi), Rational(2)).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation) ).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation), arcTangent @@ -106,7 +106,7 @@ ComplexPolar ComplexHelper::complexPolarFromComplexCartesian(const ExpressionNod argument = Multiplication( Subtraction( Rational(1), - SignFunction::Builder(a).shallowReduce(context, angleUnit) + SignFunction::Builder(a).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation) ).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation), Division(Constant(Ion::Charset::SmallPi), Rational(2)).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation) ).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); diff --git a/poincare/src/sign_function.cpp b/poincare/src/sign_function.cpp index 7b4e3acd1..dac3de99b 100644 --- a/poincare/src/sign_function.cpp +++ b/poincare/src/sign_function.cpp @@ -32,7 +32,7 @@ int SignFunctionNode::serialize(char * buffer, int bufferSize, Preferences::Prin } Expression SignFunctionNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return SignFunction(this).shallowReduce(context, angleUnit); + return SignFunction(this).shallowReduce(context, angleUnit, target); } template @@ -46,7 +46,7 @@ Complex SignFunctionNode::computeOnComplex(const std::complex c, Preferenc return Complex(1.0); } -Expression SignFunction::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression SignFunction::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { Expression e = Expression::defaultShallowReduce(context, angleUnit); if (e.isUndefined()) { @@ -59,16 +59,30 @@ Expression SignFunction::shallowReduce(Context & context, Preferences::AngleUnit } #endif Rational one(1); - if (childAtIndex(0).sign(&context, angleUnit) != ExpressionNode::Sign::Unknown) { - if (childAtIndex(0).sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { + Expression child = childAtIndex(0); + ExpressionNode::Sign s = child.sign(&context, angleUnit); + if (s != ExpressionNode::Sign::Unknown) { + if (s == ExpressionNode::Sign::Negative) { one = Rational(-1); } } else { - Evaluation childApproximated = childAtIndex(0).node()->approximate(1.0f, context, angleUnit); + Evaluation childApproximated = child.node()->approximate(1.0f, context, angleUnit); assert(childApproximated.type() == EvaluationNode::Type::Complex); Complex c = static_cast&>(childApproximated); + // c has no sign (c is complex or NAN) if (std::isnan(c.imag()) || std::isnan(c.real()) || c.imag() != 0) { - return *this; + // sign(-x) = sign(x) + Expression oppChild = child.makePositiveAnyNegativeNumeralFactor(context, angleUnit); + if (oppChild.isUninitialized()) { + return *this; + } else { + Expression sign = *this; + Multiplication m(Rational(-1)); + replaceWithInPlace(m); + m.addChildAtIndexInPlace(sign, 1, 1); + sign.shallowReduce(context, angleUnit, target); + return m.shallowReduce(context, angleUnit, target); + } } if (c.real() < 0) { one = Rational(-1); diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index a42e94719..663cb6d5c 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -62,7 +62,7 @@ ComplexCartesian SquareRootNode::complexCartesian(Context & context, Preferences // a = sqrt(x^2+y^2)+x Multiplication real = complexCartesianHelper(Addition(norm.clone(), x.clone()), context, angleUnit); Multiplication imag = complexCartesianHelper(Subtraction(norm, x), context, angleUnit); - imag.addChildAtIndexInPlace(SignFunction::Builder(y).shallowReduce(context, angleUnit), imag.numberOfChildren(), imag.numberOfChildren()); + imag.addChildAtIndexInPlace(SignFunction::Builder(y).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation), imag.numberOfChildren(), imag.numberOfChildren()); return ComplexCartesian::Builder( real.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), imag.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) From 2f8a65d04c495cb604e315df150aca3b59628dfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 17 Dec 2018 11:25:22 +0100 Subject: [PATCH 103/373] [poincare] Improve shallowReduce of AbsoluteValue, ComplexArgument, ImaginaryPart, RealPart --- poincare/src/absolute_value.cpp | 26 ++++++++++++++++++++------ poincare/src/complex_argument.cpp | 30 ++++++++++++++++++++++++------ poincare/src/imaginary_part.cpp | 13 ++++++------- poincare/src/real_part.cpp | 13 ++++++------- 4 files changed, 56 insertions(+), 26 deletions(-) diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 0a27a5718..44c45e734 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -47,13 +47,27 @@ Expression AbsoluteValue::shallowReduce(Context & context, Preferences::AngleUni #endif #endif Expression c = childAtIndex(0); - ComplexPolar polar = c.complexPolar(context, angleUnit); - if (!polar.isUninitialized()) { - Expression n = polar.norm(); - replaceWithInPlace(n); - // We have to deepReduce because the complexPolar function returns an Expression reduced only BottomUp - return n.deepReduce(context, angleUnit, target); + if (c.isReal(context, angleUnit)) { + float app = c.approximateToScalar(context, angleUnit); + if (!std::isnan(app) && app >= 0) { + // abs(a) = a with a > 0 + replaceWithInPlace(c); + return c; + } else if (!std::isnan(app) && app < 0) { + // abs(a) = -a with a < 0 + Multiplication m(Rational(-1), c); + replaceWithInPlace(m); + return m.shallowReduce(context, angleUnit, target); + } } + if (c.type() == ExpressionNode::Type::ComplexCartesian) { + ComplexCartesian complexChild = static_cast(c); + Expression childNorm = complexChild.norm(context, angleUnit, target); + replaceWithInPlace(childNorm); + return childNorm.shallowReduce(context, angleUnit, target); + } + // abs(-x) = abs(x) + c.makePositiveAnyNegativeNumeralFactor(context, angleUnit); return *this; } diff --git a/poincare/src/complex_argument.cpp b/poincare/src/complex_argument.cpp index 8e70e417c..fa0b69ae8 100644 --- a/poincare/src/complex_argument.cpp +++ b/poincare/src/complex_argument.cpp @@ -2,6 +2,8 @@ #include #include #include +#include +#include extern "C" { #include } @@ -43,12 +45,28 @@ Expression ComplexArgument::shallowReduce(Context & context, Preferences::AngleU return SimplificationHelper::Map(*this, context, angleUnit); } #endif - ComplexPolar polar = c.complexPolar(context, angleUnit); - if (!polar.isUninitialized()) { - Expression a = polar.arg(); - replaceWithInPlace(a); - // We have to deepReduce because the complexPolar function returns an Expression reduced only BottomUp - return a.deepReduce(context, angleUnit, target); + if (c.isReal(context, angleUnit)) { + float app = c.approximateToScalar(context, angleUnit); + if (std::isnan(app)) { + ComplexCartesian complexChild = ComplexCartesian::Builder(c, Rational(0)); + Expression arg = complexChild.argument(context, angleUnit, target); + replaceWithInPlace(arg); + return arg.shallowReduce(context, angleUnit, target); + } else if (app >= 0) { + Expression result = Rational(0); + replaceWithInPlace(result); + return result; + } + assert(app < 0); + Expression result = Constant(Ion::Charset::SmallPi); + replaceWithInPlace(result); + return result; + } + if (c.type() == ExpressionNode::Type::ComplexCartesian) { + ComplexCartesian complexChild = static_cast(c); + Expression childArg = complexChild.argument(context, angleUnit, target); + replaceWithInPlace(childArg); + return childArg.shallowReduce(context, angleUnit, target); } return *this; } diff --git a/poincare/src/imaginary_part.cpp b/poincare/src/imaginary_part.cpp index 4c7f494a4..f8ae8fe45 100644 --- a/poincare/src/imaginary_part.cpp +++ b/poincare/src/imaginary_part.cpp @@ -36,17 +36,16 @@ Expression ImaginaryPart::shallowReduce(Context & context, Preferences::AngleUni return SimplificationHelper::Map(*this, context, angleUnit); } #endif - if (c.type() == ExpressionNode::Type::Rational) { + if (c.isReal(context, angleUnit)) { Expression result = Rational(0); replaceWithInPlace(result); return result; } - ComplexCartesian cartesian = c.complexCartesian(context, angleUnit); - if (!cartesian.isUninitialized()) { - Expression im = cartesian.imag(); - replaceWithInPlace(im); - // We have to deepReduce because the complexCartesian function returns an Expression reduced only BottomUp - return im.deepReduce(context, angleUnit, target); + if (c.type() == ExpressionNode::Type::ComplexCartesian) { + ComplexCartesian complexChild = static_cast(c); + Expression i = complexChild.imag(); + replaceWithInPlace(i); + return i.shallowReduce(context, angleUnit, target); } return *this; } diff --git a/poincare/src/real_part.cpp b/poincare/src/real_part.cpp index 696a09f61..3bd0b688c 100644 --- a/poincare/src/real_part.cpp +++ b/poincare/src/real_part.cpp @@ -36,16 +36,15 @@ Expression RealPart::shallowReduce(Context & context, Preferences::AngleUnit ang return SimplificationHelper::Map(*this, context, angleUnit); } #endif - if (c.type() == ExpressionNode::Type::Rational) { + if (c.isReal(context, angleUnit)) { replaceWithInPlace(c); return c; } - ComplexCartesian cartesian = c.complexCartesian(context, angleUnit); - if (!cartesian.isUninitialized()) { - Expression re = cartesian.real(); - replaceWithInPlace(re); - // We have to deepReduce because the complexCartesian function returns an Expression reduced only BottomUp - return re.deepReduce(context, angleUnit, target); + if (c.type() == ExpressionNode::Type::ComplexCartesian) { + ComplexCartesian complexChild = static_cast(c); + Expression r = complexChild.real(); + replaceWithInPlace(r); + return r.shallowReduce(context, angleUnit, target); } return *this; } From 4a7a95fddf6b66d6f9e99511a397618013fb07d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 17 Dec 2018 11:25:42 +0100 Subject: [PATCH 104/373] [poincare] ComplexCartesian: improve norm on real numbers --- poincare/src/complex_cartesian.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/poincare/src/complex_cartesian.cpp b/poincare/src/complex_cartesian.cpp index 289939dc0..31aa56698 100644 --- a/poincare/src/complex_cartesian.cpp +++ b/poincare/src/complex_cartesian.cpp @@ -64,6 +64,17 @@ Expression ComplexCartesian::squareNorm(Context & context, Preferences::AngleUni } Expression ComplexCartesian::norm(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + if (imag().isRationalZero()) { + Expression a = real(); + ExpressionNode::Sign s = a.sign(&context, angleUnit); + if (s == ExpressionNode::Sign::Positive) { + // Case 1: the expression is positive real + return a;; + } else if (s == ExpressionNode::Sign::Negative) { + // Case 2: the argument is negative real + return a.setSign(ExpressionNode::Sign::Positive, &context, angleUnit); + } + } Expression n2 = squareNorm(context, angleUnit, target); Expression n = SquareRoot::Builder(n2); n2.shallowReduce(context, angleUnit, target); From 8a00aa16cca5a735396c4ec22f095fdfa82d5802 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 17 Dec 2018 11:38:53 +0100 Subject: [PATCH 105/373] [poincare] Clean: remove complexCartesian and complexPolar methods --- poincare/Makefile | 1 - poincare/include/poincare/absolute_value.h | 2 - poincare/include/poincare/addition.h | 3 - poincare/include/poincare/arc_tangent.h | 2 - .../include/poincare/binomial_coefficient.h | 2 - poincare/include/poincare/ceiling.h | 2 - poincare/include/poincare/complex_argument.h | 2 - poincare/include/poincare/complex_helper.h | 24 ---- poincare/include/poincare/complex_polar.h | 47 ------- .../include/poincare/confidence_interval.h | 4 - poincare/include/poincare/conjugate.h | 2 - poincare/include/poincare/constant.h | 1 - poincare/include/poincare/cosine.h | 2 - poincare/include/poincare/decimal.h | 1 - poincare/include/poincare/derivative.h | 2 - poincare/include/poincare/division.h | 8 -- poincare/include/poincare/division_quotient.h | 2 - .../include/poincare/division_remainder.h | 2 - poincare/include/poincare/expression.h | 3 - poincare/include/poincare/expression_node.h | 2 - poincare/include/poincare/factorial.h | 2 - poincare/include/poincare/floor.h | 2 - poincare/include/poincare/frac_part.h | 2 - poincare/include/poincare/function.h | 2 - .../include/poincare/great_common_divisor.h | 2 - poincare/include/poincare/imaginary_part.h | 2 - poincare/include/poincare/integral.h | 2 - .../include/poincare/least_common_multiple.h | 2 - poincare/include/poincare/matrix_dimension.h | 4 - poincare/include/poincare/multiplication.h | 9 -- poincare/include/poincare/nth_root.h | 5 - poincare/include/poincare/number.h | 2 - poincare/include/poincare/opposite.h | 4 - poincare/include/poincare/parenthesis.h | 5 - .../include/poincare/permute_coefficient.h | 3 - poincare/include/poincare/power.h | 2 - .../include/poincare/prediction_interval.h | 4 - poincare/include/poincare/randint.h | 2 - poincare/include/poincare/random.h | 2 - poincare/include/poincare/real_part.h | 2 - poincare/include/poincare/round.h | 2 - poincare/include/poincare/sign_function.h | 2 - poincare/include/poincare/sine.h | 2 - poincare/include/poincare/square_root.h | 10 -- poincare/include/poincare/subtraction.h | 3 - poincare/include/poincare/symbol.h | 2 - poincare/include/poincare/symbol_abstract.h | 2 - poincare/include/poincare/tangent.h | 2 - poincare/include/poincare/undefined.h | 2 +- poincare/src/absolute_value.cpp | 1 + poincare/src/addition.cpp | 25 +--- poincare/src/complex_argument.cpp | 1 + poincare/src/complex_helper.cpp | 132 ------------------ poincare/src/conjugate.cpp | 23 --- poincare/src/constant.cpp | 8 +- poincare/src/division.cpp | 41 ------ poincare/src/expression.cpp | 20 --- poincare/src/expression_node.cpp | 10 -- poincare/src/function.cpp | 10 -- poincare/src/imaginary_part.cpp | 1 + poincare/src/multiplication.cpp | 61 -------- poincare/src/nth_root.cpp | 41 ------ poincare/src/opposite.cpp | 22 --- poincare/src/power.cpp | 44 ------ poincare/src/real_part.cpp | 1 + poincare/src/sign_function.cpp | 1 + poincare/src/square_root.cpp | 51 ------- poincare/src/subtraction.cpp | 13 -- poincare/src/symbol.cpp | 10 -- poincare/src/symbol_abstract.cpp | 18 --- poincare/src/tree_pool.cpp | 1 - 71 files changed, 8 insertions(+), 728 deletions(-) delete mode 100644 poincare/include/poincare/complex_helper.h delete mode 100644 poincare/include/poincare/complex_polar.h delete mode 100644 poincare/src/complex_helper.cpp diff --git a/poincare/Makefile b/poincare/Makefile index 17fede897..816a3a53f 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -50,7 +50,6 @@ objs += $(addprefix poincare/src/,\ complex.o\ complex_argument.o\ complex_cartesian.o\ - complex_helper.o\ confidence_interval.o\ conjugate.o\ constant.o\ diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 7e33f4660..973f8df7a 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -4,7 +4,6 @@ #include #include #include -#include namespace Poincare { @@ -25,7 +24,6 @@ public: Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } // Approximation diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 51004ba94..ca822b7a5 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -27,9 +27,6 @@ public: int polynomialDegree(Context & context, const char * symbolName) const override; int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const override; - // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; - // Evaluation template static Complex compute(const std::complex c, const std::complex d) { return Complex(c+d); } template static MatrixComplex computeOnMatrices(const MatrixComplex m, const MatrixComplex n) { diff --git a/poincare/include/poincare/arc_tangent.h b/poincare/include/poincare/arc_tangent.h index 5175dc1c0..f581c2e0e 100644 --- a/poincare/include/poincare/arc_tangent.h +++ b/poincare/include/poincare/arc_tangent.h @@ -2,7 +2,6 @@ #define POINCARE_ARC_TANGENT_H #include -#include #include #include @@ -24,7 +23,6 @@ public: Type type() const override { return Type::ArcTangent; } // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianComplexFunction(this, context, angleUnit); } bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return childAtIndex(0)->isReal(context, angleUnit); } private: diff --git a/poincare/include/poincare/binomial_coefficient.h b/poincare/include/poincare/binomial_coefficient.h index da1c17ecd..9dcebba2c 100644 --- a/poincare/include/poincare/binomial_coefficient.h +++ b/poincare/include/poincare/binomial_coefficient.h @@ -3,7 +3,6 @@ #include #include -#include namespace Poincare { @@ -20,7 +19,6 @@ public: #endif // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } // Properties diff --git a/poincare/include/poincare/ceiling.h b/poincare/include/poincare/ceiling.h index 91da42199..9d1bb78f5 100644 --- a/poincare/include/poincare/ceiling.h +++ b/poincare/include/poincare/ceiling.h @@ -3,7 +3,6 @@ #include #include -#include namespace Poincare { @@ -20,7 +19,6 @@ public: #endif // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } // Properties diff --git a/poincare/include/poincare/complex_argument.h b/poincare/include/poincare/complex_argument.h index 891bd222b..fa751d591 100644 --- a/poincare/include/poincare/complex_argument.h +++ b/poincare/include/poincare/complex_argument.h @@ -3,7 +3,6 @@ #include #include -#include namespace Poincare { @@ -19,7 +18,6 @@ public: } #endif // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } // Properties diff --git a/poincare/include/poincare/complex_helper.h b/poincare/include/poincare/complex_helper.h deleted file mode 100644 index 78553d079..000000000 --- a/poincare/include/poincare/complex_helper.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef POINCARE_COMPLEX_HELPER_H -#define POINCARE_COMPLEX_HELPER_H - -#include -#include -#include - -namespace Poincare { - -class ComplexHelper { -public: - static ComplexCartesian complexCartesianComplexFunction(const ExpressionNode * e, Context & context, Preferences::AngleUnit angleUnit); - static ComplexCartesian complexCartesianRealFunction(const ExpressionNode * e, Context & context, Preferences::AngleUnit angleUnit); - // static Expression realPartMatrix(const Expression e, Context & context, Preferences::AngleUnit angleUnit); - static ComplexCartesian complexCartesianFromComplexPolar(const ExpressionNode * node, Context & context, Preferences::AngleUnit angleUnit); - static ComplexPolar complexPolarFromComplexCartesian(const ExpressionNode * node, Context & context, Preferences::AngleUnit angleUnit); - static Expression complexSquareNormComplexCartesian(Expression real, Expression imag, Context & context, Preferences::AngleUnit angleUnit); -private: - static Expression complexCartesianFromComplexPolarHelper(Expression norm, Expression trigo, Context & context, Preferences::AngleUnit angleUnit); -}; - -} - -#endif diff --git a/poincare/include/poincare/complex_polar.h b/poincare/include/poincare/complex_polar.h deleted file mode 100644 index ff947ccf9..000000000 --- a/poincare/include/poincare/complex_polar.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef POINCARE_COMPLEX_POLAR_H -#define POINCARE_COMPLEX_POLAR_H - -#include -#include - -namespace Poincare { - -class ComplexPolarNode : public ExpressionNode { -public: - - // TreeNode - size_t size() const override { return sizeof(ComplexPolarNode); } - int numberOfChildren() const override { return 2; } -#if POINCARE_TREE_LOG - virtual void logNodeName(std::ostream & stream) const override { - stream << "ComplexPolar"; - } -#endif - - // Properties - Type type() const override { return Type::ComplexPolar; } -private: - // Layout - Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override { assert(false); return Layout(); } - // Evaluation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { assert(false); return Evaluation(); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { assert(false); return Evaluation(); } -}; - -class ComplexPolar final : public Expression { -public: - ComplexPolar() : Expression() {} - static ComplexPolar Builder(Expression child0, Expression child1) { return ComplexPolar(child0, child1); } - Expression norm() { return childAtIndex(0); } - Expression arg() { return childAtIndex(1); } -private: - ComplexPolar(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child0); - replaceChildAtIndexInPlace(1, child1); - } -}; - - -} - -#endif diff --git a/poincare/include/poincare/confidence_interval.h b/poincare/include/poincare/confidence_interval.h index 48a829d9c..78c526f68 100644 --- a/poincare/include/poincare/confidence_interval.h +++ b/poincare/include/poincare/confidence_interval.h @@ -2,7 +2,6 @@ #define POINCARE_CONFIDENCE_INTERVAL_H #include -#include namespace Poincare { @@ -20,9 +19,6 @@ public: // ExpressionNode - // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } - // Properties Type type() const override { return Type::ConfidenceInterval; } int polynomialDegree(Context & context, const char * symbolName) const override { return -1; } diff --git a/poincare/include/poincare/conjugate.h b/poincare/include/poincare/conjugate.h index 7c36ee9cc..141e897fd 100644 --- a/poincare/include/poincare/conjugate.h +++ b/poincare/include/poincare/conjugate.h @@ -19,8 +19,6 @@ public: #endif bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return childAtIndex(0)->isReal(context, angleUnit); } - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; - ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override; // Properties Type type() const override { return Type::Conjugate; } diff --git a/poincare/include/poincare/constant.h b/poincare/include/poincare/constant.h index 7d7f28110..ef3a385c7 100644 --- a/poincare/include/poincare/constant.h +++ b/poincare/include/poincare/constant.h @@ -19,7 +19,6 @@ public: // Complex bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override; - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; // Expression Properties Type type() const override { return Type::Constant; } diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index 5da48dacc..7fd552ccb 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -2,7 +2,6 @@ #define POINCARE_COSINE_H #include -#include #include #include @@ -21,7 +20,6 @@ public: #endif // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianComplexFunction(this, context, angleUnit); } bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return childAtIndex(0)->isReal(context, angleUnit); } // Properties diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index e3da48d30..7f6c1ea78 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -3,7 +3,6 @@ #include #include -#include namespace Poincare { diff --git a/poincare/include/poincare/derivative.h b/poincare/include/poincare/derivative.h index 44c01b74f..afda48893 100644 --- a/poincare/include/poincare/derivative.h +++ b/poincare/include/poincare/derivative.h @@ -2,7 +2,6 @@ #define POINCARE_DERIVATIVE_H #include -#include #include #include @@ -21,7 +20,6 @@ public: #endif // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } // Properties diff --git a/poincare/include/poincare/division.h b/poincare/include/poincare/division.h index 7533bd53c..728f514aa 100644 --- a/poincare/include/poincare/division.h +++ b/poincare/include/poincare/division.h @@ -22,14 +22,6 @@ public: } #endif - /* Property */ - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; - /* If we use the formula arg(a/b) = arg(a)-arg(b), we are likely to end up - * with subtractions of arcTangent. To avoid that, we compute the argument(a/b) - * from the real and imaginary part of a/b. - * TODO: What about norm(a/b)? */ - //ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override; - // Properties Type type() const override { return Type::Division; } int polynomialDegree(Context & context, const char * symbolName) const override; diff --git a/poincare/include/poincare/division_quotient.h b/poincare/include/poincare/division_quotient.h index 43f1ea673..36c3a002d 100644 --- a/poincare/include/poincare/division_quotient.h +++ b/poincare/include/poincare/division_quotient.h @@ -2,7 +2,6 @@ #define POINCARE_DIVISION_QUOTIENT_H #include -#include namespace Poincare { @@ -22,7 +21,6 @@ public: Type type() const override { return Type::DivisionQuotient; } // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } private: diff --git a/poincare/include/poincare/division_remainder.h b/poincare/include/poincare/division_remainder.h index ad6e98f88..c0a4ca2ab 100644 --- a/poincare/include/poincare/division_remainder.h +++ b/poincare/include/poincare/division_remainder.h @@ -2,7 +2,6 @@ #define POINCARE_DIVISION_REMAINDER_H #include -#include #include namespace Poincare { @@ -23,7 +22,6 @@ public: Type type() const override { return Type::DivisionRemainder; } // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } private: diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 3ff918930..ca25dfdc6 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -168,9 +168,6 @@ public: /* Complex */ bool isReal(Context & context, Preferences::AngleUnit angleUnit) const { return node()->isReal(context, angleUnit); } - bool isPureReal(Context & context, Preferences::AngleUnit angleUnit) const; - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const; - ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const; /* Comparison */ /* isIdenticalTo is the "easy" equality, it returns true if both trees have diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index 409d1e1d7..7e43e0f47 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -130,8 +130,6 @@ public: * scan of the tree in ParseAndSimplifyForComplexFormat instead of Simplifying * and then extracting ComplexCartesian. */ virtual bool isReal(Context & context, Preferences::AngleUnit angleUnit) const { return false; } - virtual ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const; - virtual ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const; /* Simplification */ /* SimplificationOrder returns: diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index 9c4d5a4eb..76bac852a 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -3,7 +3,6 @@ #include #include -#include namespace Poincare { @@ -25,7 +24,6 @@ public: Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } private: diff --git a/poincare/include/poincare/floor.h b/poincare/include/poincare/floor.h index 48e85999d..24fc2b44f 100644 --- a/poincare/include/poincare/floor.h +++ b/poincare/include/poincare/floor.h @@ -3,7 +3,6 @@ #include #include -#include namespace Poincare { @@ -24,7 +23,6 @@ public: // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } private: diff --git a/poincare/include/poincare/frac_part.h b/poincare/include/poincare/frac_part.h index aca4ee91c..b39d8e039 100644 --- a/poincare/include/poincare/frac_part.h +++ b/poincare/include/poincare/frac_part.h @@ -3,7 +3,6 @@ #include #include -#include namespace Poincare { @@ -24,7 +23,6 @@ public: // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } private: diff --git a/poincare/include/poincare/function.h b/poincare/include/poincare/function.h index aecee8ad5..71aa21854 100644 --- a/poincare/include/poincare/function.h +++ b/poincare/include/poincare/function.h @@ -29,8 +29,6 @@ public: // Complex bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override; - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; - ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override; private: char m_name[0]; // MUST be the last member variable diff --git a/poincare/include/poincare/great_common_divisor.h b/poincare/include/poincare/great_common_divisor.h index 1e1a86a08..8d601de24 100644 --- a/poincare/include/poincare/great_common_divisor.h +++ b/poincare/include/poincare/great_common_divisor.h @@ -2,7 +2,6 @@ #define POINCARE_GREAT_COMMON_DIVISOR_H #include -#include namespace Poincare { @@ -21,7 +20,6 @@ public: // ExpressionNode Type type() const override { return Type::GreatCommonDivisor; } // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } private: diff --git a/poincare/include/poincare/imaginary_part.h b/poincare/include/poincare/imaginary_part.h index bbc8bde4a..d6f24f590 100644 --- a/poincare/include/poincare/imaginary_part.h +++ b/poincare/include/poincare/imaginary_part.h @@ -2,7 +2,6 @@ #define POINCARE_IMAGINARY_PART_H #include -#include #include namespace Poincare { @@ -23,7 +22,6 @@ public: Type type() const override { return Type::ImaginaryPart; } // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } private: diff --git a/poincare/include/poincare/integral.h b/poincare/include/poincare/integral.h index 57d82309c..b9231ca71 100644 --- a/poincare/include/poincare/integral.h +++ b/poincare/include/poincare/integral.h @@ -3,7 +3,6 @@ #include #include -#include namespace Poincare { @@ -25,7 +24,6 @@ public: Expression replaceUnknown(const Symbol & symbol) override; // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } private: diff --git a/poincare/include/poincare/least_common_multiple.h b/poincare/include/poincare/least_common_multiple.h index dcbc9a0db..00b909bd5 100644 --- a/poincare/include/poincare/least_common_multiple.h +++ b/poincare/include/poincare/least_common_multiple.h @@ -2,7 +2,6 @@ #define POINCARE_LEAST_COMMON_MULTIPLE_H #include -#include namespace Poincare { @@ -21,7 +20,6 @@ public: Type type() const override { return Type::LeastCommonMultiple; } // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } private: diff --git a/poincare/include/poincare/matrix_dimension.h b/poincare/include/poincare/matrix_dimension.h index 215e89d42..66fe2d550 100644 --- a/poincare/include/poincare/matrix_dimension.h +++ b/poincare/include/poincare/matrix_dimension.h @@ -2,7 +2,6 @@ #define POINCARE_MATRIX_DIMENSION_H #include -#include namespace Poincare { @@ -21,9 +20,6 @@ public: // Properties Type type() const override { return Type::MatrixDimension; } -// Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } - private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index a06148859..8cb6ec154 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -25,15 +25,6 @@ public: int polynomialDegree(Context & context, const char * symbolName) const override; int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const override; - // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; - /* If we use the formula arg(a*b) = arg(a)+arg(b), we are likely to end up - * with additions of arcTangent. To avoid that, we compute the argument(a*b) - * from the real and imaginary part of a*b. - * TODO: What about norm(a*b)? */ - //ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override; - //Expression complexArgument(Context & context, Preferences::AngleUnit angleUnit) const override; - // Approximation template static Complex compute(const std::complex c, const std::complex d) { return Complex(c*d); } template static MatrixComplex computeOnComplexAndMatrix(const std::complex c, const MatrixComplex m) { diff --git a/poincare/include/poincare/nth_root.h b/poincare/include/poincare/nth_root.h index 22caadc24..191d881db 100644 --- a/poincare/include/poincare/nth_root.h +++ b/poincare/include/poincare/nth_root.h @@ -2,7 +2,6 @@ #define POINCARE_NTH_ROOT_H #include -#include namespace Poincare { @@ -20,10 +19,6 @@ public: } #endif - // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianFromComplexPolar(this, context, angleUnit); } - ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override; - private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/number.h b/poincare/include/poincare/number.h index b2fbb08a2..d1a9affed 100644 --- a/poincare/include/poincare/number.h +++ b/poincare/include/poincare/number.h @@ -2,7 +2,6 @@ #define POINCARE_NUMBER_H #include -#include namespace Poincare { @@ -24,7 +23,6 @@ public: double doubleApproximation() const; // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } }; diff --git a/poincare/include/poincare/opposite.h b/poincare/include/poincare/opposite.h index c14eb2d5a..8e443f6f9 100644 --- a/poincare/include/poincare/opposite.h +++ b/poincare/include/poincare/opposite.h @@ -27,10 +27,6 @@ public: int polynomialDegree(Context & context, const char * symbolName) const override; Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override; - // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; - ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override; - // Approximation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return ApproximationHelper::Map(this, context, angleUnit, compute); diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index edfb3f17f..bd8e7d7ed 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -3,7 +3,6 @@ #include #include -#include namespace Poincare { @@ -23,10 +22,6 @@ public: Type type() const override { return Type::Parenthesis; } int polynomialDegree(Context & context, const char * symbolName) const override; - // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return childAtIndex(0)->complexCartesian(context, angleUnit); } - ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override { return childAtIndex(0)->complexPolar(context, angleUnit); } - // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/permute_coefficient.h b/poincare/include/poincare/permute_coefficient.h index 00bc4e579..426a90684 100644 --- a/poincare/include/poincare/permute_coefficient.h +++ b/poincare/include/poincare/permute_coefficient.h @@ -3,7 +3,6 @@ #include #include -#include namespace Poincare { @@ -24,9 +23,7 @@ public: // Properties Type type() const override{ return Type::PermuteCoefficient; } - // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } private: diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 7b1503d1a..e1c8f34d1 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -23,8 +23,6 @@ public: // Complex bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override; - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; - ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override; // Properties Type type() const override { return Type::Power; } diff --git a/poincare/include/poincare/prediction_interval.h b/poincare/include/poincare/prediction_interval.h index 273eadaa2..9b27a7861 100644 --- a/poincare/include/poincare/prediction_interval.h +++ b/poincare/include/poincare/prediction_interval.h @@ -2,7 +2,6 @@ #define POINCARE_PREDICTION_INTERVAL_H #include -#include namespace Poincare { @@ -20,9 +19,6 @@ public: // ExpressionNode - // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } - // Properties Type type() const override { return Type::PredictionInterval; } int polynomialDegree(Context & context, const char * symbolName) const override { return -1; } diff --git a/poincare/include/poincare/randint.h b/poincare/include/poincare/randint.h index 25e5b1d95..ce11d615c 100644 --- a/poincare/include/poincare/randint.h +++ b/poincare/include/poincare/randint.h @@ -2,7 +2,6 @@ #define POINCARE_RANDINT_H #include -#include namespace Poincare { @@ -22,7 +21,6 @@ public: Type type() const override { return Type::Randint; } // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } private: diff --git a/poincare/include/poincare/random.h b/poincare/include/poincare/random.h index a78507d6d..eb3a0c0b8 100644 --- a/poincare/include/poincare/random.h +++ b/poincare/include/poincare/random.h @@ -3,7 +3,6 @@ #include #include -#include namespace Poincare { @@ -20,7 +19,6 @@ public: #endif // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } // Properties diff --git a/poincare/include/poincare/real_part.h b/poincare/include/poincare/real_part.h index da5a13da5..f1344ccc7 100644 --- a/poincare/include/poincare/real_part.h +++ b/poincare/include/poincare/real_part.h @@ -3,7 +3,6 @@ #include #include -#include namespace Poincare { @@ -23,7 +22,6 @@ public: Type type() const override { return Type::RealPart; } // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } private: diff --git a/poincare/include/poincare/round.h b/poincare/include/poincare/round.h index a2ae66d7a..b9007b9f4 100644 --- a/poincare/include/poincare/round.h +++ b/poincare/include/poincare/round.h @@ -3,7 +3,6 @@ #include #include -#include namespace Poincare { @@ -20,7 +19,6 @@ public: #endif // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } // Properties diff --git a/poincare/include/poincare/sign_function.h b/poincare/include/poincare/sign_function.h index d2a845c0d..994e9926c 100644 --- a/poincare/include/poincare/sign_function.h +++ b/poincare/include/poincare/sign_function.h @@ -2,7 +2,6 @@ #define POINCARE_SIGN_FUNCTION_H #include -#include #include namespace Poincare { @@ -25,7 +24,6 @@ public: Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianRealFunction(this, context, angleUnit); } bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } private: diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index d2561db0c..442630cc8 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -4,7 +4,6 @@ #include #include #include -#include namespace Poincare { @@ -21,7 +20,6 @@ public: #endif // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianComplexFunction(this, context, angleUnit); } bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return childAtIndex(0)->isReal(context, angleUnit); } // Properties diff --git a/poincare/include/poincare/square_root.h b/poincare/include/poincare/square_root.h index 872465227..3b815898f 100644 --- a/poincare/include/poincare/square_root.h +++ b/poincare/include/poincare/square_root.h @@ -22,17 +22,7 @@ public: } #endif - // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; - /* If we use the formula arg(sqrt(a)) = arg(a)/2, we are likely to end up - * with half arcTangent. To avoid that, we compute the argument(sqrt(a)) - * from the real and imaginary part of sqrt(a). - * TODO: What about norm(sqrt(a))? */ - //ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override; - private: - //Complex - static Multiplication complexCartesianHelper(Expression e, Context & context, Preferences::AngleUnit angleUnit); // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/subtraction.h b/poincare/include/poincare/subtraction.h index b0334b825..122c4f994 100644 --- a/poincare/include/poincare/subtraction.h +++ b/poincare/include/poincare/subtraction.h @@ -24,9 +24,6 @@ public: Type type() const override { return Type::Subtraction; } int polynomialDegree(Context & context, const char * symbolName) const override; - // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; - // Approximation template static Complex compute(const std::complex c, const std::complex d) { return Complex(c - d); } Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index 989bfef8f..d621cf0a4 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -28,8 +28,6 @@ public: // Complex bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override; - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; - ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override; /* Layout */ Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/symbol_abstract.h b/poincare/include/poincare/symbol_abstract.h index e5ffb9c2c..01bd719bc 100644 --- a/poincare/include/poincare/symbol_abstract.h +++ b/poincare/include/poincare/symbol_abstract.h @@ -81,8 +81,6 @@ protected: private: static Expression Expand(const SymbolAbstract & symbol, Context & context, bool clone); static bool isReal(const SymbolAbstract & symbol, Context & context, Preferences::AngleUnit angleUnit); - static ComplexCartesian complexCartesian(const SymbolAbstract & symbol, Context & context, Preferences::AngleUnit angleUnit); - static ComplexPolar complexPolar(const SymbolAbstract & symbol, Context & context, Preferences::AngleUnit angleUnit); static size_t AlignedNodeSize(size_t nameLength, size_t nodeSize); }; diff --git a/poincare/include/poincare/tangent.h b/poincare/include/poincare/tangent.h index b4c0aa747..71c1f2b1c 100644 --- a/poincare/include/poincare/tangent.h +++ b/poincare/include/poincare/tangent.h @@ -2,7 +2,6 @@ #define POINCARE_TANGENT_H #include -#include #include namespace Poincare { @@ -24,7 +23,6 @@ public: float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override; // Complex - ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override { return ComplexHelper::complexCartesianComplexFunction(this, context, angleUnit); } bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return childAtIndex(0)->isReal(context, angleUnit); } private: diff --git a/poincare/include/poincare/undefined.h b/poincare/include/poincare/undefined.h index 6d3588686..23fbb03b8 100644 --- a/poincare/include/poincare/undefined.h +++ b/poincare/include/poincare/undefined.h @@ -17,7 +17,7 @@ public: #endif // Complex - using ExpressionNode::complexCartesian; + using ExpressionNode::isReal; // Properties Type type() const override { return Type::Undefined; } diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 44c45e734..baa33c08f 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 9b7fbc659..40e27c4c3 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -27,30 +28,6 @@ int AdditionNode::getPolynomialCoefficients(Context & context, const char * symb return Addition(this).getPolynomialCoefficients(context, symbolName, coefficients); } -// Private - -ComplexCartesian AdditionNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { - Expression e(this); - Addition real; - Addition imag; - int nbOfChildren = e.numberOfChildren(); - for (int i = 0; i < nbOfChildren; i++) { - ComplexCartesian cartesianParts = e.childAtIndex(i).complexCartesian(context, angleUnit); - if (cartesianParts.isUninitialized()) { - return ComplexCartesian(); - } - Expression a = cartesianParts.real(); - Expression b = cartesianParts.imag(); - assert(!a.isUninitialized() && !b.isUninitialized()); - real.addChildAtIndexInPlace(a, real.numberOfChildren(), real.numberOfChildren()); - imag.addChildAtIndexInPlace(b, imag.numberOfChildren(), imag.numberOfChildren()); - } - return ComplexCartesian::Builder( - real.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - imag.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ); -} - // Layout bool AdditionNode::childNeedsParenthesis(const TreeNode * child) const { if (((static_cast(child)->isNumber() diff --git a/poincare/src/complex_argument.cpp b/poincare/src/complex_argument.cpp index fa0b69ae8..60c9d7d8e 100644 --- a/poincare/src/complex_argument.cpp +++ b/poincare/src/complex_argument.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include diff --git a/poincare/src/complex_helper.cpp b/poincare/src/complex_helper.cpp deleted file mode 100644 index 4ad679be6..000000000 --- a/poincare/src/complex_helper.cpp +++ /dev/null @@ -1,132 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Poincare { - -ComplexCartesian ComplexHelper::complexCartesianComplexFunction(const ExpressionNode * node, Context & context, Preferences::AngleUnit angleUnit) { - Expression e(node); - ComplexCartesian complexChild = e.childAtIndex(0).complexCartesian(context, angleUnit); - if (complexChild.isUninitialized()) { - return ComplexCartesian(); - } - Expression childImaginaryPart = complexChild.imag(); - assert(!childImaginaryPart.isUninitialized()); - if (childImaginaryPart.type() != ExpressionNode::Type::Rational || !static_cast(childImaginaryPart).isZero()) { - return ComplexCartesian(); - } - return ComplexCartesian::Builder( - e.clone(), - Rational(0) - ); -} - -ComplexCartesian ComplexHelper::complexCartesianRealFunction(const ExpressionNode * e, Context & context, Preferences::AngleUnit angleUnit) { - return ComplexCartesian::Builder( - Expression(e).clone(), - Rational(0) - ); -} - -Expression ComplexHelper::complexCartesianFromComplexPolarHelper(Expression norm, Expression trigo, Context & context, Preferences::AngleUnit angleUnit) { - return Multiplication(norm, trigo.shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation)).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); -} - -ComplexCartesian ComplexHelper::complexCartesianFromComplexPolar(const ExpressionNode * node, Context & context, Preferences::AngleUnit angleUnit) { - Expression e(node); - ComplexPolar polar = e.complexPolar(context, angleUnit); - if (polar.isUninitialized()) { - return ComplexCartesian(); - } - Expression r = polar.norm(); - Expression th = polar.arg(); - assert(!r.isUninitialized() && !th.isUninitialized()); - Expression argument = th; - return ComplexCartesian::Builder( - complexCartesianFromComplexPolarHelper(r.clone(), Cosine::Builder(argument.clone()), context, angleUnit), - complexCartesianFromComplexPolarHelper(r, Sine::Builder(argument), context, angleUnit) - ); -} - -ComplexPolar ComplexHelper::complexPolarFromComplexCartesian(const ExpressionNode * node, Context & context, Preferences::AngleUnit angleUnit) { - Expression e(node); - ComplexCartesian cartesian = e.complexCartesian(context, angleUnit); - if (cartesian.isUninitialized()) { - return ComplexPolar(); - } - Expression a = cartesian.real(); - Expression b = cartesian.imag(); - assert(!a.isUninitialized() && !b.isUninitialized()); - // Step 1: find norm - Expression norm; - ExpressionNode::Sign s = e.sign(&context, angleUnit); - if (s == ExpressionNode::Sign::Positive) { - // Case 1: the expression is positive real - norm = e.clone(); - } else if (s == ExpressionNode::Sign::Negative) { - // Case 2: the argument is negative real - norm = e.clone().setSign(ExpressionNode::Sign::Positive, &context, angleUnit); - } else { - // Case 3: the argument is complex or of unknown approximation - // sqrt(a^2+b^2) - norm = SquareRoot::Builder( - Addition( - Power(a.clone(), Rational(2)).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation), - Power(b.clone(), Rational(2)).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); - } - // Step 2: find the argument - Expression argument; - float bApprox = b.approximateToScalar(context, angleUnit); - if (bApprox != 0.0f) { - // if b != 0, argument = sign(b) * Pi/2 - arctan(a/b) - // First, compute arctan(a/b) or (Pi/180)*arctan(a/b) - Expression arcTangent = ArcTangent::Builder(Division(a, b.clone()).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation)).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); - // Then, compute sign(b) * Pi/2 - arctan(a/b) - argument = Subtraction( - Multiplication( - SignFunction::Builder(b).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation), - Division(Constant(Ion::Charset::SmallPi), Rational(2)).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation), - arcTangent - ).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); - } else { - // if b == 0, argument = (1-sign(a))*Pi/2 - argument = Multiplication( - Subtraction( - Rational(1), - SignFunction::Builder(a).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation), - Division(Constant(Ion::Charset::SmallPi), Rational(2)).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); - } - return ComplexPolar::Builder(norm, argument); - -} - -Expression ComplexHelper::complexSquareNormComplexCartesian(Expression real, Expression imag, Context & context, Preferences::AngleUnit angleUnit) { - assert(!real.isUninitialized() && !imag.isUninitialized()); - return Addition( - Power( - real, - Rational(2) - ).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation), - Power( - imag, - Rational(2) - ).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); -} - -} diff --git a/poincare/src/conjugate.cpp b/poincare/src/conjugate.cpp index eae04b0ac..796af952e 100644 --- a/poincare/src/conjugate.cpp +++ b/poincare/src/conjugate.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include @@ -16,28 +15,6 @@ constexpr Expression::FunctionHelper Conjugate::s_functionHelper; int ConjugateNode::numberOfChildren() const { return Conjugate::s_functionHelper.numberOfChildren(); } -ComplexCartesian ConjugateNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { - ComplexCartesian childCartesian = childAtIndex(0)->complexCartesian(context, angleUnit); - if (childCartesian.isUninitialized()) { - return ComplexCartesian(); - } - return ComplexCartesian::Builder( - childCartesian.real(), - Multiplication(Rational(-1), childCartesian.imag()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ); -} - -ComplexPolar ConjugateNode::complexPolar(Context & context, Preferences::AngleUnit angleUnit) const { - ComplexPolar childPolar = childAtIndex(0)->complexPolar(context, angleUnit); - if (childPolar.isUninitialized()) { - return ComplexPolar(); - } - return ComplexPolar::Builder( - childPolar.norm(), - Multiplication(Rational(-1), childPolar.arg()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ); -} - Layout ConjugateNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { return ConjugateLayout(childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits)); } diff --git a/poincare/src/constant.cpp b/poincare/src/constant.cpp index 50ec2c2cc..3eb6f53be 100644 --- a/poincare/src/constant.cpp +++ b/poincare/src/constant.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -20,13 +21,6 @@ bool ConstantNode::isReal(Context & context, Preferences::AngleUnit angleUnit) c return !isIComplex(); } -ComplexCartesian ConstantNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { - if (isIComplex()) { - return ComplexCartesian::Builder(Rational(0), Rational(1)); - } - return ComplexCartesian::Builder(Constant(this).clone(), Rational(0)); -} - Layout ConstantNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { return LayoutHelper::String(m_name, strlen(m_name)); } diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index 56aa1d2af..54dc36e32 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -46,47 +46,6 @@ Expression DivisionNode::shallowReduce(Context & context, Preferences::AngleUnit return Division(this).shallowReduce(context, angleUnit, target); } -ComplexCartesian DivisionNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { - Division e(this); - ComplexCartesian cartesianChild0 = e.childAtIndex(0).complexCartesian(context, angleUnit); - ComplexCartesian cartesianChild1 = e.childAtIndex(1).complexCartesian(context, angleUnit); - if (cartesianChild0.isUninitialized() || cartesianChild1.isUninitialized()) { - return ComplexCartesian(); - } - Expression a = cartesianChild0.real(); - Expression b = cartesianChild0.imag(); - Expression c = cartesianChild1.real(); - Expression d = cartesianChild1.imag(); - assert(!a.isUninitialized() && !b.isUninitialized() && !c.isUninitialized() && !d.isUninitialized()); - Expression denominator = ComplexHelper::complexSquareNormComplexCartesian(c.clone(), d.clone(), context, angleUnit); - return ComplexCartesian::Builder( - Division( - Addition( - Multiplication(a.clone(), c.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - Multiplication(b.clone(), d.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - denominator.clone() - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - Division( - Subtraction( - Multiplication(b, c).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - Multiplication(a, d).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - denominator - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ); -} - -/*ComplexPolar DivisionNode::complexPolar(Context & context, Preferences::AngleUnit angleUnit) const { - Division d(this); - Expression r0 = d.childAtIndex(0).complexNorm(context, angleUnit); - Expression r1 = d.childAtIndex(1).complexNorm(context, angleUnit); - if (r0.isUninitialized() || r1.isUninitialized()) { - return Expression(); - } - return Division(r0,r1).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); -}*/ - template Complex DivisionNode::compute(const std::complex c, const std::complex d) { return Complex(c/d); } diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index d072da896..ebc22ae00 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -199,26 +199,6 @@ bool Expression::getLinearCoefficients(char * variables, int maxVariableSize, Ex return !isMultivariablePolynomial; } -/* Complex */ - -bool Expression::isPureReal(Context & context, Preferences::AngleUnit angleUnit) const { - Evaluation approx = approximateToEvaluation(context, angleUnit); - if (approx.type() == EvaluationNode::Type::Complex) { - Complex approxComplex = static_cast&>(approx); - return approxComplex.imag() == 0.0f; - } - // TODO: matrix are not reduced yet so isPureReal is dummy if the approximation is a matrix - return true; -} - -ComplexCartesian Expression::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { - return node()->complexCartesian(context, angleUnit); -} - -ComplexPolar Expression::complexPolar(Context & context, Preferences::AngleUnit angleUnit) const { - return node()->complexPolar(context, angleUnit); -} - // Private void Expression::defaultDeepReduceChildren(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { diff --git a/poincare/src/expression_node.cpp b/poincare/src/expression_node.cpp index 1f4fd19b2..01397ba06 100644 --- a/poincare/src/expression_node.cpp +++ b/poincare/src/expression_node.cpp @@ -3,8 +3,6 @@ #include #include #include -#include -#include #include #include #include @@ -74,14 +72,6 @@ float ExpressionNode::characteristicXRange(Context & context, Preferences::Angle return range; } -ComplexCartesian ExpressionNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { - return ComplexCartesian(); -} - -ComplexPolar ExpressionNode::complexPolar(Context & context, Preferences::AngleUnit angleUnit) const { - return ComplexHelper::complexPolarFromComplexCartesian(this, context, angleUnit); -} - int ExpressionNode::SimplificationOrder(const ExpressionNode * e1, const ExpressionNode * e2, bool canBeInterrupted) { if (e1->type() > e2->type()) { if (canBeInterrupted && Expression::shouldStopProcessing()) { diff --git a/poincare/src/function.cpp b/poincare/src/function.cpp index 2d6346f9f..8e2b73bcf 100644 --- a/poincare/src/function.cpp +++ b/poincare/src/function.cpp @@ -9,21 +9,11 @@ namespace Poincare { -ComplexCartesian FunctionNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { - Function f(this); - return SymbolAbstract::complexCartesian(f, context, angleUnit); -} - bool FunctionNode::isReal(Context & context, Preferences::AngleUnit angleUnit) const { Function f(this); return SymbolAbstract::isReal(f, context, angleUnit); } -ComplexPolar FunctionNode::complexPolar(Context & context, Preferences::AngleUnit angleUnit) const { - Function f(this); - return SymbolAbstract::complexPolar(f, context, angleUnit); -} - Expression FunctionNode::replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression) { return Function(this).replaceSymbolWithExpression(symbol, expression); } diff --git a/poincare/src/imaginary_part.cpp b/poincare/src/imaginary_part.cpp index f8ae8fe45..dfe859363 100644 --- a/poincare/src/imaginary_part.cpp +++ b/poincare/src/imaginary_part.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index bbc7ad08d..8f1ec2d22 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -31,67 +31,6 @@ ExpressionNode::Sign MultiplicationNode::sign(Context * context, Preferences::An return (Sign)sign; } -ComplexCartesian MultiplicationNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { - Multiplication m(this); - int nbChildren = m.numberOfChildren(); - assert(nbChildren > 0); - ComplexCartesian cartesian = m.childAtIndex(0).complexCartesian(context, angleUnit); - if (cartesian.isUninitialized()) { - return ComplexCartesian(); - } - Expression real = cartesian.real(); - Expression imag = cartesian.imag(); - assert(!real.isUninitialized() && !imag.isUninitialized()); - for (int i = 1; i < nbChildren; i++) { - ComplexCartesian childCartesian = m.childAtIndex(i).complexCartesian(context, angleUnit); - if (childCartesian.isUninitialized()) { - return ComplexCartesian(); - } - Expression childReal = childCartesian.real(); - Expression childImag = childCartesian.imag(); - assert(!real.isUninitialized() && !imag.isUninitialized()); - Expression newReal = - Subtraction( - Multiplication(real.clone(), childReal.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - Multiplication(imag.clone(), childImag.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); - Expression newImag = - Addition( - Multiplication(real, childImag).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - Multiplication(imag, childReal).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); - real = newReal; - imag = newImag; - } - return ComplexCartesian::Builder(real, imag); -} - -/*Expression MultiplicationNode::complexNorm(Context & context, Preferences::AngleUnit angleUnit) const { - Multiplication m(this); - Multiplication norm; - for (int i = 0; i < m.numberOfChildren(); i++) { - Expression r = m.childAtIndex(i).complexNorm(context, angleUnit); - if (r.isUninitialized()) { - return Expression(); - } - norm.addChildAtIndexInPlace(r, norm.numberOfChildren(), norm.numberOfChildren()); - } - return norm.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); -} - -Expression MultiplicationNode::complexArgument(Context & context, Preferences::AngleUnit angleUnit) const { - Multiplication m(this); - Addition arg; - for (int i = 0; i < m.numberOfChildren(); i++) { - Expression r = m.childAtIndex(i).complexArgument(context, angleUnit); - if (r.isUninitialized()) { - return Expression(); - } - arg.addChildAtIndexInPlace(r, arg.numberOfChildren(), arg.numberOfChildren()); - } - return arg; -} -*/ int MultiplicationNode::polynomialDegree(Context & context, const char * symbolName) const { int degree = 0; for (ExpressionNode * c : children()) { diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index 761c84ca2..f4cdca87b 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -18,47 +18,6 @@ constexpr Expression::FunctionHelper NthRoot::s_functionHelper; int NthRootNode::numberOfChildren() const { return NthRoot::s_functionHelper.numberOfChildren(); } -ComplexPolar NthRootNode::complexPolar(Context & context, Preferences::AngleUnit angleUnit) const { - NthRoot e(this); - ComplexPolar polarChild0 = e.childAtIndex(0).complexPolar(context, angleUnit); - ComplexCartesian cartesianChild1 = e.childAtIndex(0).complexCartesian(context, angleUnit); - if (polarChild0.isUninitialized() || cartesianChild1.isUninitialized()) { - return ComplexPolar(); - } - // NthRoot(r*e^(i*th), c+id) - Expression r = polarChild0.norm(); - Expression th = polarChild0.arg(); - Expression c = cartesianChild1.real(); - Expression d = cartesianChild1.imag(); - assert(!r.isUninitialized() && !th.isUninitialized() && !c.isUninitialized() && !d.isUninitialized()); - Expression denominator = ComplexHelper::complexSquareNormComplexCartesian(c.clone(), d.clone(), context, angleUnit); - // R = r^(c/(c^2+d^2))*e^(th*d/(c^2+d^2)) - Expression norm = Multiplication( - Power( - r.clone(), - Division(c.clone(), denominator.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - Power( - Constant(Ion::Charset::Exponential), - Division( - Multiplication(d.clone(), th.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - denominator.clone()) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); - // TH = (th*c-d*ln(r))/(c^2+d^2) - Expression argument = Division( - Subtraction( - Multiplication(th, c).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - Multiplication( - d, - NaperianLogarithm::Builder(r).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - denominator - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); - return ComplexPolar::Builder(norm, argument); -} - Layout NthRootNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { return NthRootLayout( childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits), diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index aa23e6878..3b65c047f 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -29,28 +29,6 @@ ExpressionNode::Sign OppositeNode::sign(Context * context, Preferences::AngleUni return ExpressionNode::sign(context,angleUnit); } -ComplexCartesian OppositeNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { - ComplexCartesian childCartesian = childAtIndex(0)->complexCartesian(context, angleUnit); - if (childCartesian.isUninitialized()) { - return ComplexCartesian(); - } - return ComplexCartesian::Builder( - Multiplication(Rational(-1), childCartesian.real()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - Multiplication(Rational(-1), childCartesian.imag()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ); -} - -ComplexPolar OppositeNode::complexPolar(Context & context, Preferences::AngleUnit angleUnit) const { - ComplexPolar childPolar = childAtIndex(0)->complexPolar(context, angleUnit); - if (childPolar.isUninitialized()) { - return ComplexPolar(); - } - return ComplexPolar::Builder( - childPolar.norm(), - Addition(childPolar.arg(), Constant(Ion::Charset::SmallPi)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ); -} - /* Layout */ bool OppositeNode::childNeedsParenthesis(const TreeNode * child) const { diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index d7b4dc5b8..92f9c5247 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -94,50 +94,6 @@ bool PowerNode::isReal(Context & context, Preferences::AngleUnit angleUnit) cons return false; } -ComplexCartesian PowerNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { - Power p(this); - Expression e = p.equivalentExpressionUsingStandardExpression(); - if (!e.isUninitialized()) { - return e.complexCartesian(context, angleUnit); - } - return ComplexHelper::complexCartesianFromComplexPolar(this, context, angleUnit); -} - -ComplexPolar PowerNode::complexPolar(Context & context, Preferences::AngleUnit angleUnit) const { - Power p(this); - Expression e = p.equivalentExpressionUsingStandardExpression(); - if (!e.isUninitialized()) { - return e.complexPolar(context, angleUnit); - } - ComplexPolar polarChild0 = p.childAtIndex(0).complexPolar(context, angleUnit); - ComplexCartesian cartesianChild1 = p.childAtIndex(1).complexCartesian(context, angleUnit); - if (polarChild0.isUninitialized() || cartesianChild1.isUninitialized()) { - return ComplexPolar(); - } - // Power(r*e^(i*th), c+id) - Expression r = polarChild0.norm(); - Expression th = polarChild0.arg(); - Expression c = cartesianChild1.real(); - Expression d = cartesianChild1.imag(); - // R = r^c*e^(-th*d) - Expression norm = Multiplication( - Power(r.clone(), c.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - Power( - Constant(Ion::Charset::Exponential), - Multiplication(Rational(-1), th.clone(), d.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); - // TH = d*ln(r)+c*th - Expression argument = Addition( - Multiplication(th, c).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - Multiplication( - d, - NaperianLogarithm::Builder(r).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); - return ComplexPolar::Builder(norm, argument); -} - // Private template diff --git a/poincare/src/real_part.cpp b/poincare/src/real_part.cpp index 3bd0b688c..cf5254634 100644 --- a/poincare/src/real_part.cpp +++ b/poincare/src/real_part.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include diff --git a/poincare/src/sign_function.cpp b/poincare/src/sign_function.cpp index dac3de99b..913c4100e 100644 --- a/poincare/src/sign_function.cpp +++ b/poincare/src/sign_function.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index 663cb6d5c..53f7379fd 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -18,57 +18,6 @@ constexpr Expression::FunctionHelper SquareRoot::s_functionHelper; int SquareRootNode::numberOfChildren() const { return SquareRoot::s_functionHelper.numberOfChildren(); } -/*Expression SquareRootNode::complexNorm(Context & context, Preferences::AngleUnit angleUnit) const { - Expression r = childAtIndex(0)->complexNorm(context, angleUnit); - if (r.isUninitialized()) { - return Expression(); - } - // R = sqrt(r) - return SquareRoot::Builder(r).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); -}*/ - -/*Expression SquareRootNode::complexArgument(Context & context, Preferences::AngleUnit angleUnit) const { - Expression th = childAtIndex(0)->complexArgument(context, angleUnit); - if (th.isUninitialized()) { - return Expression(); - } - // TH = th/2 - return Division(th, Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); -}*/ - -Multiplication SquareRootNode::complexCartesianHelper(Expression e, Context & context, Preferences::AngleUnit angleUnit) { - return Multiplication( - Rational(1,2), - SquareRoot::Builder( - Multiplication( - Rational(2), - e.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ); -} -ComplexCartesian SquareRootNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { - // real: (1/2)*sqrt(2*(sqrt(x^2+y^2)+x)) - // imag: (1/2)*sqrt(2*(sqrt(x^2+y^2)-x)*sign(y)) - SquareRoot e(this); - ComplexCartesian cartesian = e.childAtIndex(0).complexCartesian(context, angleUnit); - if (cartesian.isUninitialized()) { - return ComplexCartesian(); - } - Expression x = cartesian.real(); - Expression y = cartesian.imag(); - assert(!x.isUninitialized() && !y.isUninitialized()); - Expression norm = SquareRoot::Builder(ComplexHelper::complexSquareNormComplexCartesian(x.clone(), y.clone(), context, angleUnit)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); - // a = sqrt(x^2+y^2)+x - Multiplication real = complexCartesianHelper(Addition(norm.clone(), x.clone()), context, angleUnit); - Multiplication imag = complexCartesianHelper(Subtraction(norm, x), context, angleUnit); - imag.addChildAtIndexInPlace(SignFunction::Builder(y).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation), imag.numberOfChildren(), imag.numberOfChildren()); - return ComplexCartesian::Builder( - real.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - imag.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ); -} - Layout SquareRootNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { return NthRootLayout(childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits)); } diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index 541fec2b8..f6ce7a4f6 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -23,19 +23,6 @@ int SubtractionNode::polynomialDegree(Context & context, const char * symbolName // Private -ComplexCartesian SubtractionNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { - Subtraction e(this); - ComplexCartesian cartesian0 = e.childAtIndex(0).complexCartesian(context, angleUnit); - ComplexCartesian cartesian1 = e.childAtIndex(1).complexCartesian(context, angleUnit); - if (cartesian0.isUninitialized() || cartesian1.isUninitialized()) { - return ComplexCartesian(); - } - return ComplexCartesian::Builder( - Subtraction(cartesian0.real(), cartesian1.real()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), - Subtraction(cartesian0.imag(), cartesian1.imag()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ); -} - bool SubtractionNode::childNeedsParenthesis(const TreeNode * child) const { if (child == childAtIndex(0)) { return false; diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 754f558cc..c4746ba5c 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -82,16 +82,6 @@ bool SymbolNode::isReal(Context & context, Preferences::AngleUnit angleUnit) con return SymbolAbstract::isReal(s, context, angleUnit); } -ComplexCartesian SymbolNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { - Symbol s(this); - return SymbolAbstract::complexCartesian(s, context, angleUnit); -} - -ComplexPolar SymbolNode::complexPolar(Context & context, Preferences::AngleUnit angleUnit) const { - Symbol f(this); - return SymbolAbstract::complexPolar(f, context, angleUnit); -} - Layout SymbolNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { if (m_name[0] == Symbol::SpecialSymbols::UnknownX) { assert(m_name[1] == 0); diff --git a/poincare/src/symbol_abstract.cpp b/poincare/src/symbol_abstract.cpp index c8f57e0c9..4dfe4808a 100644 --- a/poincare/src/symbol_abstract.cpp +++ b/poincare/src/symbol_abstract.cpp @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -88,23 +87,6 @@ bool SymbolAbstract::isReal(const SymbolAbstract & symbol, Context & context, Pr return e.isReal(context, angleUnit); } -ComplexCartesian SymbolAbstract::complexCartesian(const SymbolAbstract & symbol, Context & context, Preferences::AngleUnit angleUnit) { - Expression e = SymbolAbstract::Expand(symbol, context, true); - if (e.isUninitialized()) { - return ComplexCartesian::Builder(symbol.clone(), Rational(0)); - } - return e.complexCartesian(context, angleUnit); -} - -ComplexPolar SymbolAbstract::complexPolar(const SymbolAbstract & symbol, Context & context, Preferences::AngleUnit angleUnit) { - Expression e = SymbolAbstract::Expand(symbol, context, true); - if (e.isUninitialized()) { - // sqrt(f(x)^2)*exp((1-sign(f(x))*Pi/2) - return ComplexHelper::complexPolarFromComplexCartesian(symbol.node(), context, angleUnit); - } - return e.complexPolar(context, angleUnit); -} - /* TreePool uses adresses and sizes that are multiples of 4 in order to make * node moves faster.*/ size_t SymbolAbstract::AlignedNodeSize(size_t nameLength, size_t nodeSize) { diff --git a/poincare/src/tree_pool.cpp b/poincare/src/tree_pool.cpp index 4cb9f9486..70d095737 100644 --- a/poincare/src/tree_pool.cpp +++ b/poincare/src/tree_pool.cpp @@ -222,7 +222,6 @@ template OppositeNode * Poincare::TreePool::createTreeNode(size_t template PowerNode * Poincare::TreePool::createTreeNode(size_t size); template ComplexArgumentNode * Poincare::TreePool::createTreeNode(size_t size); template ComplexCartesianNode * Poincare::TreePool::createTreeNode(size_t size); -template ComplexPolarNode * Poincare::TreePool::createTreeNode(size_t size); template ConfidenceIntervalNode * Poincare::TreePool::createTreeNode(size_t size); template ConjugateNode * Poincare::TreePool::createTreeNode(size_t size); template ConstantNode * Poincare::TreePool::createTreeNode(size_t size); From 6794f8c802bc46b44faf2b15fa31abf5e353f3ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 17 Dec 2018 12:03:53 +0100 Subject: [PATCH 106/373] [poincare] Add comments --- poincare/src/addition.cpp | 5 +++-- poincare/src/complex_argument.cpp | 2 ++ poincare/src/multiplication.cpp | 3 +++ poincare/src/power.cpp | 23 +++++++---------------- 4 files changed, 15 insertions(+), 18 deletions(-) diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 40e27c4c3..0f37ccedb 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -256,8 +256,9 @@ Expression Addition::shallowReduce(Context & context, Preferences::AngleUnit ang * - All children are either real or ComplexCartesian (allChildrenAreReal == 0) * We can bubble up ComplexCartesian nodes. */ if (allChildrenAreReal(context, angleUnit) == 0) { - Addition imag; - Addition real = *this; + /* We turn (a+ib)+(c+id) into (a+c)+i(c+d)*/ + Addition imag; // we store all imaginary parts in 'imag' + Addition real = *this; // we store all real parts in 'real' i = numberOfChildren() - 1; while (i >= 0) { Expression c = childAtIndex(i); diff --git a/poincare/src/complex_argument.cpp b/poincare/src/complex_argument.cpp index 60c9d7d8e..dbd1acb60 100644 --- a/poincare/src/complex_argument.cpp +++ b/poincare/src/complex_argument.cpp @@ -54,10 +54,12 @@ Expression ComplexArgument::shallowReduce(Context & context, Preferences::AngleU replaceWithInPlace(arg); return arg.shallowReduce(context, angleUnit, target); } else if (app >= 0) { + // arg(x) = 0 if x > 0 Expression result = Rational(0); replaceWithInPlace(result); return result; } + // arg(x) = Pi if x < 0 assert(app < 0); Expression result = Constant(Ion::Charset::SmallPi); replaceWithInPlace(result); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 8f1ec2d22..21ebc1974 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -478,7 +478,9 @@ Expression Multiplication::privateShallowReduce(Context & context, Preferences:: if (allChildrenAreReal(context, angleUnit) == 0) { int nbChildren = numberOfChildren(); int i = nbChildren-1; + // Children are sorted so ComplexCartesian nodes are at the end assert(childAtIndex(i).type() == ExpressionNode::Type::ComplexCartesian); + // First, we merge all ComplexCartesian children into one ComplexCartesian child = childAtIndex(i).convert(); removeChildAtIndexInPlace(i); i--; @@ -492,6 +494,7 @@ Expression Multiplication::privateShallowReduce(Context & context, Preferences:: removeChildAtIndexInPlace(i); i--; } + // The real children are both factors of the real and the imaginary multiplication Multiplication real = *this; Multiplication imag = clone().convert(); real.addChildAtIndexInPlace(child.real(), real.numberOfChildren(), real.numberOfChildren()); diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 92f9c5247..57f389770 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -330,19 +330,6 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU #endif #endif - // TODO: do we need this? - /*Evaluation c0Approximated = childAtIndex(0).node()->approximate(1.0f, context, angleUnit); - Evaluation c1Approximated = childAtIndex(1).node()->approximate(1.0f, context, angleUnit); - Complex c0 = static_cast&>(c0Approximated); - Complex c1 = static_cast&>(c1Approximated); - bool bothChildrenComplexes = c0.imag() != 0 && c1.imag() != 0 && !std::isnan(c0.imag()) && !std::isnan(c1.imag()); - bool nonNullChild0 = !std::isnan(c0.real()) && !std::isnan(c0.imag()) && (c0.real() > Expression::epsilon() || c0.imag() > Expression::epsilon()); - if (bothChildrenComplexes) { - return *this; - }*/ - - /* Step 0: if both children are true unresolved complexes, the result is not simplified. TODO? */ - Expression power = *this; Expression base = childAtIndex(0); Expression index = childAtIndex(1); @@ -406,13 +393,17 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU } } - /* Step 1: we now bubble up ComplexCartesian, we handle different case */ + /* Step 1: we now bubble up ComplexCartesian, we handle different cases: + * At least, one child is a ComplexCartesian and the other is either a + * ComplexCartesian or real. */ ComplexCartesian complexBase; ComplexCartesian complexIndex; ComplexCartesian result; - // First, (x+iy)^q with q special values - // TODO: explain here why? + /* First, (x+iy)^q with q special values + * For q = -1, 1/2, -1/2, n with n integer < 10, we avoid introducing arctangent + * by using the formula (r*e^(i*th))^(a+ib) = r^a*e(-th*b)*e^(b*ln(r)+th*a). + * Instead, we rather use the cartesian form of the base and the index. */ if (base.type() == ExpressionNode::Type::ComplexCartesian) { complexBase = static_cast(base); Integer ten(10); From 38de794642b2796e139841d28bc28cc997165127 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 17 Dec 2018 13:37:47 +0100 Subject: [PATCH 107/373] [poincare] Change signature setSign(Context, AngleUnit, ReductionTarget) --- poincare/include/poincare/absolute_value.h | 2 +- poincare/include/poincare/decimal.h | 2 +- poincare/include/poincare/expression.h | 4 ++-- poincare/include/poincare/expression_node.h | 12 ++++++------ poincare/include/poincare/factorial.h | 2 +- poincare/include/poincare/float.h | 2 +- poincare/include/poincare/infinity.h | 2 +- poincare/include/poincare/multiplication.h | 4 ++-- poincare/include/poincare/number.h | 2 +- poincare/include/poincare/power.h | 4 ++-- poincare/include/poincare/random.h | 2 +- poincare/include/poincare/rational.h | 2 +- poincare/include/poincare/sign_function.h | 2 +- poincare/include/poincare/symbol_abstract.h | 2 +- poincare/include/poincare/undefined.h | 2 +- poincare/src/absolute_value.cpp | 4 ++-- poincare/src/addition.cpp | 2 +- poincare/src/complex_cartesian.cpp | 6 +++--- poincare/src/decimal.cpp | 2 +- poincare/src/expression.cpp | 10 +++++----- poincare/src/expression_node.cpp | 2 +- poincare/src/factorial.cpp | 2 +- poincare/src/float.cpp | 2 +- poincare/src/infinity.cpp | 2 +- poincare/src/multiplication.cpp | 14 +++++++------- poincare/src/power.cpp | 16 ++++++++-------- poincare/src/random.cpp | 2 +- poincare/src/rational.cpp | 2 +- poincare/src/sign_function.cpp | 4 ++-- poincare/src/symbol_abstract.cpp | 4 ++-- poincare/src/trigonometry.cpp | 4 ++-- poincare/src/undefined.cpp | 2 +- 32 files changed, 63 insertions(+), 63 deletions(-) diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 973f8df7a..665d5fa4a 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -21,7 +21,7 @@ public: // Properties Type type() const override { return Type::AbsoluteValue; } Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override { return Sign::Positive; } - Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; + Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Complex bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index 7f6c1ea78..a19dcb552 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -48,7 +48,7 @@ public: // Properties Type type() const override { return Type::Decimal; } Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override { return m_negative ? Sign::Negative : Sign::Positive; } - Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; + Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Approximation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index ca25dfdc6..7b9339469 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -271,12 +271,12 @@ protected: * - a multiplication who has one numeral child whose is negative * and turns the negative factor into a positive one */ - Expression makePositiveAnyNegativeNumeralFactor(Context & context, Preferences::AngleUnit angleUnit); + Expression makePositiveAnyNegativeNumeralFactor(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); Expression denominator(Context & context, Preferences::AngleUnit angleUnit) const { return node()->denominator(context, angleUnit); } Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { return node()->shallowReduce(context, angleUnit, target); } Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { return node()->shallowBeautify(context, angleUnit); } Expression deepBeautify(Context & context, Preferences::AngleUnit angleUnit); - Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit); + Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: static constexpr int k_maxSymbolReplacementsCount = 10; diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index 7e43e0f47..fe6eac9e8 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -102,6 +102,11 @@ public: virtual Type type() const = 0; /* Properties */ + enum class ReductionTarget { + BottomUpComputation = 0, + TopDownComputation = 1, + User + }; enum class Sign { Negative = -1, Unknown = 0, @@ -111,7 +116,7 @@ public: virtual bool isNumber() const { return false; } /*!*/ virtual Expression replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression); /*!*/ virtual Expression replaceUnknown(const Symbol & symbol); - /*!*/ virtual Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit); + /*!*/ virtual Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target); virtual int polynomialDegree(Context & context, const char * symbolName) const; /*!*/ virtual int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const; /*!*/ virtual Expression shallowReplaceReplaceableSymbols(Context & context); @@ -163,11 +168,6 @@ public: virtual Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const = 0; /* Simplification */ - enum class ReductionTarget { - BottomUpComputation = 0, - TopDownComputation = 1, - User - }; /*!*/ virtual void deepReduceChildren(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target); /*!*/ virtual Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target); /*!*/ virtual Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit); diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index 76bac852a..2ed36e38b 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -21,7 +21,7 @@ public: // Properties Type type() const override { return Type::Factorial; } Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override { return Sign::Positive; } - Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; + Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Complex bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } diff --git a/poincare/include/poincare/float.h b/poincare/include/poincare/float.h index 66fc7a68c..6d0998448 100644 --- a/poincare/include/poincare/float.h +++ b/poincare/include/poincare/float.h @@ -40,7 +40,7 @@ public: // Properties Type type() const override { return Type::Float; } Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override { return m_value < 0 ? Sign::Negative : Sign::Positive; } - Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; + Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override; // Layout diff --git a/poincare/include/poincare/infinity.h b/poincare/include/poincare/infinity.h index 6887fa08f..5aecea410 100644 --- a/poincare/include/poincare/infinity.h +++ b/poincare/include/poincare/infinity.h @@ -9,7 +9,7 @@ class InfinityNode final : public NumberNode { public: void setNegative(bool negative) { m_negative = negative; } - Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; + Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // TreeNode size_t size() const override { return sizeof(InfinityNode); } diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 8cb6ec154..c4a1565a3 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -34,7 +34,7 @@ public: private: // Property - Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; + Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Layout bool childNeedsParenthesis(const TreeNode * child) const override; @@ -80,7 +80,7 @@ public: template static void computeOnArrays(T * m, T * n, T * result, int mNumberOfColumns, int mNumberOfRows, int nNumberOfColumns); // Expression - Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit); + Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit); int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const; diff --git a/poincare/include/poincare/number.h b/poincare/include/poincare/number.h index d1a9affed..fe23a2dfd 100644 --- a/poincare/include/poincare/number.h +++ b/poincare/include/poincare/number.h @@ -47,7 +47,7 @@ public: /* Number::sign() or Number::setSign does not need a context or an angle unit * (a number can be Infinity, Undefined, Float, Decimal, Rational). */ ExpressionNode::Sign sign() { return Expression::sign(nullptr, Preferences::AngleUnit::Degree); } - Number setSign(ExpressionNode::Sign s) { return Expression::setSign(s, nullptr, Preferences::AngleUnit::Degree).convert(); } + Number setSign(ExpressionNode::Sign s) { return Expression::setSign(s, nullptr, Preferences::AngleUnit::Degree, ExpressionNode::ReductionTarget::User).convert(); } protected: Number() : Expression() {} NumberNode * node() const { return static_cast(Expression::node()); } diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index e1c8f34d1..e672bdcc8 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -27,7 +27,7 @@ public: // Properties Type type() const override { return Type::Power; } Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override; - Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; + Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; int polynomialDegree(Context & context, const char * symbolName) const override; int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const override; @@ -68,7 +68,7 @@ class Power final : public Expression { public: Power(Expression base, Expression exponent); Power(const PowerNode * n) : Expression(n) {} - Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit); + Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const; Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit); diff --git a/poincare/include/poincare/random.h b/poincare/include/poincare/random.h index eb3a0c0b8..d6b5096d6 100644 --- a/poincare/include/poincare/random.h +++ b/poincare/include/poincare/random.h @@ -24,7 +24,7 @@ public: // Properties Type type() const override { return Type::Random; } Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override { return Sign::Positive; } - Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; + Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index 9daab1b3b..29fc7f2a7 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -59,7 +59,7 @@ private: int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override; Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) override; - Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; + Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; Expression denominator(Context & context, Preferences::AngleUnit angleUnit) const override; bool m_negative; uint8_t m_numberOfDigitsNumerator; diff --git a/poincare/include/poincare/sign_function.h b/poincare/include/poincare/sign_function.h index 994e9926c..b10f33c85 100644 --- a/poincare/include/poincare/sign_function.h +++ b/poincare/include/poincare/sign_function.h @@ -21,7 +21,7 @@ public: // Properties Type type() const override { return Type::SignFunction; } Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override; - Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; + Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Complex bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } diff --git a/poincare/include/poincare/symbol_abstract.h b/poincare/include/poincare/symbol_abstract.h index 01bd719bc..a60910fa4 100644 --- a/poincare/include/poincare/symbol_abstract.h +++ b/poincare/include/poincare/symbol_abstract.h @@ -36,7 +36,7 @@ public: // Property Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override; - Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit) override; + Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // TreeNode #if POINCARE_TREE_LOG diff --git a/poincare/include/poincare/undefined.h b/poincare/include/poincare/undefined.h index 23fbb03b8..ae0006e0f 100644 --- a/poincare/include/poincare/undefined.h +++ b/poincare/include/poincare/undefined.h @@ -22,7 +22,7 @@ public: // Properties Type type() const override { return Type::Undefined; } int polynomialDegree(Context & context, const char * symbolName) const override; - Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) override; + Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Approximation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index baa33c08f..70c738f49 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -14,7 +14,7 @@ constexpr Expression::FunctionHelper AbsoluteValue::s_functionHelper; int AbsoluteValueNode::numberOfChildren() const { return AbsoluteValue::s_functionHelper.numberOfChildren(); } -Expression AbsoluteValueNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { +Expression AbsoluteValueNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) { return AbsoluteValue(this).setSign(s, context, angleUnit); } @@ -68,7 +68,7 @@ Expression AbsoluteValue::shallowReduce(Context & context, Preferences::AngleUni return childNorm.shallowReduce(context, angleUnit, target); } // abs(-x) = abs(x) - c.makePositiveAnyNegativeNumeralFactor(context, angleUnit); + c.makePositiveAnyNegativeNumeralFactor(context, angleUnit, target); return *this; } diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 0f37ccedb..3afb91fba 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -101,7 +101,7 @@ Expression Addition::shallowBeautify(Context & context, Preferences::AngleUnit a for (int i = 0; i < numberOfChildren(); i++) { // Try to make the child i positive if any negative numeral factor is found - Expression subtractant = childAtIndex(i).makePositiveAnyNegativeNumeralFactor(context, angleUnit); + Expression subtractant = childAtIndex(i).makePositiveAnyNegativeNumeralFactor(context, angleUnit, ExpressionNode::ReductionTarget::User); if (subtractant.isUninitialized()) { // if subtractant is not initialized, it means the child i had no negative numeral factor diff --git a/poincare/src/complex_cartesian.cpp b/poincare/src/complex_cartesian.cpp index 31aa56698..e81773b39 100644 --- a/poincare/src/complex_cartesian.cpp +++ b/poincare/src/complex_cartesian.cpp @@ -38,8 +38,8 @@ Expression ComplexCartesian::shallowReduce(Context & context, Preferences::Angle Expression ComplexCartesian::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { Expression a = real(); Expression b = imag(); - Expression oppositeA = a.makePositiveAnyNegativeNumeralFactor(context, angleUnit); - Expression oppositeB = b.makePositiveAnyNegativeNumeralFactor(context, angleUnit); + Expression oppositeA = a.makePositiveAnyNegativeNumeralFactor(context, angleUnit, ExpressionNode::ReductionTarget::User); + Expression oppositeB = b.makePositiveAnyNegativeNumeralFactor(context, angleUnit, ExpressionNode::ReductionTarget::User); a = oppositeA.isUninitialized() ? a : oppositeA; b = oppositeB.isUninitialized() ? b : oppositeB; Expression e = Expression::CreateComplexExpression(a, b, Preferences::ComplexFormat::Cartesian, @@ -72,7 +72,7 @@ Expression ComplexCartesian::norm(Context & context, Preferences::AngleUnit angl return a;; } else if (s == ExpressionNode::Sign::Negative) { // Case 2: the argument is negative real - return a.setSign(ExpressionNode::Sign::Positive, &context, angleUnit); + return a.setSign(ExpressionNode::Sign::Positive, &context, angleUnit, target); } } Expression n2 = squareNorm(context, angleUnit, target); diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index 06d9a6b63..5be3623a8 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -56,7 +56,7 @@ size_t DecimalNode::size() const { return DecimalSize(m_numberOfDigitsInMantissa); } -Expression DecimalNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { +Expression DecimalNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) { return Decimal(this).setSign(s); } diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index ebc22ae00..90d68a682 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -248,10 +248,10 @@ Expression Expression::defaultReplaceReplaceableSymbols(Context & context) { return *this; } -Expression Expression::makePositiveAnyNegativeNumeralFactor(Context & context, Preferences::AngleUnit angleUnit) { +Expression Expression::makePositiveAnyNegativeNumeralFactor(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { // The expression is a negative number if (isNumber() && sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { - return setSign(ExpressionNode::Sign::Positive, &context, angleUnit); + return setSign(ExpressionNode::Sign::Positive, &context, angleUnit, target); } // The expression is a multiplication whose numeral factor is negative if (type() == ExpressionNode::Type::Multiplication && numberOfChildren() > 0 && childAtIndex(0).isNumber() && childAtIndex(0).sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { @@ -263,7 +263,7 @@ Expression Expression::makePositiveAnyNegativeNumeralFactor(Context & context, P return m.squashUnaryHierarchyInPlace(); } else { // Otherwise, we make it positive - m.childAtIndex(0).setSign(ExpressionNode::Sign::Positive, &context, angleUnit); + m.childAtIndex(0).setSign(ExpressionNode::Sign::Positive, &context, angleUnit, target); } return m; } @@ -460,8 +460,8 @@ Expression Expression::deepBeautify(Context & context, Preferences::AngleUnit an return e; } -Expression Expression::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit) { - return node()->setSign(s, context, angleUnit); +Expression Expression::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + return node()->setSign(s, context, angleUnit, target); } /* Evaluation */ diff --git a/poincare/src/expression_node.cpp b/poincare/src/expression_node.cpp index 01397ba06..0a9bbcc63 100644 --- a/poincare/src/expression_node.cpp +++ b/poincare/src/expression_node.cpp @@ -22,7 +22,7 @@ Expression ExpressionNode::replaceUnknown(const Symbol & symbol) { return Expression(this).defaultReplaceUnknown(symbol); } -Expression ExpressionNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { +Expression ExpressionNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) { assert(false); return Expression(); } diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index 74cddfdf9..5929a02a1 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -14,7 +14,7 @@ namespace Poincare { // Property -Expression FactorialNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { +Expression FactorialNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) { assert(s == Sign::Positive); return Factorial(this); } diff --git a/poincare/src/float.cpp b/poincare/src/float.cpp index a2039d714..eecf004ee 100644 --- a/poincare/src/float.cpp +++ b/poincare/src/float.cpp @@ -4,7 +4,7 @@ namespace Poincare { template -Expression FloatNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { +Expression FloatNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) { assert(s != Sign::Unknown); Sign currentSign = m_value < 0 ? Sign::Negative : Sign::Positive; Expression thisExpr = Number(this); diff --git a/poincare/src/infinity.cpp b/poincare/src/infinity.cpp index 2302fbdfb..9b11e2296 100644 --- a/poincare/src/infinity.cpp +++ b/poincare/src/infinity.cpp @@ -9,7 +9,7 @@ extern "C" { namespace Poincare { -Expression InfinityNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { +Expression InfinityNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) { return Infinity(this).setSign(s, context, angleUnit); } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 21ebc1974..517593ccc 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -66,8 +66,8 @@ MatrixComplex MultiplicationNode::computeOnMatrices(const MatrixComplex m, return result; } -Expression MultiplicationNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { - return Multiplication(this).setSign(s, context, angleUnit); +Expression MultiplicationNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Multiplication(this).setSign(s, context, angleUnit, target); } bool MultiplicationNode::childNeedsParenthesis(const TreeNode * child) const { @@ -122,14 +122,14 @@ void Multiplication::computeOnArrays(T * m, T * n, T * result, int mNumberOfColu } } -Expression Multiplication::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit) { +Expression Multiplication::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { assert(s == ExpressionNode::Sign::Positive); for (int i = 0; i < numberOfChildren(); i++) { if (childAtIndex(i).sign(context, angleUnit) == ExpressionNode::Sign::Negative) { - replaceChildAtIndexInPlace(i, childAtIndex(i).setSign(s, context, angleUnit)); + replaceChildAtIndexInPlace(i, childAtIndex(i).setSign(s, context, angleUnit, target)); } } - return shallowReduce(*context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); + return shallowReduce(*context, angleUnit, target); } Expression Multiplication::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { @@ -144,7 +144,7 @@ Expression Multiplication::shallowBeautify(Context & context, Preferences::Angle * shall become a/b) or a non-integer rational term (3/2*a -> (3*a)/2). */ // Step 1: Turn -n*A into -(n*A) - Expression noNegativeNumeral = makePositiveAnyNegativeNumeralFactor(context, angleUnit); + Expression noNegativeNumeral = makePositiveAnyNegativeNumeralFactor(context, angleUnit, ExpressionNode::ReductionTarget::User); // If one negative numeral factor was made positive, we turn the expression in an Opposite if (!noNegativeNumeral.isUninitialized()) { Opposite o = Opposite(); @@ -749,7 +749,7 @@ Expression Multiplication::mergeNegativePower(Context & context, Preferences::An while (i < numberOfChildren()) { if (childAtIndex(i).type() == ExpressionNode::Type::Power) { Expression p = childAtIndex(i); - Expression positivePIndex = p.childAtIndex(1).makePositiveAnyNegativeNumeralFactor(context, angleUnit); + Expression positivePIndex = p.childAtIndex(1).makePositiveAnyNegativeNumeralFactor(context, angleUnit, ExpressionNode::ReductionTarget::User); if (!positivePIndex.isUninitialized()) { // Remove a^(-b) from the Multiplication removeChildAtIndexInPlace(i); diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 57f389770..db8b037c3 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -47,8 +47,8 @@ ExpressionNode::Sign PowerNode::sign(Context * context, Preferences::AngleUnit a return Sign::Unknown; } -Expression PowerNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { - return Power(this).setSign(s, context, angleUnit); +Expression PowerNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Power(this).setSign(s, context, angleUnit, target); } int PowerNode::polynomialDegree(Context & context, const char * symbolName) const { @@ -238,10 +238,10 @@ Power::Power(Expression base, Expression exponent) : Expression(TreePool::shared replaceChildAtIndexInPlace(1, exponent); } -Expression Power::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit) { +Expression Power::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { assert(s == ExpressionNode::Sign::Positive); if (childAtIndex(0).sign(context, angleUnit) == ExpressionNode::Sign::Negative) { - Expression result = Power(childAtIndex(0).setSign(ExpressionNode::Sign::Positive, context, angleUnit), childAtIndex(1)); + Expression result = Power(childAtIndex(0).setSign(ExpressionNode::Sign::Positive, context, angleUnit, target), childAtIndex(1)); replaceWithInPlace(result); return result; } @@ -513,7 +513,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU && childAtIndex(1).type() == ExpressionNode::Type::Rational && childAtIndex(1).convert().isHalf()) { - Expression m0 = childAtIndex(0).makePositiveAnyNegativeNumeralFactor(context, angleUnit); + Expression m0 = childAtIndex(0).makePositiveAnyNegativeNumeralFactor(context, angleUnit, target); if (!m0.isUninitialized()) { replaceChildAtIndexInPlace(0, m0); //m0.shallowReduce(context, angleUnit, target); @@ -596,7 +596,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU // (sign(a)*b*...)^r if (factor.sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { m.replaceChildAtIndexInPlace(i, Rational(-1)); - factor = factor.setSign(ExpressionNode::Sign::Positive, &context, angleUnit); + factor = factor.setSign(ExpressionNode::Sign::Positive, &context, angleUnit, target); } else { m.removeChildAtIndexInPlace(i); } @@ -781,7 +781,7 @@ Expression Power::denominator(Context & context, Preferences::AngleUnit angleUni // Clone the power Expression clone = Power(childAtIndex(0).clone(), childAtIndex(1).clone()); // If the power is of form x^(-y), denominator should be x^y - Expression positiveIndex = clone.childAtIndex(1).makePositiveAnyNegativeNumeralFactor(context, angleUnit); + Expression positiveIndex = clone.childAtIndex(1).makePositiveAnyNegativeNumeralFactor(context, angleUnit, ExpressionNode::ReductionTarget::User); if (!positiveIndex.isUninitialized()) { // if y was -1, clone is now x^1, denominator is then only x // we cannot shallowReduce the clone as it is not attached to its parent yet @@ -855,7 +855,7 @@ Expression Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational r, bo if (numberOfPrimeFactors < 0) { /* We could not break i in prime factors (it might take either too many * factors or too much time). */ - Expression rClone = r.clone().setSign(isDenominator ? ExpressionNode::Sign::Negative : ExpressionNode::Sign::Positive, &context, angleUnit); + Expression rClone = r.clone().setSign(isDenominator ? ExpressionNode::Sign::Negative : ExpressionNode::Sign::Positive, &context, angleUnit, target); return Power(Rational(i), rClone); } diff --git a/poincare/src/random.cpp b/poincare/src/random.cpp index ef8efd518..11a959e01 100644 --- a/poincare/src/random.cpp +++ b/poincare/src/random.cpp @@ -12,7 +12,7 @@ constexpr Expression::FunctionHelper Random::s_functionHelper; int RandomNode::numberOfChildren() const { return Random::s_functionHelper.numberOfChildren(); } -Expression RandomNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { +Expression RandomNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) { return Random(this).setSign(s, context, angleUnit); } diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index 3141e8090..dd76bde78 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -98,7 +98,7 @@ int RationalNode::serialize(char * buffer, int bufferSize, Preferences::PrintFlo // Expression subclassing -Expression RationalNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { +Expression RationalNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) { return Rational(this).setSign(s); } diff --git a/poincare/src/sign_function.cpp b/poincare/src/sign_function.cpp index 913c4100e..6bfeccfa6 100644 --- a/poincare/src/sign_function.cpp +++ b/poincare/src/sign_function.cpp @@ -17,7 +17,7 @@ ExpressionNode::Sign SignFunctionNode::sign(Context * context, Preferences::Angl return childAtIndex(0)->sign(context, angleUnit); } -Expression SignFunctionNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { +Expression SignFunctionNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) { SignFunction sign(this); Rational r(s == ExpressionNode::Sign::Positive ? 1 : -1); sign.replaceWithInPlace(r); @@ -73,7 +73,7 @@ Expression SignFunction::shallowReduce(Context & context, Preferences::AngleUnit // c has no sign (c is complex or NAN) if (std::isnan(c.imag()) || std::isnan(c.real()) || c.imag() != 0) { // sign(-x) = sign(x) - Expression oppChild = child.makePositiveAnyNegativeNumeralFactor(context, angleUnit); + Expression oppChild = child.makePositiveAnyNegativeNumeralFactor(context, angleUnit, target); if (oppChild.isUninitialized()) { return *this; } else { diff --git a/poincare/src/symbol_abstract.cpp b/poincare/src/symbol_abstract.cpp index 4dfe4808a..0dab4e75b 100644 --- a/poincare/src/symbol_abstract.cpp +++ b/poincare/src/symbol_abstract.cpp @@ -37,12 +37,12 @@ ExpressionNode::Sign SymbolAbstractNode::sign(Context * context, Preferences::An return e.sign(context, angleUnit); } -Expression SymbolAbstractNode::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit) { +Expression SymbolAbstractNode::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) { SymbolAbstract sa(this); Expression e = SymbolAbstract::Expand(sa, *context, true); assert(!e.isUninitialized()); sa.replaceWithInPlace(e); - return e.setSign(s, context, angleUnit); + return e.setSign(s, context, angleUnit, target); } int SymbolAbstractNode::simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const { diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index c7dc75ba2..722a32440 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -116,7 +116,7 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& co } // Step 3. Look for an expression of type "cos(-a)", return "+/-cos(a)" - Expression positiveArg = e.childAtIndex(0).makePositiveAnyNegativeNumeralFactor(context, angleUnit); + Expression positiveArg = e.childAtIndex(0).makePositiveAnyNegativeNumeralFactor(context, angleUnit, target); if (!positiveArg.isUninitialized()) { // The argument was of form cos(-a) if (e.type() == ExpressionNode::Type::Cosine) { @@ -270,7 +270,7 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& c * arcsin(-x) = -arcsin(x), arctan(-x)= -arctan(x) * */ if (!letArcFunctionAtRoot) { - Expression positiveArg = e.childAtIndex(0).makePositiveAnyNegativeNumeralFactor(context, angleUnit); + Expression positiveArg = e.childAtIndex(0).makePositiveAnyNegativeNumeralFactor(context, angleUnit, target); if (!positiveArg.isUninitialized()) { // The argument was made positive // acos(-x) = pi-acos(x) diff --git a/poincare/src/undefined.cpp b/poincare/src/undefined.cpp index 020657a86..2928c987a 100644 --- a/poincare/src/undefined.cpp +++ b/poincare/src/undefined.cpp @@ -13,7 +13,7 @@ int UndefinedNode::polynomialDegree(Context & context, const char * symbolName) return -1; } -Expression UndefinedNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit) { +Expression UndefinedNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { return Undefined(this); } From 5463486d59301e0396339a4bcd5602dd4cc5c61a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 17 Dec 2018 13:38:23 +0100 Subject: [PATCH 108/373] [poincare] Fix Power::setSign --- poincare/src/power.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index db8b037c3..5147bbcaa 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -243,7 +243,7 @@ Expression Power::setSign(ExpressionNode::Sign s, Context * context, Preferences if (childAtIndex(0).sign(context, angleUnit) == ExpressionNode::Sign::Negative) { Expression result = Power(childAtIndex(0).setSign(ExpressionNode::Sign::Positive, context, angleUnit, target), childAtIndex(1)); replaceWithInPlace(result); - return result; + return result.shallowReduce(*context, angleUnit, target); } return *this; } From dae5c4d2d43375cdc17568c85251b5a09df1df96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 17 Dec 2018 14:54:48 +0100 Subject: [PATCH 109/373] [poincare] Constant: i->ComplexCartesian(0,1) only if the reduction target is the user --- poincare/include/poincare/constant.h | 2 +- poincare/src/constant.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/poincare/include/poincare/constant.h b/poincare/include/poincare/constant.h index ef3a385c7..acf8be0a4 100644 --- a/poincare/include/poincare/constant.h +++ b/poincare/include/poincare/constant.h @@ -58,7 +58,7 @@ public: bool isIComplex() const { return node()->isIComplex(); } // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: ConstantNode * node() const { return static_cast(Expression::node()); } diff --git a/poincare/src/constant.cpp b/poincare/src/constant.cpp index 3eb6f53be..12fc9fae4 100644 --- a/poincare/src/constant.cpp +++ b/poincare/src/constant.cpp @@ -46,15 +46,15 @@ Evaluation ConstantNode::templatedApproximate(Context& context, Preferences:: } Expression ConstantNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Constant(this).shallowReduce(context, angleUnit); + return Constant(this).shallowReduce(context, angleUnit, target); } Constant::Constant(char name) : SymbolAbstract(TreePool::sharedPool()->createTreeNode(SymbolAbstract::AlignedNodeSize(1, sizeof(ConstantNode)))) { node()->setName(&name, 1); } -Expression Constant::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { - if (isIComplex()) { +Expression Constant::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + if (target == ExpressionNode::ReductionTarget::User && isIComplex()) { ComplexCartesian c = ComplexCartesian::Builder(Rational(0), Rational(1)); replaceWithInPlace(c); return c; From c6039423a9ab6108973568e38bf01cfa8b0ad3b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 17 Dec 2018 16:12:39 +0100 Subject: [PATCH 110/373] [poincare] When simplifying an expression, also compute the approximation from the reduced expression to avoid loss of precision. If an expression is reduced to a ComplexCartesian(a, b), we compute the approximation from ComplexCartesian(a,b) instead of going through the potentially complicated expression resulting from beautifying (sqrt(a^2+b^2)*exp(i*(arctan(b/a) -Pi/2*sign(b)) for example) --- apps/calculation/calculation.cpp | 7 +- apps/shared/poincare_helpers.h | 12 +++- apps/solver/equation_store.cpp | 22 +++--- apps/solver/equation_store.h | 4 +- poincare/include/poincare/complex_cartesian.h | 7 +- poincare/include/poincare/expression.h | 8 ++- poincare/src/complex_cartesian.cpp | 13 ++++ poincare/src/expression.cpp | 69 ++++++++++++++++--- 8 files changed, 111 insertions(+), 31 deletions(-) diff --git a/apps/calculation/calculation.cpp b/apps/calculation/calculation.cpp index 631cc295a..9684f13bd 100644 --- a/apps/calculation/calculation.cpp +++ b/apps/calculation/calculation.cpp @@ -48,9 +48,10 @@ void Calculation::setContent(const char * c, Context * context, Expression ansEx * to keep Ans symbol in the calculation store. */ PoincareHelpers::Serialize(input, m_inputText, sizeof(m_inputText)); } - Expression exactOutput = PoincareHelpers::ParseAndSimplify(m_inputText, *context); + Expression exactOutput; + Expression approximateOutput; + PoincareHelpers::ParseAndSimplifyAndApproximate(m_inputText, &exactOutput, &approximateOutput, *context); PoincareHelpers::Serialize(exactOutput, m_exactOutputText, sizeof(m_exactOutputText)); - Expression approximateOutput = PoincareHelpers::Approximate(exactOutput, *context); PoincareHelpers::Serialize(approximateOutput, m_approximateOutputText, sizeof(m_approximateOutputText)); } @@ -178,7 +179,7 @@ Calculation::EqualSign Calculation::exactAndApproximateDisplayedOutputsAreEqual( if (exactOutputExpression.isUninitialized()) { exactOutputExpression = Undefined(); } - m_equalSign = exactOutputExpression.isEqualToItsApproximationLayout(approximateOutput(context), buffer, bufferSize, preferences->angleUnit(), preferences->complexFormat(), preferences->displayMode(), preferences->numberOfSignificantDigits(), *context) ? EqualSign::Equal : EqualSign::Approximation; + m_equalSign = exactOutputExpression.isEqualToItsApproximationLayout(approximateOutput(context), buffer, bufferSize, preferences->angleUnit(), preferences->displayMode(), preferences->numberOfSignificantDigits(), *context) ? EqualSign::Equal : EqualSign::Approximation; return m_equalSign; } diff --git a/apps/shared/poincare_helpers.h b/apps/shared/poincare_helpers.h index 3e89dadcf..b666dd159 100644 --- a/apps/shared/poincare_helpers.h +++ b/apps/shared/poincare_helpers.h @@ -38,11 +38,19 @@ inline T ApproximateToScalar(const char * text, Poincare::Context & context) { } inline Poincare::Expression ParseAndSimplify(const char * text, Poincare::Context & context) { - return Poincare::Expression::ParseAndSimplify(text, context, Poincare::Preferences::sharedPreferences()->angleUnit(), Poincare::Preferences::sharedPreferences()->complexFormat()); + return Poincare::Expression::ParseAndSimplify(text, context, Poincare::Preferences::sharedPreferences()->angleUnit()); } inline void Simplify(Poincare::Expression * e, Poincare::Context & context) { - *e = e->simplify(context, Poincare::Preferences::sharedPreferences()->angleUnit(), Poincare::Preferences::sharedPreferences()->complexFormat()); + *e = e->simplify(context, Poincare::Preferences::sharedPreferences()->angleUnit()); +} + +inline void ParseAndSimplifyAndApproximate(const char * text, Poincare::Expression * simplifiedExpression, Poincare::Expression * approximateExpression, Poincare::Context & context) { + Poincare::Expression::ParseAndSimplifyAndApproximate(text, simplifiedExpression, approximateExpression, context, Poincare::Preferences::sharedPreferences()->angleUnit(), Poincare::Preferences::sharedPreferences()->complexFormat()); +} + +inline void SimplifyAndApproximate(Poincare::Expression * e, Poincare::Expression * approximate, Poincare::Context & context) { + e->simplifyAndApproximate(e, approximate, context, Poincare::Preferences::sharedPreferences()->angleUnit(), Poincare::Preferences::sharedPreferences()->complexFormat()); } } diff --git a/apps/solver/equation_store.cpp b/apps/solver/equation_store.cpp index 6ad5830d5..37f126b18 100644 --- a/apps/solver/equation_store.cpp +++ b/apps/solver/equation_store.cpp @@ -145,11 +145,12 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) { /* Initialize result */ Expression exactSolutions[k_maxNumberOfExactSolutions]; + Expression exactSolutionsApproximations[k_maxNumberOfExactSolutions]; EquationStore::Error error; if (isLinear) { m_type = Type::LinearSystem; - error = resolveLinearSystem(exactSolutions, coefficients, constants, context); + error = resolveLinearSystem(exactSolutions, exactSolutionsApproximations, coefficients, constants, context); } else { /* 2- Polynomial & Monovariable? */ assert(numberOfVariables == 1 && numberOfDefinedModels() == 1); @@ -158,7 +159,7 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) { if (degree == 2) { /* Polynomial degree <= 2*/ m_type = Type::PolynomialMonovariable; - error = oneDimensialPolynomialSolve(exactSolutions, polynomialCoefficients, degree, context); + error = oneDimensialPolynomialSolve(exactSolutions, exactSolutionsApproximations, polynomialCoefficients, degree, context); } else { /* 3- Monovariable non-polynomial or polynomial with degree > 2 */ m_type = Type::Monovariable; @@ -171,8 +172,7 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) { for (int i = 0; i < k_maxNumberOfExactSolutions; i++) { if (!exactSolutions[i].isUninitialized()) { m_exactSolutionExactLayouts[i] = PoincareHelpers::CreateLayout(exactSolutions[i]); - Expression approximate = PoincareHelpers::Approximate(exactSolutions[i], *context); - m_exactSolutionApproximateLayouts[i] = PoincareHelpers::CreateLayout(approximate); + m_exactSolutionApproximateLayouts[i] = PoincareHelpers::CreateLayout(exactSolutionsApproximations[i]); /* Check for identity between exact and approximate layouts */ char exactBuffer[Shared::ExpressionModel::k_expressionBufferSize]; char approximateBuffer[Shared::ExpressionModel::k_expressionBufferSize]; @@ -182,14 +182,14 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) { /* Check for equality between exact and approximate layouts */ if (!m_exactSolutionIdentity[i]) { char buffer[Shared::ExpressionModel::k_expressionBufferSize]; - m_exactSolutionEquality[i] = exactSolutions[i].isEqualToItsApproximationLayout(approximate, buffer, Shared::ExpressionModel::k_expressionBufferSize, preferences->angleUnit(), preferences->complexFormat(), preferences->displayMode(), preferences->numberOfSignificantDigits(), *context); + m_exactSolutionEquality[i] = exactSolutions[i].isEqualToItsApproximationLayout(exactSolutionsApproximations[i], buffer, Shared::ExpressionModel::k_expressionBufferSize, preferences->angleUnit(), preferences->displayMode(), preferences->numberOfSignificantDigits(), *context); } } } return error; } -EquationStore::Error EquationStore::resolveLinearSystem(Expression exactSolutions[k_maxNumberOfExactSolutions], Expression coefficients[k_maxNumberOfEquations][Expression::k_maxNumberOfVariables], Expression constants[k_maxNumberOfEquations], Context * context) { +EquationStore::Error EquationStore::resolveLinearSystem(Expression exactSolutions[k_maxNumberOfExactSolutions], Expression exactSolutionsApproximations[k_maxNumberOfExactSolutions], Expression coefficients[k_maxNumberOfEquations][Expression::k_maxNumberOfVariables], Expression constants[k_maxNumberOfEquations], Context * context) { Preferences::AngleUnit angleUnit = Preferences::sharedPreferences()->angleUnit(); // n unknown variables int n = 0; @@ -231,19 +231,20 @@ EquationStore::Error EquationStore::resolveLinearSystem(Expression exactSolution m_numberOfSolutions = n; for (int i = 0; i < m_numberOfSolutions; i++) { exactSolutions[i] = Ab.matrixChild(i,n); - PoincareHelpers::Simplify(&exactSolutions[i], *context); + PoincareHelpers::SimplifyAndApproximate(&exactSolutions[i], &exactSolutionsApproximations[i], *context); } } } return Error::NoError; } -EquationStore::Error EquationStore::oneDimensialPolynomialSolve(Expression exactSolutions[k_maxNumberOfExactSolutions], Expression coefficients[Expression::k_maxNumberOfPolynomialCoefficients], int degree, Context * context) { +EquationStore::Error EquationStore::oneDimensialPolynomialSolve(Expression exactSolutions[k_maxNumberOfExactSolutions], Expression exactSolutionsApproximations[k_maxNumberOfExactSolutions], Expression coefficients[Expression::k_maxNumberOfPolynomialCoefficients], int degree, Context * context) { /* Equation ax^2+bx+c = 0 */ assert(degree == 2); // Compute delta = b*b-4ac Expression delta = Subtraction(Power(coefficients[1].clone(), Rational(2)), Multiplication(Rational(4), coefficients[0].clone(), coefficients[2].clone())); - PoincareHelpers::Simplify(&delta, *context); + exactSolutions[m_numberOfSolutions] = delta; + PoincareHelpers::SimplifyAndApproximate(&delta, &exactSolutionsApproximations[m_numberOfSolutions], *context); if (delta.isRationalZero()) { // if delta = 0, x0=x1= -b/(2a) exactSolutions[0] = Division(Opposite(coefficients[1]), Multiplication(Rational(2), coefficients[2])); @@ -255,9 +256,8 @@ EquationStore::Error EquationStore::oneDimensialPolynomialSolve(Expression exact exactSolutions[1] = Division(Addition(Opposite(coefficients[1]), SquareRoot::Builder(delta.clone())), Multiplication(Rational(2), coefficients[2])); m_numberOfSolutions = 2; } - exactSolutions[m_numberOfSolutions] = delta; for (int i = 0; i < m_numberOfSolutions; i++) { - PoincareHelpers::Simplify(&exactSolutions[i], *context); + PoincareHelpers::SimplifyAndApproximate(&exactSolutions[i], &exactSolutionsApproximations[i], *context); } return Error::NoError; #if 0 diff --git a/apps/solver/equation_store.h b/apps/solver/equation_store.h index b57ab0086..1a12433bb 100644 --- a/apps/solver/equation_store.h +++ b/apps/solver/equation_store.h @@ -79,8 +79,8 @@ private: return emptyModel(); } void setModelAtIndex(Shared::ExpressionModel * f, int i) override; - Error resolveLinearSystem(Poincare::Expression solutions[k_maxNumberOfExactSolutions], Poincare::Expression coefficients[k_maxNumberOfEquations][Poincare::Expression::k_maxNumberOfVariables], Poincare::Expression constants[k_maxNumberOfEquations], Poincare::Context * context); - Error oneDimensialPolynomialSolve(Poincare::Expression solutions[k_maxNumberOfExactSolutions], Poincare::Expression polynomialCoefficients[Poincare::Expression::k_maxNumberOfPolynomialCoefficients], int degree, Poincare::Context * context); + Error resolveLinearSystem(Poincare::Expression solutions[k_maxNumberOfExactSolutions], Poincare::Expression solutionApproximations[k_maxNumberOfExactSolutions], Poincare::Expression coefficients[k_maxNumberOfEquations][Poincare::Expression::k_maxNumberOfVariables], Poincare::Expression constants[k_maxNumberOfEquations], Poincare::Context * context); + Error oneDimensialPolynomialSolve(Poincare::Expression solutions[k_maxNumberOfExactSolutions], Poincare::Expression solutionApproximations[k_maxNumberOfExactSolutions], Poincare::Expression polynomialCoefficients[Poincare::Expression::k_maxNumberOfPolynomialCoefficients], int degree, Poincare::Context * context); void tidySolution(); Equation m_equations[k_maxNumberOfEquations]; diff --git a/poincare/include/poincare/complex_cartesian.h b/poincare/include/poincare/complex_cartesian.h index a8f7a25c3..5223fdc28 100644 --- a/poincare/include/poincare/complex_cartesian.h +++ b/poincare/include/poincare/complex_cartesian.h @@ -24,11 +24,14 @@ private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override { assert(false); return Layout(); } // Evaluation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { assert(false); return Evaluation(); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { assert(false); return Evaluation(); } + Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } // Simplification Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) override; + +private: + template Complex templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; }; class ComplexCartesian final : public Expression { diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 7b9339469..1790062df 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -174,15 +174,17 @@ public: * same structures and all their nodes have same types and values (ie, * sqrt(pi^2) is NOT identical to pi). */ bool isIdenticalTo(const Expression e) const; - bool isEqualToItsApproximationLayout(Expression approximation, char * buffer, int bufferSize, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits, Context & context); + bool isEqualToItsApproximationLayout(Expression approximation, char * buffer, int bufferSize, Preferences::AngleUnit angleUnit, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits, Context & context); /* Layout Helper */ Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const; /* Simplification */ - static Expression ParseAndSimplify(const char * text, Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat); - Expression simplify(Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat); + static Expression ParseAndSimplify(const char * text, Context & context, Preferences::AngleUnit angleUnit); + static void ParseAndSimplifyAndApproximate(const char * text, Expression * simplifiedExpression, Expression * approximateExpression, Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat); + Expression simplify(Context & context, Preferences::AngleUnit angleUnit); + void simplifyAndApproximate(Expression * simplifiedExpression, Expression * approximateExpression, Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat); Expression reduce(Context & context, Preferences::AngleUnit angleUnit); static Expression ExpressionWithoutSymbols(Expression expressionWithSymbols, Context & context); Expression radianToDegree(); diff --git a/poincare/src/complex_cartesian.cpp b/poincare/src/complex_cartesian.cpp index e81773b39..981313cb3 100644 --- a/poincare/src/complex_cartesian.cpp +++ b/poincare/src/complex_cartesian.cpp @@ -26,6 +26,19 @@ Expression ComplexCartesianNode::shallowBeautify(Context & context, Preferences: return ComplexCartesian(this).shallowBeautify(context, angleUnit); } +template +Complex ComplexCartesianNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { + Evaluation realEvaluation = childAtIndex(0)->approximate(T(), context, angleUnit); + Evaluation imagEvalution = childAtIndex(1)->approximate(T(), context, angleUnit); + assert(realEvaluation.type() == EvaluationNode::Type::Complex); + assert(imagEvalution.type() == EvaluationNode::Type::Complex); + std::complex a = static_cast &>(realEvaluation).stdComplex(); + std::complex b = static_cast &>(imagEvalution).stdComplex(); + assert(a.imag() == 0.0); + assert(b.imag() == 0.0); + return Complex(a.real(), b.real()); +} + Expression ComplexCartesian::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { if (imag().isRationalZero()) { Expression r = real(); diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 90d68a682..6b8b401e1 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -323,7 +323,7 @@ bool Expression::isIdenticalTo(const Expression e) const { return ExpressionNode::SimplificationOrder(node(), e.node(), true) == 0; } -bool Expression::isEqualToItsApproximationLayout(Expression approximation, char * buffer, int bufferSize, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits, Context & context) { +bool Expression::isEqualToItsApproximationLayout(Expression approximation, char * buffer, int bufferSize, Preferences::AngleUnit angleUnit, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits, Context & context) { approximation.serialize(buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits); /* Warning: we cannot use directly the the approximate expression but we have * to re-serialize it because the number of stored significative @@ -331,7 +331,7 @@ bool Expression::isEqualToItsApproximationLayout(Expression approximation, char * identical. (For example, 0.000025 might be displayed "0.00003" and stored * as Decimal(0.000025) and isEqualToItsApproximationLayout should return * false) */ - Expression approximateOutput = Expression::ParseAndSimplify(buffer, context, angleUnit, complexFormat); + Expression approximateOutput = Expression::ParseAndSimplify(buffer, context, angleUnit); bool equal = isIdenticalTo(approximateOutput); return equal; } @@ -346,12 +346,12 @@ int Expression::serialize(char * buffer, int bufferSize, Preferences::PrintFloat /* Simplification */ -Expression Expression::ParseAndSimplify(const char * text, Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) { +Expression Expression::ParseAndSimplify(const char * text, Context & context, Preferences::AngleUnit angleUnit) { Expression exp = Parse(text); if (exp.isUninitialized()) { return Undefined(); } - exp = exp.simplify(context, angleUnit, complexFormat); + exp = exp.simplify(context, angleUnit); /* simplify might have been interrupted, in which case the resulting * expression is uninitialized, so we need to check that. */ if (exp.isUninitialized()) { @@ -360,6 +360,34 @@ Expression Expression::ParseAndSimplify(const char * text, Context & context, Pr return exp; } +void Expression::ParseAndSimplifyAndApproximate(const char * text, Expression * simplifiedExpression, Expression * approximateExpression, Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) { + assert(simplifiedExpression); + Expression exp = Parse(text); + if (exp.isUninitialized()) { + *simplifiedExpression = Undefined(); + *approximateExpression = Undefined(); + return; + } + exp.simplifyAndApproximate(simplifiedExpression, approximateExpression, context, angleUnit, complexFormat); + /* simplify might have been interrupted, in which case the resulting + * expression is uninitialized, so we need to check that. */ + if (simplifiedExpression->isUninitialized()) { + *simplifiedExpression = Parse(text); + if (approximateExpression) { + *approximateExpression = simplifiedExpression->approximate(context, angleUnit, complexFormat); + } + } +} + +Expression Expression::simplify(Context & context, Preferences::AngleUnit angleUnit) { + sSimplificationHasBeenInterrupted = false; + Expression e = deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); + if (!sSimplificationHasBeenInterrupted) { + e = e.deepBeautify(context, angleUnit); + } + return sSimplificationHasBeenInterrupted ? Expression() : e; +} + void makePositive(Expression * e, bool * isNegative) { if (e->type() == ExpressionNode::Type::Opposite) { *isNegative = true; @@ -367,12 +395,33 @@ void makePositive(Expression * e, bool * isNegative) { } } -Expression Expression::simplify(Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) { +void Expression::simplifyAndApproximate(Expression * simplifiedExpression, Expression * approximateExpression, Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) { + assert(simplifiedExpression); sSimplificationHasBeenInterrupted = false; + // Step 1: we reduce the expression Expression e = deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); + *simplifiedExpression = Expression(); if (!sSimplificationHasBeenInterrupted) { + /* Case 1: the reduced expression is ComplexCartesian, we can take + * into account the complex format to display a+i*b or r*e^(i*th) */ if (e.type() == ExpressionNode::Type::ComplexCartesian) { ComplexCartesian ecomplex = static_cast(e); + if (approximateExpression) { + /* Step 2: Approximation + * We compute the approximate expression from the Cartesian form to avoid + * unprecision. For example, if the result is the ComplexCartesian(a,b), + * the final expression is goind to be sqrt(a^2+b^2)*exp(i*arctan(b/a)... + * in Polar ComplexFormat. If we approximate this expression instead of + * ComplexCartesian(a,b), we are going to loose precision on the resulting + * complex.*/ + // Clone the ComplexCartesian to use it to compute the approximation + ComplexCartesian ecomplexClone = ecomplex.clone().convert(); + // To minimize the error on the approximation, we reduce the number of nodes in the expression by beautifying + ecomplexClone.real().deepBeautify(context, angleUnit); + ecomplexClone.imag().deepBeautify(context, angleUnit); + *approximateExpression = ecomplexClone.approximate(context, angleUnit, complexFormat); + } + // Step 3: create the simplied expression with the required complex format Expression ra = complexFormat == Preferences::ComplexFormat::Cartesian ? ecomplex.real() : ecomplex.clone().convert().norm(context, angleUnit, ExpressionNode::ReductionTarget::User).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); Expression tb = complexFormat == Preferences::ComplexFormat::Cartesian ? ecomplex.imag() : ecomplex.argument(context, angleUnit, ExpressionNode::ReductionTarget::User).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); ra = ra.deepBeautify(context, angleUnit); @@ -381,12 +430,16 @@ Expression Expression::simplify(Context & context, Preferences::AngleUnit angleU bool tbIsNegative = false; makePositive(&ra, &raIsNegative); makePositive(&tb, &tbIsNegative); - e = CreateComplexExpression(ra, tb, complexFormat, ra.type() == ExpressionNode::Type::Undefined || tb.type() == ExpressionNode::Type::Undefined, isZero(ra), isOne(ra), isZero(tb), isOne(tb), raIsNegative, tbIsNegative); + *simplifiedExpression = CreateComplexExpression(ra, tb, complexFormat, ra.type() == ExpressionNode::Type::Undefined || tb.type() == ExpressionNode::Type::Undefined, isZero(ra), isOne(ra), isZero(tb), isOne(tb), raIsNegative, tbIsNegative); } else { - e = e.deepBeautify(context, angleUnit); + /* Case 2: The reduced expression has a complex component that could not + * be bubbled up. */ + *simplifiedExpression = e.deepBeautify(context, angleUnit); + if (approximateExpression) { + *approximateExpression = simplifiedExpression->approximate(context, angleUnit, complexFormat); + } } } - return sSimplificationHasBeenInterrupted ? Expression() : e; } Expression Expression::ExpressionWithoutSymbols(Expression e, Context & context) { From e4b59ddf69b7f9935f9b79061172bc5dcfb8592a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 17 Dec 2018 16:17:00 +0100 Subject: [PATCH 111/373] [poincare] Fix Expression::simplifyAndApproximate to display polar form of negative real expression. -5 --> 5*e^(i*Pi) --- poincare/src/expression.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 6b8b401e1..c3397080f 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -402,10 +402,10 @@ void Expression::simplifyAndApproximate(Expression * simplifiedExpression, Expre Expression e = deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); *simplifiedExpression = Expression(); if (!sSimplificationHasBeenInterrupted) { - /* Case 1: the reduced expression is ComplexCartesian, we can take - * into account the complex format to display a+i*b or r*e^(i*th) */ - if (e.type() == ExpressionNode::Type::ComplexCartesian) { - ComplexCartesian ecomplex = static_cast(e); + /* Case 1: the reduced expression is ComplexCartesian or pure real, we can + * take into account the complex format to display a+i*b or r*e^(i*th) */ + if (e.type() == ExpressionNode::Type::ComplexCartesian || e.isReal(context, angleUnit)) { + ComplexCartesian ecomplex = e.type() == ExpressionNode::Type::ComplexCartesian ? static_cast(e) : ComplexCartesian::Builder(e, Rational(0)); if (approximateExpression) { /* Step 2: Approximation * We compute the approximate expression from the Cartesian form to avoid From ff77b4627600d39d0accf345a52fbbd6b41b7c5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 18 Dec 2018 12:06:22 +0100 Subject: [PATCH 112/373] [poincare] Power::shallowReduce. Fix bug: I complex should always be shallowReduced as it turns into ComplexCartesian(0,1) if the reduction target is the User and stays Constant(I) otherwise. --- poincare/include/poincare/power.h | 2 +- poincare/src/power.cpp | 27 ++++++++++++++++----------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index e672bdcc8..cead102dc 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -89,7 +89,7 @@ private: bool parentIsALogarithmOfSameBase() const; bool isNthRootOfUnity() const; Expression equivalentExpressionUsingStandardExpression() const; - static Expression CreateComplexExponent(const Expression & r); // Returns e^(i*pi*r) + static Expression CreateComplexExponent(const Expression & r, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); // Returns e^(i*pi*r) static bool TermIsARationalSquareRootOrRational(const Expression& e); static const Rational RadicandInExpression(const Expression & e); static const Rational RationalFactorInExpression(const Expression & e); diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 5147bbcaa..e6c9d0adf 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -453,16 +453,16 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU } } - /*if (target == ExpressionNode::ReductionTarget::User && childAtIndex(1).type() == ExpressionNode::Type::Rational) { + if (childAtIndex(1).type() == ExpressionNode::Type::Rational) { const Rational b = childAtIndex(1).convert(); // i^(p/q) if (childAtIndex(0).type() == ExpressionNode::Type::Constant && childAtIndex(0).convert().isIComplex()) { Number r = Number::Multiplication(b, Rational(1, 2)); - Expression result = CreateComplexExponent(r); + Expression result = CreateComplexExponent(r, context, angleUnit, target); replaceWithInPlace(result); return result.shallowReduce(context, angleUnit, target); } - }*/ + } // (±inf)^x if (childAtIndex(0).type() == ExpressionNode::Type::Infinity) { @@ -519,14 +519,17 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU //m0.shallowReduce(context, angleUnit, target); Multiplication m1 = Multiplication(); replaceWithInPlace(m1); - m1.addChildAtIndexInPlace(Constant(Ion::Charset::IComplex), 0, 0); + // Multiply m1 by i complex + Constant i(Ion::Charset::IComplex); + m1.addChildAtIndexInPlace(i, 0, 0); + i.shallowReduce(context, angleUnit, target); m1.addChildAtIndexInPlace(*this, 1, 1); shallowReduce(context, angleUnit, target); return m1.shallowReduce(context, angleUnit, target); } } // e^(i*Pi*r) with r rational - /*if (!letPowerAtRoot && isNthRootOfUnity()) { + if (!letPowerAtRoot && isNthRootOfUnity()) { Expression m = childAtIndex(1); Expression i = m.childAtIndex(m.numberOfChildren()-1); static_cast(m).removeChildAtIndexInPlace(m.numberOfChildren()-1); @@ -543,7 +546,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU complexPart.shallowReduce(context, angleUnit, target); replaceWithInPlace(a); return a.shallowReduce(context, angleUnit, target); - }*/ + } // x^log(y,x)->y if y > 0 if (childAtIndex(1).type() == ExpressionNode::Type::Logarithm) { if (childAtIndex(1).numberOfChildren() == 2 && childAtIndex(0).isIdenticalTo(childAtIndex(1).childAtIndex(1))) { @@ -887,7 +890,7 @@ Expression Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational r, bo m.addChildAtIndexInPlace(p, 1, 1); } if (i.isNegative()) { - Expression exp = CreateComplexExponent(r); + Expression exp = CreateComplexExponent(r, context, angleUnit, target); m.addChildAtIndexInPlace(exp, m.numberOfChildren(), m.numberOfChildren()); exp.shallowReduce(context, angleUnit, target); } @@ -1073,14 +1076,16 @@ Expression Power::equivalentExpressionUsingStandardExpression() const { return Expression(); } -Expression Power::CreateComplexExponent(const Expression & r) { +Expression Power::CreateComplexExponent(const Expression & r, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { // Returns e^(i*pi*r) const Constant exp = Constant(Ion::Charset::Exponential); - const Constant iComplex = Constant(Ion::Charset::IComplex); + Constant iComplex = Constant(Ion::Charset::IComplex); const Constant pi = Constant(Ion::Charset::SmallPi); Multiplication mExp = Multiplication(iComplex, pi, r.clone()); - mExp.sortChildrenInPlace(PowerNode::SimplificationOrder, false); - return Power(exp, mExp); + iComplex.shallowReduce(context, angleUnit, target); + Power p(exp, mExp); + mExp.shallowReduce(context, angleUnit, target); + return p; #if 0 const Constant iComplex = Constant(Ion::Charset::IComplex); const Constant pi = Constant(Ion::Charset::SmallPi); From 8f45cae35829dbab9081e045248d5206253e42bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 18 Dec 2018 12:07:53 +0100 Subject: [PATCH 113/373] [poincare] ComplexCartesian: fix bug due to clone missing --- poincare/src/complex_cartesian.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/complex_cartesian.cpp b/poincare/src/complex_cartesian.cpp index 981313cb3..481f206b9 100644 --- a/poincare/src/complex_cartesian.cpp +++ b/poincare/src/complex_cartesian.cpp @@ -280,7 +280,7 @@ ComplexCartesian ComplexCartesian::power(ComplexCartesian & other, Context & con Expression c = other.real(); Expression d = other.imag(); // R = r^c*e^(-th*d) - Expression rpowc = Power(rclone, c); + Expression rpowc = Power(rclone, c.clone()); rclone.shallowReduce(context, angleUnit, target); Expression thmuld = Multiplication(Rational(-1), thclone, d.clone()); thclone.shallowReduce(context, angleUnit, target); From 9401edfd3fa09e688c072462e8b54801e1885f2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 18 Dec 2018 12:08:34 +0100 Subject: [PATCH 114/373] [poincare] Clean outdated comment --- poincare/include/poincare/expression_node.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index fe6eac9e8..2f5a6be7e 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -126,14 +126,6 @@ public: bool isOfType(Type * types, int length) const; /* Complex */ - /* TODO: we could turn i in ComplexCartesian(0,1) in the shallowReduce applied - * to i. In this case, we would handle ComplexCartesian as a number and - * implement all computations (+, *, ^) in Number ?? We would have to handle - * ComplexCartesian in all Node::shallowReduce... We would then turn - * ComplexCartesian into something readable in the - * ComplexCartesian::shallowBeautify. This would enable us to do only one - * scan of the tree in ParseAndSimplifyForComplexFormat instead of Simplifying - * and then extracting ComplexCartesian. */ virtual bool isReal(Context & context, Preferences::AngleUnit angleUnit) const { return false; } /* Simplification */ From 42aad48ec4f0007eafcc5b04bfec0238de1e1a63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 18 Dec 2018 15:32:32 +0100 Subject: [PATCH 115/373] [solver] Fix EquationStore::oneDimensialPolynomialSolve --- apps/solver/equation_store.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/apps/solver/equation_store.cpp b/apps/solver/equation_store.cpp index 37f126b18..caae2088d 100644 --- a/apps/solver/equation_store.cpp +++ b/apps/solver/equation_store.cpp @@ -12,6 +12,7 @@ #include #include #include +#include using namespace Poincare; using namespace Shared; @@ -243,8 +244,10 @@ EquationStore::Error EquationStore::oneDimensialPolynomialSolve(Expression exact assert(degree == 2); // Compute delta = b*b-4ac Expression delta = Subtraction(Power(coefficients[1].clone(), Rational(2)), Multiplication(Rational(4), coefficients[0].clone(), coefficients[2].clone())); - exactSolutions[m_numberOfSolutions] = delta; - PoincareHelpers::SimplifyAndApproximate(&delta, &exactSolutionsApproximations[m_numberOfSolutions], *context); + PoincareHelpers::Simplify(&delta, *context); + if (delta.isUninitialized()) { + delta = Poincare::Undefined(); + } if (delta.isRationalZero()) { // if delta = 0, x0=x1= -b/(2a) exactSolutions[0] = Division(Opposite(coefficients[1]), Multiplication(Rational(2), coefficients[2])); @@ -256,7 +259,8 @@ EquationStore::Error EquationStore::oneDimensialPolynomialSolve(Expression exact exactSolutions[1] = Division(Addition(Opposite(coefficients[1]), SquareRoot::Builder(delta.clone())), Multiplication(Rational(2), coefficients[2])); m_numberOfSolutions = 2; } - for (int i = 0; i < m_numberOfSolutions; i++) { + exactSolutions[m_numberOfSolutions] = delta; + for (int i = 0; i <= m_numberOfSolutions; i++) { PoincareHelpers::SimplifyAndApproximate(&exactSolutions[i], &exactSolutionsApproximations[i], *context); } return Error::NoError; From c4758873d218996ff8026a94c1d5bcb07712ab4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 18 Dec 2018 15:33:17 +0100 Subject: [PATCH 116/373] [poincare] ComplexCartesian: when computing the squareNorm, simplify cos^2+sin^2 --- poincare/include/poincare/complex_cartesian.h | 1 + poincare/src/complex_cartesian.cpp | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/poincare/include/poincare/complex_cartesian.h b/poincare/include/poincare/complex_cartesian.h index 5223fdc28..622615ef5 100644 --- a/poincare/include/poincare/complex_cartesian.h +++ b/poincare/include/poincare/complex_cartesian.h @@ -63,6 +63,7 @@ private: replaceChildAtIndexInPlace(0, child0); replaceChildAtIndexInPlace(1, child1); } + void factorAndArgumentOfFunction(Expression e, ExpressionNode::Type searchedType, Expression * factor, Expression * argument, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); static Multiplication squareRootHelper(Expression e, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); static Expression powerHelper(Expression norm, Expression trigo, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); }; diff --git a/poincare/src/complex_cartesian.cpp b/poincare/src/complex_cartesian.cpp index 481f206b9..399d1f1a6 100644 --- a/poincare/src/complex_cartesian.cpp +++ b/poincare/src/complex_cartesian.cpp @@ -65,9 +65,38 @@ Expression ComplexCartesian::shallowBeautify(Context & context, Preferences::Ang return e; } +void ComplexCartesian::factorAndArgumentOfFunction(Expression e, ExpressionNode::Type searchedType, Expression * factor, Expression * argument, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + if (e.type() == searchedType) { + *factor = Rational(1); + *argument = e.childAtIndex(0); + return; + } + if (e.type() == ExpressionNode::Type::Multiplication) { + for (int i = 0; i < e.numberOfChildren(); i++) { + if (e.childAtIndex(i).type() == searchedType) { + *argument = e.childAtIndex(i).childAtIndex(0); + *factor = e.clone(); + static_cast(factor)->removeChildAtIndexInPlace(i); + *factor = factor->shallowReduce(context, angleUnit, target); + Expression positiveFactor = factor->makePositiveAnyNegativeNumeralFactor(context, angleUnit, target); + *factor = positiveFactor.isUninitialized() ? *factor : positiveFactor; + return; + } + } + } +} + Expression ComplexCartesian::squareNorm(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { Expression a = real(); Expression b = imag(); + Expression aFactor, bFactor, aArgument, bArgument; + factorAndArgumentOfFunction(a, ExpressionNode::Type::Cosine, &aFactor, &aArgument, context, angleUnit, target); + factorAndArgumentOfFunction(b, ExpressionNode::Type::Sine, &bFactor, &bArgument, context, angleUnit, target); + if (!aFactor.isUninitialized() && !aArgument.isUninitialized() && !bFactor.isUninitialized() && !bArgument.isUninitialized() && aFactor.isIdenticalTo(bFactor) && aArgument.isIdenticalTo(bArgument)) { + Power result(aFactor, Rational(2)); + aFactor.shallowReduce(context, angleUnit, target); + return result; + } Expression a2 = Power(a, Rational(2)); Expression b2 = Power(b, Rational(2)); Addition add(a2, b2); From 0d8306aa7b76871541b90562901f8530a55d1188 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 18 Dec 2018 15:33:57 +0100 Subject: [PATCH 117/373] [poincare] Fix pow: do not bubble ComplexCartesian if the parent of the pow is a Logarithm of the same base --- poincare/src/power.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index e6c9d0adf..4ff88ce55 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -393,6 +393,15 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU } } + /* We do not apply some rules to a^b if: + * - the parent node is a logarithm of same base a. In this case there is a + * simplication of form ln(e^(3^(1/2))->3^(1/2). + * - the reduction is being BottomUpComputation. In this case, we do not yet have any + * information on the parent which could later be a logarithm of the same + * base. + */ + bool letPowerAtRoot = target == ExpressionNode::ReductionTarget::BottomUpComputation || parentIsALogarithmOfSameBase(); + /* Step 1: we now bubble up ComplexCartesian, we handle different cases: * At least, one child is a ComplexCartesian and the other is either a * ComplexCartesian or real. */ @@ -404,7 +413,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU * For q = -1, 1/2, -1/2, n with n integer < 10, we avoid introducing arctangent * by using the formula (r*e^(i*th))^(a+ib) = r^a*e(-th*b)*e^(b*ln(r)+th*a). * Instead, we rather use the cartesian form of the base and the index. */ - if (base.type() == ExpressionNode::Type::ComplexCartesian) { + if (!letPowerAtRoot && base.type() == ExpressionNode::Type::ComplexCartesian) { complexBase = static_cast(base); Integer ten(10); if (index.type() == ExpressionNode::Type::Rational) { @@ -434,9 +443,9 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU } } // All other cases where one child at least is a ComplexCartesian - if ((base.isReal(context, angleUnit) && index.type() == ExpressionNode::Type::ComplexCartesian) || - (base.type() == ExpressionNode::Type::ComplexCartesian && index.isReal(context, angleUnit)) || - (base.type() == ExpressionNode::Type::ComplexCartesian && index.type() == ExpressionNode::Type::ComplexCartesian)) { + if ((!letPowerAtRoot && base.isReal(context, angleUnit) && index.type() == ExpressionNode::Type::ComplexCartesian) || + (!letPowerAtRoot && base.type() == ExpressionNode::Type::ComplexCartesian && index.isReal(context, angleUnit)) || + (!letPowerAtRoot && base.type() == ExpressionNode::Type::ComplexCartesian && index.type() == ExpressionNode::Type::ComplexCartesian)) { complexBase = base.type() == ExpressionNode::Type::ComplexCartesian ? static_cast(base) : ComplexCartesian::Builder(base, Rational(0)); complexIndex = index.type() == ExpressionNode::Type::ComplexCartesian ? static_cast(index) : ComplexCartesian::Builder(index, Rational(0)); result = complexBase.power(complexIndex, context, angleUnit, target); @@ -486,14 +495,6 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU } } - /* We do not apply some rules to a^b if: - * - the parent node is a logarithm of same base a. In this case there is a - * simplication of form ln(e^(3^(1/2))->3^(1/2). - * - the reduction is being BottomUpComputation. In this case, we do not yet have any - * information on the parent which could later be a logarithm of the same - * base. - */ - bool letPowerAtRoot = target == ExpressionNode::ReductionTarget::BottomUpComputation || parentIsALogarithmOfSameBase(); if (!letPowerAtRoot && childAtIndex(0).type() == ExpressionNode::Type::Rational) { Rational a = childAtIndex(0).convert(); // p^q with p, q rationals From 1671ee8ec8b135fba4850ddcc9a598d684cba938 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 18 Dec 2018 16:07:28 +0100 Subject: [PATCH 118/373] [poincare] Fix Undefined:: isReal is false --- poincare/include/poincare/undefined.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/include/poincare/undefined.h b/poincare/include/poincare/undefined.h index ae0006e0f..d9ce9f4db 100644 --- a/poincare/include/poincare/undefined.h +++ b/poincare/include/poincare/undefined.h @@ -17,7 +17,7 @@ public: #endif // Complex - using ExpressionNode::isReal; + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return false; } // Properties Type type() const override { return Type::Undefined; } From 6df1e3aee718dfe329bb1c4602bf9db44d73e3cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 18 Dec 2018 16:19:57 +0100 Subject: [PATCH 119/373] [poincare] Fix ComplexCartesian approximation --- poincare/src/complex_cartesian.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/poincare/src/complex_cartesian.cpp b/poincare/src/complex_cartesian.cpp index 399d1f1a6..5ba4e4ed9 100644 --- a/poincare/src/complex_cartesian.cpp +++ b/poincare/src/complex_cartesian.cpp @@ -34,8 +34,8 @@ Complex ComplexCartesianNode::templatedApproximate(Context& context, Preferen assert(imagEvalution.type() == EvaluationNode::Type::Complex); std::complex a = static_cast &>(realEvaluation).stdComplex(); std::complex b = static_cast &>(imagEvalution).stdComplex(); - assert(a.imag() == 0.0); - assert(b.imag() == 0.0); + assert(a.imag() == 0.0 || std::isnan(a.imag())); + assert(b.imag() == 0.0 || std::isnan(b.imag())); return Complex(a.real(), b.real()); } From c89fec872c29ef1ecbd358f8b3dc525974e00d77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 18 Dec 2018 16:20:35 +0100 Subject: [PATCH 120/373] [poincare] Constant: missing template declaration --- poincare/src/constant.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/poincare/src/constant.cpp b/poincare/src/constant.cpp index 12fc9fae4..37f0a841d 100644 --- a/poincare/src/constant.cpp +++ b/poincare/src/constant.cpp @@ -62,4 +62,6 @@ Expression Constant::shallowReduce(Context & context, Preferences::AngleUnit ang return *this; } +template Evaluation ConstantNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; +template Evaluation ConstantNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; } From a02fd614ab69ca483661e2ddf368ec36ff07393f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 18 Dec 2018 18:04:18 +0100 Subject: [PATCH 121/373] [poincare] Trigonometry: add rule arctan(1/x) = sign(x)*pi/2-arctan(x) --- poincare/src/trigonometry.cpp | 20 ++++++++++++++++++-- poincare/test/trigo.cpp | 1 + 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 722a32440..23717ac1d 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -252,7 +253,22 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& c } } - // Step 3. Try finding an easy standard calculation reduction + // Step 3. Look for an expression of type "arctan(1/X), return sign(x)*Pi/2-arctan(x) + if (e.type() == ExpressionNode::Type::ArcTangent && e.childAtIndex(0).type() == ExpressionNode::Type::Power && e.childAtIndex(0).childAtIndex(1).type() == ExpressionNode::Type::Rational && e.childAtIndex(0).childAtIndex(1).convert().isMinusOne()) { + Expression x = e.childAtIndex(0).childAtIndex(0); + Expression sign = SignFunction::Builder(x.clone()); + Multiplication m0(Rational(1,2), sign, Constant(Ion::Charset::SmallPi)); + sign.shallowReduce(context, angleUnit, target); + e.replaceChildAtIndexInPlace(0, x); + Addition a(m0); + e.replaceWithInPlace(a); + Multiplication m1(Rational(-1), e); + e.shallowReduce(context, angleUnit, target); + a.addChildAtIndexInPlace(m1, 1, 1); + return a.shallowReduce(context, angleUnit, target); + } + + // Step 4. Try finding an easy standard calculation reduction Expression lookup = Trigonometry::table(e.childAtIndex(0), e.type(), context, angleUnit, target); if (!lookup.isUninitialized()) { e.replaceWithInPlace(lookup); @@ -266,7 +282,7 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& c * information on the parent which could later be a cosine, a sine or a tangent. */ bool letArcFunctionAtRoot = target == ExpressionNode::ReductionTarget::BottomUpComputation || parentIsDirectTrigonometry(e); - /* Step 4. Handle opposite argument: arccos(-x) = Pi-arcos(x), + /* Step 5. Handle opposite argument: arccos(-x) = Pi-arcos(x), * arcsin(-x) = -arcsin(x), arctan(-x)= -arctan(x) * */ if (!letArcFunctionAtRoot) { diff --git a/poincare/test/trigo.cpp b/poincare/test/trigo.cpp index 511896557..c86d2114b 100644 --- a/poincare/test/trigo.cpp +++ b/poincare/test/trigo.cpp @@ -511,6 +511,7 @@ QUIZ_CASE(poincare_trigo_simplify) { assert_parsed_expression_simplify_to("atan(tan(1808))", "8", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("atan(tan(-180/7))", "-180/7", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("atan(R(3))", "60", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("atan(1/x)", "(-2*atan(x)+sign(x)*P)/2", Preferences::AngleUnit::Degree); // cos(arcsin) assert_parsed_expression_simplify_to("cos(asin(x))", "R(1-x^2)", Preferences::AngleUnit::Degree); From df2f6e3b6efb986439391234af128816fb9e81f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 18 Dec 2018 16:21:05 +0100 Subject: [PATCH 122/373] [poincare] Fix tests with complex cas --- apps/solver/test/equation_store.cpp | 2 +- poincare/test/complex.cpp | 218 ++++++++++++---------------- poincare/test/helper.cpp | 26 ++-- poincare/test/helper.h | 2 +- poincare/test/layouts.cpp | 6 +- poincare/test/logarithm.cpp | 2 +- poincare/test/power.cpp | 10 +- poincare/test/properties.cpp | 6 +- poincare/test/simplify_mix.cpp | 10 +- 9 files changed, 133 insertions(+), 149 deletions(-) diff --git a/apps/solver/test/equation_store.cpp b/apps/solver/test/equation_store.cpp index 55c5d00f8..30e1279d5 100644 --- a/apps/solver/test/equation_store.cpp +++ b/apps/solver/test/equation_store.cpp @@ -105,7 +105,7 @@ QUIZ_CASE(equation_solve) { // 3x^2-4x+4=2 const char * equations8[] = {"3*x^2-4x+4=2", 0}; - const char * solutions8[] = {"(2-R(2)*I)/(3)","(2+R(2)*I)/(3)", "-8"}; + const char * solutions8[] = {"(2)/(3)-(R(2))/(3)*I","(2)/(3)+(R(2))/(3)*I", "-8"}; assert_equation_system_exact_solve_to(equations8, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions8, 2); // 2*x^2-4*x+4=3 diff --git a/poincare/test/complex.cpp b/poincare/test/complex.cpp index 15f460e84..b44fb6808 100644 --- a/poincare/test/complex.cpp +++ b/poincare/test/complex.cpp @@ -6,156 +6,128 @@ using namespace Poincare; -void assert_expression_has_complex_cartesian_parts(const char * expression, const char * real, const char * imag, Preferences::AngleUnit angleUnit = Degree) { - Shared::GlobalContext context; - Expression e = parse_expression(expression).reduce(context, angleUnit); - ComplexCartesian cartesian = e.complexCartesian(context, angleUnit); - if (cartesian.isUninitialized()) { - assert(real == nullptr); - assert(imag == nullptr); - } else { - cartesian.real().simplify(context, angleUnit); - cartesian.imag().simplify(context, angleUnit); - assert_parsed_expression_serialize_to(cartesian.real(), real); - assert_parsed_expression_serialize_to(cartesian.imag(), imag); - } -} - -void assert_expression_has_complex_polar_parts(const char * expression, const char * norm, const char * arg, Preferences::AngleUnit angleUnit = Degree) { - Shared::GlobalContext context; - Expression e = parse_expression(expression).simplify(context, angleUnit); - ComplexPolar polar = e.complexPolar(context, angleUnit); - if (polar.isUninitialized()) { - assert(norm == nullptr); - assert(arg == nullptr); - } else { - polar.norm().simplify(context, angleUnit); - polar.arg().simplify(context, angleUnit); - assert_parsed_expression_serialize_to(polar.norm(), norm); - assert_parsed_expression_serialize_to(polar.arg(), arg); - } -} - QUIZ_CASE(poincare_complex_parts) { - assert_expression_has_complex_cartesian_parts("-2.3E3", "-2300", "0"); - assert_expression_has_complex_cartesian_parts("3", "3", "0"); - assert_expression_has_complex_cartesian_parts("inf", "inf", "0"); - assert_expression_has_complex_cartesian_parts("1+2+I", "3", "1"); - assert_expression_has_complex_cartesian_parts("-(5+2*I)", "-5", "-2"); - assert_expression_has_complex_cartesian_parts("(5+2*I)", "5", "2"); - assert_expression_has_complex_cartesian_parts("I+I", "0", "2"); - assert_expression_has_complex_cartesian_parts("-2+2*I", "-2", "2"); - assert_expression_has_complex_cartesian_parts("(3+I)-(2+4*I)", "1", "-3"); - assert_expression_has_complex_cartesian_parts("(2+3*I)*(4-2*I)", "14", "8"); - assert_expression_has_complex_cartesian_parts("(3+I)/2", "3/2", "1/2"); - assert_expression_has_complex_cartesian_parts("(3+I)/(2+I)", "7/5", "-1/5"); - assert_expression_has_complex_cartesian_parts("(3+I)^(2+I)", "10*cos((-4*atan(3)+ln(2)+ln(5)+2*P)/2)*X^((2*atan(3)-P)/2)", "10*sin((-4*atan(3)+ln(2)+ln(5)+2*P)/2)*X^((2*atan(3)-P)/2)", Radian); - assert_expression_has_complex_cartesian_parts("R(1+6I)", "R(2+2*R(37))/2", "R(-2+2*R(37))/2"); - assert_expression_has_complex_cartesian_parts("(1+I)^2", "0", "2"); - assert_expression_has_complex_cartesian_parts("2*I", "0", "2"); - assert_expression_has_complex_cartesian_parts("I!", "undef", "0"); - assert_expression_has_complex_cartesian_parts("3!", "6", "0"); - assert_expression_has_complex_cartesian_parts("x!", "x!", "0"); - assert_expression_has_complex_cartesian_parts("X", "X", "0"); - assert_expression_has_complex_cartesian_parts("P", "P", "0"); - assert_expression_has_complex_cartesian_parts("I", "0", "1"); + assert_parsed_expression_simplify_to("-2.3E3", "-2300", Radian, Cartesian); + assert_parsed_expression_simplify_to("3", "3", Radian, Cartesian); + assert_parsed_expression_simplify_to("inf", "inf", Radian, Cartesian); + assert_parsed_expression_simplify_to("1+2+I", "3+I", Radian, Cartesian); + assert_parsed_expression_simplify_to("-(5+2*I)", "-5-2*I", Radian, Cartesian); + assert_parsed_expression_simplify_to("(5+2*I)", "5+2*I", Radian, Cartesian); + assert_parsed_expression_simplify_to("I+I", "2*I", Radian, Cartesian); + assert_parsed_expression_simplify_to("-2+2*I", "-2+2*I", Radian, Cartesian); + assert_parsed_expression_simplify_to("(3+I)-(2+4*I)", "1-3*I", Radian, Cartesian); + assert_parsed_expression_simplify_to("(2+3*I)*(4-2*I)", "14+8*I", Radian, Cartesian); + assert_parsed_expression_simplify_to("(3+I)/2", "3/2+1/2*I", Radian, Cartesian); + assert_parsed_expression_simplify_to("(3+I)/(2+I)", "7/5-1/5*I", Radian, Cartesian); + assert_parsed_expression_simplify_to("(3+I)^(2+I)", "10*cos((-4*atan(3)+ln(2)+ln(5)+2*P)/2)*X^((2*atan(3)-P)/2)+10*sin((-4*atan(3)+ln(2)+ln(5)+2*P)/2)*X^((2*atan(3)-P)/2)*I", Radian, Cartesian); + assert_parsed_expression_simplify_to("R(1+6I)", "R(2+2*R(37))/2+R(-2+2*R(37))/2*I", Radian, Cartesian); + assert_parsed_expression_simplify_to("(1+I)^2", "2*I", Radian, Cartesian); + assert_parsed_expression_simplify_to("2*I", "2*I", Radian, Cartesian); + assert_parsed_expression_simplify_to("I!", "I!", Radian, Cartesian); + assert_parsed_expression_simplify_to("3!", "6", Radian, Cartesian); + assert_parsed_expression_simplify_to("x!", "x!", Radian, Cartesian); + assert_parsed_expression_simplify_to("X", "X", Radian, Cartesian); + assert_parsed_expression_simplify_to("P", "P", Radian, Cartesian); + assert_parsed_expression_simplify_to("I", "I", Radian, Cartesian); - assert_expression_has_complex_cartesian_parts("abs(-3)", "3", "0"); - assert_expression_has_complex_cartesian_parts("abs(-3+I)", "R(10)", "0"); - assert_expression_has_complex_cartesian_parts("atan(2)", "atan(2)", "0"); - assert_expression_has_complex_cartesian_parts("atan(2+I)", nullptr, nullptr); - assert_expression_has_complex_cartesian_parts("binomial(10, 4)", "210", "0"); - assert_expression_has_complex_cartesian_parts("ceil(-1.3)", "-1", "0"); - assert_expression_has_complex_cartesian_parts("arg(-2)", "P", "0"); + assert_parsed_expression_simplify_to("abs(-3)", "3", Radian, Cartesian); + assert_parsed_expression_simplify_to("abs(-3+I)", "R(10)", Radian, Cartesian); + assert_parsed_expression_simplify_to("atan(2)", "atan(2)", Radian, Cartesian); + assert_parsed_expression_simplify_to("atan(2+I)", "atan(2+I)", Radian, Cartesian); + assert_parsed_expression_simplify_to("binomial(10, 4)", "210", Radian, Cartesian); + assert_parsed_expression_simplify_to("ceil(-1.3)", "-1", Radian, Cartesian); + assert_parsed_expression_simplify_to("arg(-2)", "P", Radian, Cartesian); // TODO: confidence is not simplified yet - //assert_expression_has_complex_cartesian_parts("confidence(-2,-3)", "confidence(-2)", "0"); - assert_expression_has_complex_cartesian_parts("conj(-2)", "-2", "0"); - assert_expression_has_complex_cartesian_parts("conj(-2+2*I+I)", "-2", "-3"); - assert_expression_has_complex_cartesian_parts("cos(12)", "cos(12)", "0"); - assert_expression_has_complex_cartesian_parts("cos(12+I)", nullptr, nullptr); - assert_expression_has_complex_cartesian_parts("diff(3*x, x, 3)", "diff(3*x,x,3)", "0"); - assert_expression_has_complex_cartesian_parts("quo(34,x)", "quo(34,x)", "0"); - assert_expression_has_complex_cartesian_parts("rem(5,3)", "2", "0"); - assert_expression_has_complex_cartesian_parts("floor(x)", "floor(x)", "0"); - assert_expression_has_complex_cartesian_parts("frac(x)", "frac(x)", "0"); - assert_expression_has_complex_cartesian_parts("gcd(x,y)", "gcd(x,y)", "0"); - assert_expression_has_complex_cartesian_parts("im(1+I)", "1", "0"); - assert_expression_has_complex_cartesian_parts("int(x^2, x, 1, 2)", "int(x^2,x,1,2)", "0"); - assert_expression_has_complex_cartesian_parts("lcm(x,y)", "lcm(x,y)", "0"); + //assert_parsed_expression_simplify_to("confidence(-2,-3)", "confidence(-2)", Radian, Cartesian); + assert_parsed_expression_simplify_to("conj(-2)", "-2", Radian, Cartesian); + assert_parsed_expression_simplify_to("conj(-2+2*I+I)", "-2-3*I", Radian, Cartesian); + assert_parsed_expression_simplify_to("cos(12)", "cos(12)", Radian, Cartesian); + assert_parsed_expression_simplify_to("cos(12+I)", "cos(12+I)", Radian, Cartesian); + assert_parsed_expression_simplify_to("diff(3*x, x, 3)", "diff(3*x,x,3)", Radian, Cartesian); + assert_parsed_expression_simplify_to("quo(34,x)", "quo(34,x)", Radian, Cartesian); + assert_parsed_expression_simplify_to("rem(5,3)", "2", Radian, Cartesian); + assert_parsed_expression_simplify_to("floor(x)", "floor(x)", Radian, Cartesian); + assert_parsed_expression_simplify_to("frac(x)", "frac(x)", Radian, Cartesian); + assert_parsed_expression_simplify_to("gcd(x,y)", "gcd(x,y)", Radian, Cartesian); + assert_parsed_expression_simplify_to("im(1+I)", "1", Radian, Cartesian); + assert_parsed_expression_simplify_to("int(x^2, x, 1, 2)", "int(x^2,x,1,2)", Radian, Cartesian); + assert_parsed_expression_simplify_to("lcm(x,y)", "lcm(x,y)", Radian, Cartesian); // TODO: dim is not simplified yet - //assert_expression_has_complex_cartesian_parts("dim(x)", "dim(x)", "0"); + //assert_parsed_expression_simplify_to("dim(x)", "dim(x)", Radian, Cartesian); - assert_expression_has_complex_cartesian_parts("root(2,I)", "cos(ln(2))", "-sin(ln(2))", Radian); - assert_expression_has_complex_cartesian_parts("root(2,I+1)", "R(2)*cos((90*ln(2))/P)", "-R(2)*sin((90*ln(2))/P)"); - assert_expression_has_complex_cartesian_parts("root(2,I+1)", "R(2)*cos(ln(2)/2)", "-R(2)*sin(ln(2)/2)", Radian); - assert_expression_has_complex_cartesian_parts("permute(10, 4)", "5040", "0"); + assert_parsed_expression_simplify_to("root(2,I)", "cos(ln(2))-sin(ln(2))*I", Radian, Cartesian); + assert_parsed_expression_simplify_to("root(2,I+1)", "R(2)*cos((90*ln(2))/P)-R(2)*sin((90*ln(2))/P)*I", Degree, Cartesian); + assert_parsed_expression_simplify_to("root(2,I+1)", "R(2)*cos(ln(2)/2)-R(2)*sin(ln(2)/2)*I", Radian, Cartesian); + assert_parsed_expression_simplify_to("permute(10, 4)", "5040", Radian, Cartesian); // TODO: prediction is not simplified yet - //assert_expression_has_complex_cartesian_parts("prediction(-2,-3)", "prediction(-2)", "0"); - assert_expression_has_complex_cartesian_parts("randint(2,4)", "randint(2,4)", "0"); - assert_expression_has_complex_cartesian_parts("random()", "random()", "0"); - assert_expression_has_complex_cartesian_parts("re(x)", "x", "0"); - assert_expression_has_complex_cartesian_parts("round(x,y)", "round(x,y)", "0"); - assert_expression_has_complex_cartesian_parts("sign(x)", "sign(x)", "0"); - assert_expression_has_complex_cartesian_parts("sin(23)", "sin(23)", "0"); - assert_expression_has_complex_cartesian_parts("sin(23+I)", nullptr, nullptr); - assert_expression_has_complex_cartesian_parts("R(1-I)", "R(2+2*R(2))/2", "-R(-2+2*R(2))/2"); - assert_expression_has_complex_cartesian_parts("tan(23)", "tan(23)", "0"); - assert_expression_has_complex_cartesian_parts("tan(23+I)", nullptr, nullptr); + //assert_parsed_expression_simplify_to("prediction(-2,-3)", "prediction(-2)", Radian, Cartesian); + assert_parsed_expression_simplify_to("randint(2,4)", "randint(2,4)", Radian, Cartesian); + assert_parsed_expression_simplify_to("random()", "random()", Radian, Cartesian); + assert_parsed_expression_simplify_to("re(x)", "x", Radian, Cartesian); + assert_parsed_expression_simplify_to("round(x,y)", "round(x,y)", Radian, Cartesian); + assert_parsed_expression_simplify_to("sign(x)", "sign(x)", Radian, Cartesian); + assert_parsed_expression_simplify_to("sin(23)", "sin(23)", Radian, Cartesian); + assert_parsed_expression_simplify_to("sin(23+I)", "sin(23+I)", Radian, Cartesian); + assert_parsed_expression_simplify_to("R(1-I)", "R(2+2*R(2))/2-R(-2+2*R(2))/2*I", Radian, Cartesian); + assert_parsed_expression_simplify_to("tan(23)", "tan(23)", Radian, Cartesian); + assert_parsed_expression_simplify_to("tan(23+I)", "tan(23+I)", Radian, Cartesian); // User defined variable - assert_expression_has_complex_cartesian_parts("a", "a", "0"); + assert_parsed_expression_simplify_to("a", "a", Radian, Cartesian); // a = 2+i assert_simplify("2+I>a"); - assert_expression_has_complex_cartesian_parts("a", "2", "1"); + assert_parsed_expression_simplify_to("a", "2+I", Radian, Cartesian); // Clean the storage for other tests Ion::Storage::sharedStorage()->recordNamed("a.exp").destroy(); // User defined function - assert_expression_has_complex_cartesian_parts("f(3)", "f(3)", "0"); + assert_parsed_expression_simplify_to("f(3)", "f(3)", Radian, Cartesian); // f: x -> x+1 assert_simplify("x+1+I>f(x)"); - assert_expression_has_complex_cartesian_parts("f(3)", "4", "1"); + assert_parsed_expression_simplify_to("f(3)", "4+I", Radian, Cartesian); // Clean the storage for other tests Ion::Storage::sharedStorage()->recordNamed("f.func").destroy(); - assert_expression_has_complex_polar_parts("-2.3E3", "2300", "P"); - assert_expression_has_complex_polar_parts("3", "3", "0"); - assert_expression_has_complex_polar_parts("inf", "inf", "0"); - assert_expression_has_complex_polar_parts("1+2+I", "R(10)", "(-2*atan(3)+P)/2", Radian); - assert_expression_has_complex_polar_parts("1+2+I", "R(10)", "(90*P-atan(3)*P)/180"); - assert_expression_has_complex_polar_parts("-(5+2*I)", "R(29)", "(-2*atan(5/2)-P)/2", Radian); - assert_expression_has_complex_polar_parts("(5+2*I)", "R(29)", "(-2*atan(5/2)+P)/2", Radian); - assert_expression_has_complex_polar_parts("I+I", "2", "P/2", Radian); - assert_expression_has_complex_polar_parts("I+I", "2", "P/2"); - assert_expression_has_complex_polar_parts("-2+2*I", "2*R(2)", "(3*P)/4", Radian); - assert_expression_has_complex_polar_parts("(3+I)-(2+4*I)", "R(10)", "(2*atan(1/3)-P)/2", Radian); - assert_expression_has_complex_polar_parts("(2+3*I)*(4-2*I)", "2*R(65)", "(-2*atan(7/4)+P)/2", Radian); - assert_expression_has_complex_polar_parts("(3+I)/2", "R(10)/2", "(-2*atan(3)+P)/2", Radian); - assert_expression_has_complex_polar_parts("(3+I)/(2+I)", "R(2)", "(2*atan(7)-P)/2", Radian); - assert_expression_has_complex_polar_parts("(3+I)^(2+I)", "10*X^((2*atan(3)-P)/2)", "(-4*atan(3)+ln(2)+ln(5)+2*P)/2", Radian); - assert_expression_has_complex_polar_parts("(1+I)^2", "2", "P/2"); - assert_expression_has_complex_polar_parts("2*I", "2", "P/2"); - assert_expression_has_complex_polar_parts("3!", "6", "0"); - assert_expression_has_complex_polar_parts("x!", "x!", "0"); - assert_expression_has_complex_polar_parts("X", "X", "0"); - assert_expression_has_complex_polar_parts("P", "P", "0"); - assert_expression_has_complex_polar_parts("I", "1", "P/2"); - assert_expression_has_complex_polar_parts("abs(-3)", "3", "0"); - assert_expression_has_complex_polar_parts("abs(-3+I)", "R(10)", "0"); - assert_expression_has_complex_polar_parts("conj(2*X^(I*cos(2)))", "2", "-cos(2)"); - assert_expression_has_complex_polar_parts("-2*X^(I*cos(2))", "2", "cos(2)+P"); + assert_parsed_expression_simplify_to("-2.3E3", "2300*X^(P*I)", Radian, Polar); + assert_parsed_expression_simplify_to("3", "3", Radian, Polar); + assert_parsed_expression_simplify_to("inf", "inf", Radian, Polar); + assert_parsed_expression_simplify_to("1+2+I", "R(10)*X^((-2*atan(3)+P)/2*I)", Radian, Polar); + assert_parsed_expression_simplify_to("1+2+I", "R(10)*X^((90*P-atan(3)*P)/180*I)", Degree, Polar); + assert_parsed_expression_simplify_to("-(5+2*I)", "R(29)*X^((-2*atan(5/2)-P)/2*I)", Radian, Polar); + assert_parsed_expression_simplify_to("(5+2*I)", "R(29)*X^((-2*atan(5/2)+P)/2*I)", Radian, Polar); + assert_parsed_expression_simplify_to("I+I", "2*X^(P/2*I)", Radian, Polar); + assert_parsed_expression_simplify_to("I+I", "2*X^(P/2*I)", Radian, Polar); + assert_parsed_expression_simplify_to("-2+2*I", "2*R(2)*X^((3*P)/4*I)", Radian, Polar); + assert_parsed_expression_simplify_to("(3+I)-(2+4*I)", "R(10)*X^((2*atan(1/3)-P)/2*I)", Radian, Polar); + assert_parsed_expression_simplify_to("(2+3*I)*(4-2*I)", "2*R(65)*X^((-2*atan(7/4)+P)/2*I)", Radian, Polar); + assert_parsed_expression_simplify_to("(3+I)/2", "R(10)/2*X^((-2*atan(3)+P)/2*I)", Radian, Polar); + assert_parsed_expression_simplify_to("(3+I)/(2+I)", "R(2)*X^((2*atan(7)-P)/2*I)", Radian, Polar); + // TODO: simplify atan(tan(x)) = x±k*pi? + //assert_parsed_expression_simplify_to("(3+I)^(2+I)", "10*X^((2*atan(3)-P)/2)*X^((-4*atan(3)+ln(2)+ln(5)+2*P)/2*I)", Radian, Polar); + assert_parsed_expression_simplify_to("(3+I)^(2+I)", "10*X^((2*atan(3)-P)/2)*X^((atan(tan((-4*atan(3)+ln(2)+ln(5)+2*P)/2))+P)*I)", Radian, Polar); + assert_parsed_expression_simplify_to("(1+I)^2", "2*X^(P/2*I)", Radian, Polar); + assert_parsed_expression_simplify_to("2*I", "2*X^(P/2*I)", Radian, Polar); + assert_parsed_expression_simplify_to("3!", "6", Radian, Polar); + assert_parsed_expression_simplify_to("x!", "x!", Radian, Polar); + assert_parsed_expression_simplify_to("X", "X", Radian, Polar); + assert_parsed_expression_simplify_to("P", "P", Radian, Polar); + assert_parsed_expression_simplify_to("I", "X^(P/2*I)", Radian, Polar); + assert_parsed_expression_simplify_to("abs(-3)", "3", Radian, Polar); + assert_parsed_expression_simplify_to("abs(-3+I)", "R(10)", Radian, Polar); + assert_parsed_expression_simplify_to("conj(2*X^(I*P/2))", "2*X^(-P/2*I)", Radian, Polar); + assert_parsed_expression_simplify_to("-2*X^(I*P/2)", "2*X^(-P/2*I)", Radian, Polar); // User defined variable - assert_expression_has_complex_polar_parts("a", "R(a^2)", "(P-sign(a)*P)/2"); + assert_parsed_expression_simplify_to("a", "R(a^2)*X^((P-sign(a)*P)/2*I)", Radian, Polar); // a = 2+i assert_simplify("2+I>a"); - assert_expression_has_complex_polar_parts("a", "R(5", "(-2*atan(2)+P)/2"); + assert_parsed_expression_simplify_to("a", "R(5)*X^((-2*atan(2)+P)/2*I)", Radian, Polar); // Clean the storage for other tests Ion::Storage::sharedStorage()->recordNamed("a.exp").destroy(); // User defined function - assert_expression_has_complex_polar_parts("f(3)", "R(f(3)^2)", "(P-sign(f(3))*P)/2"); + assert_parsed_expression_simplify_to("f(3)", "R(f(3)^2)*X^((P-sign(f(3))*P)/2*I)", Radian, Polar); // f: x -> x+1 assert_simplify("x+1+I>f(x)"); - assert_expression_has_complex_polar_parts("f(3)", "R(17)", "(-2*atan(4)+P)/2"); + assert_parsed_expression_simplify_to("f(3)", "R(17)*X^((-2*atan(4)+P)/2*I)", Radian, Polar); // Clean the storage for other tests Ion::Storage::sharedStorage()->recordNamed("f.func").destroy(); diff --git a/poincare/test/helper.cpp b/poincare/test/helper.cpp index bbc7c1720..936c518e8 100644 --- a/poincare/test/helper.cpp +++ b/poincare/test/helper.cpp @@ -106,7 +106,7 @@ void assert_parsed_expression_is(const char * expression, Poincare::Expression r void assert_parsed_expression_polynomial_degree(const char * expression, int degree, const char * symbolName) { Shared::GlobalContext globalContext; Expression e = parse_expression(expression); - Expression result = e.clone().simplify(globalContext, Radian); + Expression result = e.clone().reduce(globalContext, Radian); if (result.isUninitialized()) { result = e; } @@ -150,12 +150,12 @@ void assert_parsed_expression_evaluates_to(const char * expression, const char * int numberOfDigits = sizeof(T) == sizeof(double) ? PrintFloat::k_numberOfStoredSignificantDigits : PrintFloat::k_numberOfPrintedSignificantDigits; numberOfDigits = numberOfSignificantDigits > 0 ? numberOfSignificantDigits : numberOfDigits; assert_parsed_expression_process_to(expression, approximation, angleUnit, complexFormat, [](Expression e, Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) { - Expression result = e.clone().simplify(context, angleUnit); - if (result.isUninitialized()) { - result = e; - } - return result.approximate(context, angleUnit, complexFormat); - }, numberOfDigits); + Expression result = e.clone().simplify(context, angleUnit); + if (result.isUninitialized()) { + result = e; + } + return result.approximate(context, angleUnit, complexFormat); + }, numberOfDigits); } template @@ -165,16 +165,18 @@ void assert_parsed_expression_approximates_with_value_for_symbol(Expression expr quiz_assert(std::fabs(result - approximation) < 10.0*Expression::epsilon()); } -void assert_parsed_expression_simplify_to(const char * expression, const char * simplifiedExpression, Preferences::AngleUnit angleUnit) { +void assert_parsed_expression_simplify_to(const char * expression, const char * simplifiedExpression, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) { #if POINCARE_TESTS_PRINT_EXPRESSIONS cout << "--------- Simplification ---------" << endl; #endif - assert_parsed_expression_process_to(expression, simplifiedExpression, angleUnit, Preferences::ComplexFormat::Cartesian, [](Expression e, Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) { - Expression result = e.clone().simplify(context, angleUnit); - if (result.isUninitialized()) { + assert_parsed_expression_process_to(expression, simplifiedExpression, angleUnit, complexFormat, [](Expression e, Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) { + Expression copy = e.clone(); + copy.simplifyAndApproximate(©, nullptr, context, angleUnit, complexFormat); + if (copy.isUninitialized()) { return e; } - return result;}); + return copy; + }); } void assert_parsed_expression_serialize_to(Expression expression, const char * serializedExpression, Preferences::PrintFloatMode mode, int numberOfSignifiantDigits) { diff --git a/poincare/test/helper.h b/poincare/test/helper.h index cbd3084ef..00a0e8f20 100644 --- a/poincare/test/helper.h +++ b/poincare/test/helper.h @@ -31,7 +31,7 @@ void assert_parsed_expression_evaluates_to(const char * expression, const char * template void assert_parsed_expression_approximates_with_value_for_symbol(Poincare::Expression expression, const char * symbol, T value, T approximation, Poincare::Preferences::AngleUnit angleUnit = Degree); -void assert_parsed_expression_simplify_to(const char * expression, const char * simplifiedExpression, Poincare::Preferences::AngleUnit angleUnit = Poincare::Preferences::AngleUnit::Radian); +void assert_parsed_expression_simplify_to(const char * expression, const char * simplifiedExpression, Poincare::Preferences::AngleUnit angleUnit = Poincare::Preferences::AngleUnit::Radian, Poincare::Preferences::ComplexFormat complexFormat = Poincare::Preferences::ComplexFormat::Cartesian); void assert_parsed_expression_serialize_to(Poincare::Expression expression, const char * serializedExpression, Poincare::Preferences::PrintFloatMode mode = DecimalMode, int numberOfSignifiantDigits = 7); diff --git a/poincare/test/layouts.cpp b/poincare/test/layouts.cpp index e90da6bdf..59133fb96 100644 --- a/poincare/test/layouts.cpp +++ b/poincare/test/layouts.cpp @@ -14,13 +14,15 @@ void assert_parsed_layout_is(Layout l, Poincare::Expression r) { char buffer[bufferSize]; l.serializeForParsing(buffer, bufferSize); Expression e = parse_expression(buffer); - Expression eSimplified = e.clone().simplify(context, Preferences::AngleUnit::Degree); + Expression eSimplified; + e.clone().simplifyAndApproximate(&eSimplified, nullptr, context, Degree, Cartesian); if (eSimplified.isUninitialized()) { /* In case the simplification is impossible (if there are matrices for * instance), use the non simplified expression */ eSimplified = e; } - Expression rSimplified = r.clone().simplify(context, Preferences::AngleUnit::Degree); + Expression rSimplified; + r.clone().simplifyAndApproximate(&rSimplified, nullptr, context, Degree, Cartesian); if (rSimplified.isUninitialized()) { /* In case the simplification is impossible (if there are matrices for * instance), use the non simplified expression */ diff --git a/poincare/test/logarithm.cpp b/poincare/test/logarithm.cpp index d2628b7cf..89320e40d 100644 --- a/poincare/test/logarithm.cpp +++ b/poincare/test/logarithm.cpp @@ -43,7 +43,7 @@ QUIZ_CASE(poincare_logarithm_simplify) { assert_parsed_expression_simplify_to("log(R(3),R(3))", "1"); assert_parsed_expression_simplify_to("log(1/R(2))", "-log(2)/2"); assert_parsed_expression_simplify_to("log(-I)", "log(-I)"); - assert_parsed_expression_simplify_to("ln(X^(IP/7))", "(P*I)/7"); + assert_parsed_expression_simplify_to("ln(X^(IP/7))", "P/7*I"); assert_parsed_expression_simplify_to("log(10^24)", "24"); assert_parsed_expression_simplify_to("log((23P)^4,23P)", "4"); assert_parsed_expression_simplify_to("log(10^(2+P))", "2+P"); diff --git a/poincare/test/power.cpp b/poincare/test/power.cpp index 027d828a6..f21693f34 100644 --- a/poincare/test/power.cpp +++ b/poincare/test/power.cpp @@ -29,6 +29,12 @@ QUIZ_CASE(poincare_power_evaluate) { assert_parsed_expression_evaluates_to("X^(I*P)", "-1"); assert_parsed_expression_evaluates_to("X^(I*P+2)", "-7.38906", Radian, Cartesian, 6); assert_parsed_expression_evaluates_to("X^(I*P+2)", "-7.3890560989307"); + assert_parsed_expression_evaluates_to("(-1)^(1/3)", "0.5+0.8660254*I"); + assert_parsed_expression_evaluates_to("(-1)^(1/3)", "0.5+8.6602540378444E-1*I"); + assert_parsed_expression_evaluates_to("X^(I*P/3)", "0.5+0.8660254*I"); + assert_parsed_expression_evaluates_to("X^(I*P/3)", "0.5+8.6602540378444E-1*I"); + assert_parsed_expression_evaluates_to("I^(2/3)", "0.5+0.8660254*I"); + assert_parsed_expression_evaluates_to("I^(2/3)", "0.5+8.6602540378444E-1*I"); } QUIZ_CASE(poincare_power_simplify) { @@ -64,7 +70,6 @@ QUIZ_CASE(poincare_power_simplify) { assert_parsed_expression_simplify_to("R(x*144*P^2)", "12*R(x)*P"); assert_parsed_expression_simplify_to("R(x*144*P)", "12*R(x)*R(P)"); assert_parsed_expression_simplify_to("(-1)*(2+(-4*R(2)))", "-2+4*R(2)"); - assert_parsed_expression_simplify_to("R(2-4*R(2))", "R(-2+4*R(2))*I"); assert_parsed_expression_simplify_to("x^(1/2)", "R(x)"); assert_parsed_expression_simplify_to("x^(-1/2)", "1/R(x)"); assert_parsed_expression_simplify_to("x^(1/7)", "root(x,7)"); @@ -94,4 +99,7 @@ QUIZ_CASE(poincare_power_simplify) { assert_parsed_expression_simplify_to("(P+R(2)+R(3)+x)^(-3)", "1/(11*R(2)+9*R(3)+15*x+6*R(6)*x+3*R(2)*x^2+3*R(3)*x^2+x^3+15*P+6*R(6)*P+6*R(2)*x*P+6*R(3)*x*P+3*x^2*P+3*R(2)*P^2+3*R(3)*P^2+3*x*P^2+P^3)"); assert_parsed_expression_simplify_to("1.0066666666667^60", "(10066666666667/10000000000000)^60"); assert_parsed_expression_simplify_to("2^(6+P+x)", "64*2^(x+P)"); + assert_parsed_expression_simplify_to("I^(2/3)", "1/2+R(3)/2*I"); + assert_parsed_expression_simplify_to("X^(I*P/3)", "1/2+R(3)/2*I"); + assert_parsed_expression_simplify_to("(-1)^(1/3)", "1/2+R(3)/2*I"); } diff --git a/poincare/test/properties.cpp b/poincare/test/properties.cpp index 33548c961..eedcfe6e6 100644 --- a/poincare/test/properties.cpp +++ b/poincare/test/properties.cpp @@ -15,12 +15,12 @@ void assert_parsed_expression_sign(const char * expression, Poincare::Expression Shared::GlobalContext globalContext; Expression e = parse_expression(expression); quiz_assert(!e.isUninitialized()); - e = e.simplify(globalContext, Degree); + e = e.reduce(globalContext, Degree); quiz_assert(e.sign(&globalContext, Degree) == sign); } QUIZ_CASE(poincare_sign) { - assert_parsed_expression_sign("abs(-cos(2))", Positive); + assert_parsed_expression_sign("abs(-cos(2)+I)", Positive); assert_parsed_expression_sign("2.345E-23", Positive); assert_parsed_expression_sign("-2.345E-23", Negative); assert_parsed_expression_sign("2*(-3)*abs(-32)", Negative); @@ -62,7 +62,7 @@ QUIZ_CASE(poincare_polynomial_degree) { void assert_expression_has_characteristic_range(Expression e, float range, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Degree) { Shared::GlobalContext globalContext; quiz_assert(!e.isUninitialized()); - e = e.simplify(globalContext, angleUnit); + e = e.reduce(globalContext, angleUnit); if (std::isnan(range)) { quiz_assert(std::isnan(e.characteristicXRange(globalContext, angleUnit))); } else { diff --git a/poincare/test/simplify_mix.cpp b/poincare/test/simplify_mix.cpp index 6385daa73..e65586ada 100644 --- a/poincare/test/simplify_mix.cpp +++ b/poincare/test/simplify_mix.cpp @@ -40,13 +40,13 @@ QUIZ_CASE(poincare_simplify_mix) { // Complex assert_parsed_expression_simplify_to("I", "I"); assert_parsed_expression_simplify_to("R(-33)", "R(33)*I"); - assert_parsed_expression_simplify_to("I^(3/5)", "(R(2)*R(5-R(5))+I+R(5)*I)/4"); + assert_parsed_expression_simplify_to("I^(3/5)", "(R(2)*R(5-R(5)))/4+(1+R(5))/4*I"); assert_parsed_expression_simplify_to("IIII", "1"); - assert_parsed_expression_simplify_to("R(-I)", "R(-I)"); + assert_parsed_expression_simplify_to("R(-I)", "R(2)/2-R(2)/2*I"); assert_parsed_expression_simplify_to("A*cos(9)IIln(2)", "-cos(9)*ln(2)*A"); - assert_parsed_expression_simplify_to("(R(2)+R(2)*I)/2(R(2)+R(2)*I)/2(R(2)+R(2)*I)/2", "(R(2)-R(2)*I)/32"); - assert_parsed_expression_simplify_to("root(5^((-I)3^9),I)", "1/(1/5^(19683*I))^I"); - assert_parsed_expression_simplify_to("I^I", "I^I"); + assert_parsed_expression_simplify_to("(R(2)+R(2)*I)/2(R(2)+R(2)*I)/2(R(2)+R(2)*I)/2", "R(2)/32-R(2)/32*I"); + assert_parsed_expression_simplify_to("root(5^((-I)3^9),I)", "1/X^atan(tan(19683*ln(5)))"); + assert_parsed_expression_simplify_to("I^I", "1/X^(P/2)"); //assert_parsed_expression_simplify_to("log(cos(9)^ln(6), cos(9))", "ln(2)+ln(3)"); // TODO: for this to work, we must know the sign of cos(9) //assert_parsed_expression_simplify_to("log(cos(9)^ln(6), 9)", "ln(6)*log(cos(9), 9)"); // TODO: for this to work, we must know the sign of cos(9) From 759aee23455b7082ba2511e07769eb58902a1a5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 19 Dec 2018 10:59:40 +0100 Subject: [PATCH 123/373] [poincare] Discard wrong optimization. NAryExpression children are sorted but Power(ComplexCartesian) is after ComplexCartesian in the simplification order. ComplexCartesian are not ensure to be last ones if some children are not real. --- poincare/src/n_ary_expression_node.cpp | 11 ++++------- poincare/test/simplify_mix.cpp | 2 ++ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/poincare/src/n_ary_expression_node.cpp b/poincare/src/n_ary_expression_node.cpp index d50e1ca61..99f747199 100644 --- a/poincare/src/n_ary_expression_node.cpp +++ b/poincare/src/n_ary_expression_node.cpp @@ -82,20 +82,17 @@ int NAryExpressionNode::simplificationOrderGreaterType(const ExpressionNode * e, int NAryExpression::allChildrenAreReal(Context & context, Preferences::AngleUnit angleUnit) const { int i = 0; - /* The addition children are assumed to be sorted. ComplexCartesian children - * are supposed to be the last ones before matrices. We just test children - * to be real until we reach the first ComplexCartesian. */ + int result = 1; while (i < numberOfChildren()) { Expression c = childAtIndex(i); if (c.type() == ExpressionNode::Type::ComplexCartesian) { - return 0; - } - if (!c.isReal(context, angleUnit)) { + result *= 0; + } else if (!c.isReal(context, angleUnit)) { return -1; } i++; } - return 1; + return result; } } diff --git a/poincare/test/simplify_mix.cpp b/poincare/test/simplify_mix.cpp index e65586ada..03122c151 100644 --- a/poincare/test/simplify_mix.cpp +++ b/poincare/test/simplify_mix.cpp @@ -47,6 +47,8 @@ QUIZ_CASE(poincare_simplify_mix) { assert_parsed_expression_simplify_to("(R(2)+R(2)*I)/2(R(2)+R(2)*I)/2(R(2)+R(2)*I)/2", "R(2)/32-R(2)/32*I"); assert_parsed_expression_simplify_to("root(5^((-I)3^9),I)", "1/X^atan(tan(19683*ln(5)))"); assert_parsed_expression_simplify_to("I^I", "1/X^(P/2)"); + assert_parsed_expression_simplify_to("I/(1+I*R(x))", "I/(1+R(x)*I)"); + assert_parsed_expression_simplify_to("x+I/(1+I*R(x))", "(x+I+x^(3/2)*I)/(1+R(x)*I)"); //assert_parsed_expression_simplify_to("log(cos(9)^ln(6), cos(9))", "ln(2)+ln(3)"); // TODO: for this to work, we must know the sign of cos(9) //assert_parsed_expression_simplify_to("log(cos(9)^ln(6), 9)", "ln(6)*log(cos(9), 9)"); // TODO: for this to work, we must know the sign of cos(9) From f00f639bed0f395686ceb2a02664850feafdd7df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 19 Dec 2018 15:59:31 +0100 Subject: [PATCH 124/373] [poincare] Interrupt simplification of when too many nodes where generated while bubbling up ComplexCartesian. Retry with another ReductionTarget --- poincare/include/poincare/complex_cartesian.h | 2 ++ poincare/include/poincare/expression.h | 2 +- poincare/src/complex_cartesian.cpp | 23 +++++++++++++++---- poincare/src/expression.cpp | 10 +++++--- poincare/src/matrix.cpp | 2 +- poincare/test/complex.cpp | 8 +++++-- 6 files changed, 35 insertions(+), 12 deletions(-) diff --git a/poincare/include/poincare/complex_cartesian.h b/poincare/include/poincare/complex_cartesian.h index 622615ef5..d1ab221b1 100644 --- a/poincare/include/poincare/complex_cartesian.h +++ b/poincare/include/poincare/complex_cartesian.h @@ -59,11 +59,13 @@ public: ComplexCartesian multiply(ComplexCartesian & other, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); ComplexCartesian power(ComplexCartesian & other, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: + static constexpr int k_maxNumberOfNodesBeforeInterrupting = 50; ComplexCartesian(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child0); replaceChildAtIndexInPlace(1, child1); } void factorAndArgumentOfFunction(Expression e, ExpressionNode::Type searchedType, Expression * factor, Expression * argument, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + ComplexCartesian interruptComputationIfManyNodes(); static Multiplication squareRootHelper(Expression e, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); static Expression powerHelper(Expression norm, Expression trigo, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); }; diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 1790062df..ebece6b7b 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -111,7 +111,7 @@ public: typedef bool (*CircuitBreaker)(); static void setCircuitBreaker(CircuitBreaker cb); static bool shouldStopProcessing(); - static void resetInterruption(); + static void setInterruption(bool interrupt); /* Hierarchy */ Expression childAtIndex(int i) const; diff --git a/poincare/src/complex_cartesian.cpp b/poincare/src/complex_cartesian.cpp index 5ba4e4ed9..73bde8b91 100644 --- a/poincare/src/complex_cartesian.cpp +++ b/poincare/src/complex_cartesian.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -175,7 +176,7 @@ ComplexCartesian ComplexCartesian::inverse(Context & context, Preferences::Angle ComplexCartesian result(A,B); A.shallowReduce(context, angleUnit, target); B.shallowReduce(context, angleUnit, target); - return result; + return result.interruptComputationIfManyNodes(); } Multiplication ComplexCartesian::squareRootHelper(Expression e, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { @@ -211,7 +212,7 @@ ComplexCartesian ComplexCartesian::squareRoot(Context & context, Preferences::An ComplexCartesian result = ComplexCartesian::Builder(A, B); A.shallowReduce(context, angleUnit, target); B.shallowReduce(context, angleUnit, target); - return result; + return result.interruptComputationIfManyNodes(); } @@ -244,6 +245,7 @@ ComplexCartesian ComplexCartesian::powerInteger(int n, Context & context, Prefer // Imaginary part: B = b*a^(n-1) Addition A; Addition B; + ComplexCartesian result = ComplexCartesian::Builder(A, B); for (int i = 0; i <= n; i++) { BinomialCoefficient binom = BinomialCoefficient::Builder(Rational(n), Rational(i)); Expression aclone = i == n ? a : a.clone(); @@ -263,8 +265,11 @@ ComplexCartesian ComplexCartesian::powerInteger(int n, Context & context, Prefer B.addChildAtIndexInPlace(m, B.numberOfChildren(), B.numberOfChildren()); } m.shallowReduce(context, angleUnit, target); + result = result.interruptComputationIfManyNodes(); + if (result.real().isUndefined()) { + return result; + } } - ComplexCartesian result = ComplexCartesian::Builder(A, B); A.shallowReduce(context, angleUnit, target); B.shallowReduce(context, angleUnit, target); return result; @@ -291,7 +296,7 @@ ComplexCartesian ComplexCartesian::multiply(ComplexCartesian & other, Context & ComplexCartesian result = ComplexCartesian::Builder(A, B); A.shallowReduce(context, angleUnit, target); B.shallowReduce(context, angleUnit, target); - return result; + return result.interruptComputationIfManyNodes(); } Expression ComplexCartesian::powerHelper(Expression norm, Expression trigo, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { @@ -347,7 +352,15 @@ ComplexCartesian ComplexCartesian::power(ComplexCartesian & other, Context & con ComplexCartesian result = ComplexCartesian::Builder(normcosarg, normsinarg); normcosarg.shallowReduce(context, angleUnit, target); normsinarg.shallowReduce(context, angleUnit, target); - return result; + return result.interruptComputationIfManyNodes(); +} + +ComplexCartesian ComplexCartesian::interruptComputationIfManyNodes() { + if (numberOfDescendants(true) > k_maxNumberOfNodesBeforeInterrupting) { + Expression::setInterruption(true); + return ComplexCartesian(Undefined(), Undefined()); + } + return *this; } } diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index c3397080f..4842d95d3 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -59,8 +59,8 @@ bool Expression::shouldStopProcessing() { return false; } -void Expression::resetInterruption() { - sSimplificationHasBeenInterrupted = false; +void Expression::setInterruption(bool interrupt) { + sSimplificationHasBeenInterrupted = interrupt; } /* Hierarchy */ @@ -399,7 +399,11 @@ void Expression::simplifyAndApproximate(Expression * simplifiedExpression, Expre assert(simplifiedExpression); sSimplificationHasBeenInterrupted = false; // Step 1: we reduce the expression - Expression e = deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); + Expression e = clone().deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); + if (sSimplificationHasBeenInterrupted) { + sSimplificationHasBeenInterrupted = false; + e = deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); + } *simplifiedExpression = Expression(); if (!sSimplificationHasBeenInterrupted) { /* Case 1: the reduced expression is ComplexCartesian or pure real, we can diff --git a/poincare/src/matrix.cpp b/poincare/src/matrix.cpp index 5d24c4a9a..527830845 100644 --- a/poincare/src/matrix.cpp +++ b/poincare/src/matrix.cpp @@ -160,7 +160,7 @@ int Matrix::ArrayInverse(T * array, int numberOfRows, int numberOfColumns) { } Matrix Matrix::rowCanonize(Context & context, Preferences::AngleUnit angleUnit, Multiplication determinant) { - Expression::resetInterruption(); + Expression::setInterruption(false); // The matrix children have to be reduced to be able to spot 0 deepReduceChildren(context, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); diff --git a/poincare/test/complex.cpp b/poincare/test/complex.cpp index b44fb6808..345d568fe 100644 --- a/poincare/test/complex.cpp +++ b/poincare/test/complex.cpp @@ -19,7 +19,9 @@ QUIZ_CASE(poincare_complex_parts) { assert_parsed_expression_simplify_to("(2+3*I)*(4-2*I)", "14+8*I", Radian, Cartesian); assert_parsed_expression_simplify_to("(3+I)/2", "3/2+1/2*I", Radian, Cartesian); assert_parsed_expression_simplify_to("(3+I)/(2+I)", "7/5-1/5*I", Radian, Cartesian); - assert_parsed_expression_simplify_to("(3+I)^(2+I)", "10*cos((-4*atan(3)+ln(2)+ln(5)+2*P)/2)*X^((2*atan(3)-P)/2)+10*sin((-4*atan(3)+ln(2)+ln(5)+2*P)/2)*X^((2*atan(3)-P)/2)*I", Radian, Cartesian); + // The simplification of (3+I)^(2+I) in a Cartesian complex form generates to many nodes + //assert_parsed_expression_simplify_to("(3+I)^(2+I)", "10*cos((-4*atan(3)+ln(2)+ln(5)+2*P)/2)*X^((2*atan(3)-P)/2)+10*sin((-4*atan(3)+ln(2)+ln(5)+2*P)/2)*X^((2*atan(3)-P)/2)*I", Radian, Cartesian); + assert_parsed_expression_simplify_to("(3+I)^(2+I)", "(3+I)^(2+I)", Radian, Cartesian); assert_parsed_expression_simplify_to("R(1+6I)", "R(2+2*R(37))/2+R(-2+2*R(37))/2*I", Radian, Cartesian); assert_parsed_expression_simplify_to("(1+I)^2", "2*I", Radian, Cartesian); assert_parsed_expression_simplify_to("2*I", "2*I", Radian, Cartesian); @@ -103,7 +105,9 @@ QUIZ_CASE(poincare_complex_parts) { assert_parsed_expression_simplify_to("(3+I)/(2+I)", "R(2)*X^((2*atan(7)-P)/2*I)", Radian, Polar); // TODO: simplify atan(tan(x)) = x±k*pi? //assert_parsed_expression_simplify_to("(3+I)^(2+I)", "10*X^((2*atan(3)-P)/2)*X^((-4*atan(3)+ln(2)+ln(5)+2*P)/2*I)", Radian, Polar); - assert_parsed_expression_simplify_to("(3+I)^(2+I)", "10*X^((2*atan(3)-P)/2)*X^((atan(tan((-4*atan(3)+ln(2)+ln(5)+2*P)/2))+P)*I)", Radian, Polar); + // The simplification of (3+I)^(2+I) in a Polar complex form generates to many nodes + //assert_parsed_expression_simplify_to("(3+I)^(2+I)", "10*X^((2*atan(3)-P)/2)*X^((atan(tan((-4*atan(3)+ln(2)+ln(5)+2*P)/2))+P)*I)", Radian, Polar); + assert_parsed_expression_simplify_to("(3+I)^(2+I)", "(3+I)^(2+I)", Radian, Polar); assert_parsed_expression_simplify_to("(1+I)^2", "2*X^(P/2*I)", Radian, Polar); assert_parsed_expression_simplify_to("2*I", "2*X^(P/2*I)", Radian, Polar); assert_parsed_expression_simplify_to("3!", "6", Radian, Polar); From 5e79949ba77ad913e332ea7246d6247b3d443c53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 20 Dec 2018 09:59:05 +0100 Subject: [PATCH 125/373] [poincare] Clean Trigonometry --- poincare/include/poincare/trigonometry.h | 6 +- poincare/src/trigonometry.cpp | 92 ++++++++++++++---------- 2 files changed, 58 insertions(+), 40 deletions(-) diff --git a/poincare/include/poincare/trigonometry.h b/poincare/include/poincare/trigonometry.h index 6af46cd2c..27787022b 100644 --- a/poincare/include/poincare/trigonometry.h +++ b/poincare/include/poincare/trigonometry.h @@ -13,10 +13,12 @@ public: Sine = 1, }; static float characteristicXRange(const Expression & e, Context & context, Preferences::AngleUnit angleUnit); - static bool parentIsDirectTrigonometry(const Expression & e); + static bool isDirectTrigonometryFunction(const Expression & e); + static bool isInverseTrigonometryFunction(const Expression & e); + static bool AreInverseFunctions(const Expression & directFunction, const Expression & inverseFunction); + static bool ExpressionIsEquivalentToTangent(const Expression & e); static Expression shallowReduceDirectFunction(Expression & e, Context& context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); static Expression shallowReduceInverseFunction(Expression & e, Context& context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - static bool ExpressionIsEquivalentToTangent(const Expression & e); constexpr static int k_numberOfEntries = 37; static Expression table(const Expression e, ExpressionNode::Type type, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); // , Function f, bool inverse template static std::complex ConvertToRadian(const std::complex c, Preferences::AngleUnit angleUnit); diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 23717ac1d..8541ad375 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -41,10 +41,50 @@ float Trigonometry::characteristicXRange(const Expression & e, Context & context return 2.0f*pi/std::fabs(a); } +bool Trigonometry::isDirectTrigonometryFunction(const Expression & e) { + return e.type() == ExpressionNode::Type::Cosine || e.type() == ExpressionNode::Type::Sine || e.type() == ExpressionNode::Type::Tangent; +} + +bool Trigonometry::isInverseTrigonometryFunction(const Expression & e) { + return e.type() == ExpressionNode::Type::ArcCosine || e.type() == ExpressionNode::Type::ArcSine || e.type() == ExpressionNode::Type::ArcTangent; +} + +bool Trigonometry::AreInverseFunctions(const Expression & directFunction, const Expression & inverseFunction) { + if (!isDirectTrigonometryFunction(directFunction)) { + return false; + } + ExpressionNode::Type correspondingType; + switch (directFunction.type()) { + case ExpressionNode::Type::Cosine: + correspondingType = ExpressionNode::Type::ArcCosine; + break; + case ExpressionNode::Type::Sine: + correspondingType = ExpressionNode::Type::ArcSine; + break; + default: + assert(directFunction.type() == ExpressionNode::Type::Tangent); + correspondingType = ExpressionNode::Type::ArcTangent; + break; + } + return inverseFunction.type() == correspondingType; +} + +bool Trigonometry::ExpressionIsEquivalentToTangent(const Expression & e) { + // We look for (cos^-1 * sin) + assert(ExpressionNode::Type::Power < ExpressionNode::Type::Sine); + if (e.type() == ExpressionNode::Type::Multiplication + && e.childAtIndex(1).type() == ExpressionNode::Type::Sine + && e.childAtIndex(0).type() == ExpressionNode::Type::Power + && e.childAtIndex(0).childAtIndex(0).type() == ExpressionNode::Type::Cosine + && e.childAtIndex(0).childAtIndex(1).type() == ExpressionNode::Type::Rational + && e.childAtIndex(0).childAtIndex(1).convert().isMinusOne()) { + return true; + } + return false; +} + Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { - assert(e.type() == ExpressionNode::Type::Sine - || e.type() == ExpressionNode::Type::Cosine - || e.type() == ExpressionNode::Type::Tangent); + assert(isDirectTrigonometryFunction(e)); // Step 1. Try finding an easy standard calculation reduction Expression lookup = Trigonometry::table(e.childAtIndex(0), e.type(), context, angleUnit, target); @@ -54,15 +94,14 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& co } // Step 2. Look for an expression of type "cos(arccos(x))", return x - ExpressionNode::Type correspondingType = e.type() == ExpressionNode::Type::Cosine ? ExpressionNode::Type::ArcCosine : - (e.type() == ExpressionNode::Type::Sine ? ExpressionNode::Type::ArcSine : ExpressionNode::Type::ArcTangent); - if (e.childAtIndex(0).type() == correspondingType) { + if (AreInverseFunctions(e, e.childAtIndex(0))) { Expression result = e.childAtIndex(0).childAtIndex(0); e.replaceWithInPlace(result); return result; } // Step 3. Look for an expression of type "cos(arcsin(x))" or "sin(arccos(x)), return sqrt(1-x^2) + // These equalities are true on complexes if ((e.type() == ExpressionNode::Type::Cosine && e.childAtIndex(0).type() == ExpressionNode::Type::ArcSine) || (e.type() == ExpressionNode::Type::Sine && e.childAtIndex(0).type() == ExpressionNode::Type::ArcCosine)) { Expression sqrt = Power( @@ -70,7 +109,8 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& co Rational(1), Multiplication( Rational(-1), - Power(e.childAtIndex(0).childAtIndex(0), Rational(2)) ) + Power(e.childAtIndex(0).childAtIndex(0), Rational(2)) + ) ), Rational(1,2) ); @@ -88,6 +128,7 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& co // Step 4. Look for an expression of type "cos(arctan(x))" or "sin(arctan(x))" // cos(arctan(x)) --> 1/sqrt(1+x^2) // sin(arctan(x)) --> x/sqrt(1+x^2) + // These equalities are true on complexes if ((e.type() == ExpressionNode::Type::Cosine || e.type() == ExpressionNode::Type::Sine) && e.childAtIndex(0).type() == ExpressionNode::Type::ArcTangent) { Expression x = e.childAtIndex(0).childAtIndex(0); // Build 1/sqrt(1+x^2) @@ -116,7 +157,7 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& co return res.shallowReduce(context, angleUnit, target); } - // Step 3. Look for an expression of type "cos(-a)", return "+/-cos(a)" + // Step 5. Look for an expression of type "cos(-a)", return "+/-cos(a)" Expression positiveArg = e.childAtIndex(0).makePositiveAnyNegativeNumeralFactor(context, angleUnit, target); if (!positiveArg.isUninitialized()) { // The argument was of form cos(-a) @@ -133,7 +174,7 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& co } } - /* Step 4. Look for an expression of type "cos(p/q * Pi)" in radians or + /* Step 6. Look for an expression of type "cos(p/q * Pi)" in radians or * "cos(p/q)" in degrees, put the argument in [0, Pi/2[ or [0, 90[ and * multiply the cos/sin/tan by -1 if needed. * We know thanks to Step 3 that p/q > 0. */ @@ -201,38 +242,12 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& co return e; } -bool Trigonometry::ExpressionIsEquivalentToTangent(const Expression & e) { - // We look for (cos^-1 * sin) - assert(ExpressionNode::Type::Power < ExpressionNode::Type::Sine); - if (e.type() == ExpressionNode::Type::Multiplication - && e.childAtIndex(1).type() == ExpressionNode::Type::Sine - && e.childAtIndex(0).type() == ExpressionNode::Type::Power - && e.childAtIndex(0).childAtIndex(0).type() == ExpressionNode::Type::Cosine - && e.childAtIndex(0).childAtIndex(1).type() == ExpressionNode::Type::Rational - && e.childAtIndex(0).childAtIndex(1).convert().isMinusOne()) { - return true; - } - return false; -} - -bool Trigonometry::parentIsDirectTrigonometry(const Expression & e) { - Expression parent = e.parent(); - if (parent.isUninitialized()) { - return false; - } - if (parent.type() == ExpressionNode::Type::Cosine || parent.type() == ExpressionNode::Type::Sine || parent.type() == ExpressionNode::Type::Tangent) { - return true; - } - return false; -} - Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { - assert(e.type() == ExpressionNode::Type::ArcCosine || e.type() == ExpressionNode::Type::ArcSine || e.type() == ExpressionNode::Type::ArcTangent); - ExpressionNode::Type correspondingType = e.type() == ExpressionNode::Type::ArcCosine ? ExpressionNode::Type::Cosine : (e.type() == ExpressionNode::Type::ArcSine ? ExpressionNode::Type::Sine : ExpressionNode::Type::Tangent); + assert(isInverseTrigonometryFunction(e)); float pi = angleUnit == Preferences::AngleUnit::Radian ? M_PI : 180; // Step 1. Look for an expression of type "arccos(cos(x))", return x - if (e.childAtIndex(0).type() == correspondingType) { + if (AreInverseFunctions(e.childAtIndex(0), e)) { float trigoOp = e.childAtIndex(0).childAtIndex(0).approximateToScalar(context, angleUnit); if ((e.type() == ExpressionNode::Type::ArcCosine && trigoOp >= 0.0f && trigoOp <= pi) || (e.type() == ExpressionNode::Type::ArcSine && trigoOp >= -pi/2.0f && trigoOp <= pi/2.0f) || @@ -281,7 +296,8 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& c * - the reduction is being BottomUp. In this case, we do not yet have any * information on the parent which could later be a cosine, a sine or a tangent. */ - bool letArcFunctionAtRoot = target == ExpressionNode::ReductionTarget::BottomUpComputation || parentIsDirectTrigonometry(e); + Expression p = e.parent(); + bool letArcFunctionAtRoot = target == ExpressionNode::ReductionTarget::BottomUpComputation || (!p.isUninitialized() && isDirectTrigonometryFunction(p)); /* Step 5. Handle opposite argument: arccos(-x) = Pi-arcos(x), * arcsin(-x) = -arcsin(x), arctan(-x)= -arctan(x) * */ From c0424089f765ed981398104dbf156c26d369b4d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 20 Dec 2018 10:43:15 +0100 Subject: [PATCH 126/373] [poincare] Clean Power --- poincare/include/poincare/expression.h | 5 ++++- poincare/src/power.cpp | 28 ++++++++++++++------------ poincare/src/sign_function.cpp | 7 ++++--- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index ebece6b7b..a31e4a5c7 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -271,7 +271,10 @@ protected: /* makePositiveAnyNegativeNumeralFactor looks for: * - a negative numeral * - a multiplication who has one numeral child whose is negative - * and turns the negative factor into a positive one + * and turns the negative factor into a positive one. + * The given Expression should already be reduced and the return Expression + * is reduced (only a numeral factor was potentially made positive, and if it + * was -1, it was removed from the multiplication). */ Expression makePositiveAnyNegativeNumeralFactor(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); Expression denominator(Context & context, Preferences::AngleUnit angleUnit) const { return node()->denominator(context, angleUnit); } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 4ff88ce55..726d030a0 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -402,7 +402,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU */ bool letPowerAtRoot = target == ExpressionNode::ReductionTarget::BottomUpComputation || parentIsALogarithmOfSameBase(); - /* Step 1: we now bubble up ComplexCartesian, we handle different cases: + /* Step 2: we now bubble up ComplexCartesian, we handle different cases: * At least, one child is a ComplexCartesian and the other is either a * ComplexCartesian or real. */ @@ -453,7 +453,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU return result.shallowReduce(context, angleUnit); } - /* Step 2: We look for square root and sum of square roots (two terms maximum + /* Step 3: We look for square root and sum of square roots (two terms maximum * so far) at the denominator and move them to the numerator. */ if (target == ExpressionNode::ReductionTarget::User) { Expression r = removeSquareRootsFromDenominator(context, angleUnit); @@ -462,6 +462,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU } } + /* Step 4: we simplify i^(p/q) = e^(i*Pi*p/2q) */ if (childAtIndex(1).type() == ExpressionNode::Type::Rational) { const Rational b = childAtIndex(1).convert(); // i^(p/q) @@ -473,7 +474,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU } } - // (±inf)^x + // Step 5: (±inf)^x = 0 or ±inf if (childAtIndex(0).type() == ExpressionNode::Type::Infinity) { Expression result; if (childAtIndex(1).sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { @@ -495,6 +496,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU } } + // Step 6: p^q with p, q rationals --> a*b^c*exp(i*pi*d) with a, b, c, d rationals if (!letPowerAtRoot && childAtIndex(0).type() == ExpressionNode::Type::Rational) { Rational a = childAtIndex(0).convert(); // p^q with p, q rationals @@ -507,7 +509,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU return simplifyRationalRationalPower(context, angleUnit, target); } } - // (a)^(1/2) with a < 0 --> i*(-a)^(1/2) + // Step 7: (a)^(1/2) with a < 0 --> i*(-a)^(1/2) // WARNING: this rule true only if a real (ex: (-1*i)^(1/2) != i*i^(1/2) if (!letPowerAtRoot && childAtIndex(0).isReal(context, angleUnit) @@ -517,7 +519,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU Expression m0 = childAtIndex(0).makePositiveAnyNegativeNumeralFactor(context, angleUnit, target); if (!m0.isUninitialized()) { replaceChildAtIndexInPlace(0, m0); - //m0.shallowReduce(context, angleUnit, target); + // m0 doest not need to be shallowReduce as makePositiveAnyNegativeNumeralFactor returns a reduced expression Multiplication m1 = Multiplication(); replaceWithInPlace(m1); // Multiply m1 by i complex @@ -529,7 +531,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU return m1.shallowReduce(context, angleUnit, target); } } - // e^(i*Pi*r) with r rational + // Step 8: e^(i*Pi*r) with r rational --> cos(pi*r) + i*sin(pi*r) if (!letPowerAtRoot && isNthRootOfUnity()) { Expression m = childAtIndex(1); Expression i = m.childAtIndex(m.numberOfChildren()-1); @@ -548,7 +550,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU replaceWithInPlace(a); return a.shallowReduce(context, angleUnit, target); } - // x^log(y,x)->y if y > 0 + // Step 9: x^log(y,x)->y if y > 0 if (childAtIndex(1).type() == ExpressionNode::Type::Logarithm) { if (childAtIndex(1).numberOfChildren() == 2 && childAtIndex(0).isIdenticalTo(childAtIndex(1).childAtIndex(1))) { // y > 0 @@ -568,7 +570,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU return result; } } - // (a^b)^c -> a^(b*c) if a > 0 or c is integer + // Step 10: (a^b)^c -> a^(b*c) if a > 0 or c is integer if (childAtIndex(0).type() == ExpressionNode::Type::Power) { Power p = childAtIndex(0).convert(); // Check if a > 0 or c is Integer @@ -579,14 +581,14 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU return simplifyPowerPower(context, angleUnit, target); } } - // (a*b*c*...)^r ? + // Step 11: (a*b*c*...)^r ? if (!letPowerAtRoot && childAtIndex(0).type() == ExpressionNode::Type::Multiplication) { Multiplication m = childAtIndex(0).convert(); - // (a*b*c*...)^n = a^n*b^n*c^n*... if n integer + // Case 1: (a*b*c*...)^n = a^n*b^n*c^n*... if n integer if (childAtIndex(1).type() == ExpressionNode::Type::Rational && childAtIndex(1).convert().integerDenominator().isOne()) { return simplifyPowerMultiplication(context, angleUnit, target); } - // (a*b*...)^r -> |a|^r*(sign(a)*b*...)^r if a not -1 + // Case 2: (a*b*...)^r -> |a|^r*(sign(a)*b*...)^r if a not -1 for (int i = 0; i < m.numberOfChildren(); i++) { // a is signed and a != -1 if (m.childAtIndex(i).sign(&context, angleUnit) != ExpressionNode::Sign::Unknown @@ -620,7 +622,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU } } } - // a^(b+c+...) -> Rational(a^b)*a^c with a and b rational and a != 0 + // Step 12: a^(b+c+...) -> Rational(a^b)*a^c with a and b rational and a != 0 if (!letPowerAtRoot && childAtIndex(0).type() == ExpressionNode::Type::Rational && !childAtIndex(0).convert().isZero() @@ -647,7 +649,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU } } - // (a0+a1+...am)^n with n integer -> a^n+?a^(n-1)*b+?a^(n-2)*b^2+...+b^n (Multinome) + // Step 13: (a0+a1+...am)^n with n integer -> a^n+?a^(n-1)*b+?a^(n-2)*b^2+...+b^n (Multinome) if (!letPowerAtRoot && childAtIndex(1).type() == ExpressionNode::Type::Rational && childAtIndex(1).convert().integerDenominator().isOne() diff --git a/poincare/src/sign_function.cpp b/poincare/src/sign_function.cpp index 6bfeccfa6..99a691044 100644 --- a/poincare/src/sign_function.cpp +++ b/poincare/src/sign_function.cpp @@ -72,7 +72,7 @@ Expression SignFunction::shallowReduce(Context & context, Preferences::AngleUnit Complex c = static_cast&>(childApproximated); // c has no sign (c is complex or NAN) if (std::isnan(c.imag()) || std::isnan(c.real()) || c.imag() != 0) { - // sign(-x) = sign(x) + // sign(-x) = -sign(x) Expression oppChild = child.makePositiveAnyNegativeNumeralFactor(context, angleUnit, target); if (oppChild.isUninitialized()) { return *this; @@ -81,8 +81,9 @@ Expression SignFunction::shallowReduce(Context & context, Preferences::AngleUnit Multiplication m(Rational(-1)); replaceWithInPlace(m); m.addChildAtIndexInPlace(sign, 1, 1); - sign.shallowReduce(context, angleUnit, target); - return m.shallowReduce(context, angleUnit, target); + // sign does not need to be shallowReduce because -x = NAN --> x = NAN + return m; + // m does not need to be shallowReduce, -1*sign cannot be reduce } } if (c.real() < 0) { From 9f42d5c7ec4a3b15f212c23f31ec36d930caa9bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 20 Dec 2018 11:03:17 +0100 Subject: [PATCH 127/373] [poincare] Trigonometry: arctan(1/x) = sign(x)Pi/2-arctan(x) only when x != 0 --- poincare/src/trigonometry.cpp | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 8541ad375..06c14476f 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -268,19 +268,25 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& c } } - // Step 3. Look for an expression of type "arctan(1/X), return sign(x)*Pi/2-arctan(x) + // Step 3. Look for an expression of type "arctan(1/x), return sign(x)*Pi/2-arctan(x) if (e.type() == ExpressionNode::Type::ArcTangent && e.childAtIndex(0).type() == ExpressionNode::Type::Power && e.childAtIndex(0).childAtIndex(1).type() == ExpressionNode::Type::Rational && e.childAtIndex(0).childAtIndex(1).convert().isMinusOne()) { Expression x = e.childAtIndex(0).childAtIndex(0); - Expression sign = SignFunction::Builder(x.clone()); - Multiplication m0(Rational(1,2), sign, Constant(Ion::Charset::SmallPi)); - sign.shallowReduce(context, angleUnit, target); - e.replaceChildAtIndexInPlace(0, x); - Addition a(m0); - e.replaceWithInPlace(a); - Multiplication m1(Rational(-1), e); - e.shallowReduce(context, angleUnit, target); - a.addChildAtIndexInPlace(m1, 1, 1); - return a.shallowReduce(context, angleUnit, target); + /* This equality is not true if x = 0. We apply it under certain conditions: + * - the reduction target is the user + * - x is numeral (which means that x != 0 otherwise 0^(-1) would have been + * reduced to undef) */ + if (target == ExpressionNode::ReductionTarget::User || x.isNumber()) { + Expression sign = SignFunction::Builder(x.clone()); + Multiplication m0(Rational(1,2), sign, Constant(Ion::Charset::SmallPi)); + sign.shallowReduce(context, angleUnit, target); + e.replaceChildAtIndexInPlace(0, x); + Addition a(m0); + e.replaceWithInPlace(a); + Multiplication m1(Rational(-1), e); + e.shallowReduce(context, angleUnit, target); + a.addChildAtIndexInPlace(m1, 1, 1); + return a.shallowReduce(context, angleUnit, target); + } } // Step 4. Try finding an easy standard calculation reduction From 5c98ff15cd5a8c79b59940b3b71d8f1da2c4f46c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 20 Dec 2018 11:30:22 +0100 Subject: [PATCH 128/373] [poincare] Clean AbsoluteValue and ComplexArgument --- poincare/src/absolute_value.cpp | 4 ++-- poincare/src/complex_argument.cpp | 24 ++++++++++-------------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 70c738f49..6322cd326 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -50,11 +50,11 @@ Expression AbsoluteValue::shallowReduce(Context & context, Preferences::AngleUni Expression c = childAtIndex(0); if (c.isReal(context, angleUnit)) { float app = c.approximateToScalar(context, angleUnit); - if (!std::isnan(app) && app >= 0) { + if (!std::isnan(app) && app >= Expression::epsilon()) { // abs(a) = a with a > 0 replaceWithInPlace(c); return c; - } else if (!std::isnan(app) && app < 0) { + } else if (!std::isnan(app) && app <= -Expression::epsilon()) { // abs(a) = -a with a < 0 Multiplication m(Rational(-1), c); replaceWithInPlace(m); diff --git a/poincare/src/complex_argument.cpp b/poincare/src/complex_argument.cpp index dbd1acb60..1d7176658 100644 --- a/poincare/src/complex_argument.cpp +++ b/poincare/src/complex_argument.cpp @@ -46,27 +46,23 @@ Expression ComplexArgument::shallowReduce(Context & context, Preferences::AngleU return SimplificationHelper::Map(*this, context, angleUnit); } #endif - if (c.isReal(context, angleUnit)) { + bool real = c.isReal(context, angleUnit); + if (real) { float app = c.approximateToScalar(context, angleUnit); - if (std::isnan(app)) { - ComplexCartesian complexChild = ComplexCartesian::Builder(c, Rational(0)); - Expression arg = complexChild.argument(context, angleUnit, target); - replaceWithInPlace(arg); - return arg.shallowReduce(context, angleUnit, target); - } else if (app >= 0) { + if (!std::isnan(app) && app >= Expression::epsilon()) { // arg(x) = 0 if x > 0 Expression result = Rational(0); replaceWithInPlace(result); return result; + } else if (!std::isnan(app) && app <= -Expression::epsilon()) { + // arg(x) = Pi if x < 0 + Expression result = Constant(Ion::Charset::SmallPi); + replaceWithInPlace(result); + return result; } - // arg(x) = Pi if x < 0 - assert(app < 0); - Expression result = Constant(Ion::Charset::SmallPi); - replaceWithInPlace(result); - return result; } - if (c.type() == ExpressionNode::Type::ComplexCartesian) { - ComplexCartesian complexChild = static_cast(c); + if (real || c.type() == ExpressionNode::Type::ComplexCartesian) { + ComplexCartesian complexChild = real ? ComplexCartesian::Builder(c, Rational(0)) : static_cast(c); Expression childArg = complexChild.argument(context, angleUnit, target); replaceWithInPlace(childArg); return childArg.shallowReduce(context, angleUnit, target); From 6d32c1866e279a259cac913a94c7a9178c49895b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 20 Dec 2018 11:31:07 +0100 Subject: [PATCH 129/373] [poincare] Division: force division by 0 to be equal to NAN Before x/0 = (Inf, NAN) which leads to arctan(1/0) = Pi/2. --- poincare/src/division.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index 54dc36e32..34fbd6c79 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -47,6 +47,9 @@ Expression DivisionNode::shallowReduce(Context & context, Preferences::AngleUnit } template Complex DivisionNode::compute(const std::complex c, const std::complex d) { + if (d.real() == 0.0 && d.imag() == 0.0) { + return Complex::Undefined(); + } return Complex(c/d); } From 8bc1a7be0555299c150207c069f4e66466f63965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 20 Dec 2018 16:15:06 +0100 Subject: [PATCH 130/373] [poincare] Preferences: add a ComplexFormat::Real --- poincare/include/poincare/preferences.h | 5 +++-- poincare/src/complex.cpp | 8 ++++---- poincare/src/expression.cpp | 5 +++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/poincare/include/poincare/preferences.h b/poincare/include/poincare/preferences.h index 2df15f82a..1b4e84170 100644 --- a/poincare/include/poincare/preferences.h +++ b/poincare/include/poincare/preferences.h @@ -19,8 +19,9 @@ public: Scientific = 1, }; enum class ComplexFormat { - Cartesian = 0, - Polar = 1 + Real = 0, + Cartesian = 1, + Polar = 2 }; enum class AngleUnit { Degree = 0, diff --git a/poincare/src/complex.cpp b/poincare/src/complex.cpp index cb738432b..4237baf1b 100644 --- a/poincare/src/complex.cpp +++ b/poincare/src/complex.cpp @@ -43,12 +43,12 @@ T ComplexNode::toScalar() const { template Expression ComplexNode::complexToExpression(Preferences::ComplexFormat complexFormat) const { T ra, tb; - if (complexFormat == Preferences::ComplexFormat::Cartesian) { - ra = this->real(); - tb = this->imag(); - } else { + if (complexFormat == Preferences::ComplexFormat::Polar) { ra = std::abs(*this); tb = std::arg(*this); + } else { + ra = this->real(); + tb = this->imag(); } return Expression::CreateComplexExpression( Number::DecimalNumber(std::fabs(ra)), diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 4842d95d3..c2621023d 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -426,8 +426,8 @@ void Expression::simplifyAndApproximate(Expression * simplifiedExpression, Expre *approximateExpression = ecomplexClone.approximate(context, angleUnit, complexFormat); } // Step 3: create the simplied expression with the required complex format - Expression ra = complexFormat == Preferences::ComplexFormat::Cartesian ? ecomplex.real() : ecomplex.clone().convert().norm(context, angleUnit, ExpressionNode::ReductionTarget::User).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); - Expression tb = complexFormat == Preferences::ComplexFormat::Cartesian ? ecomplex.imag() : ecomplex.argument(context, angleUnit, ExpressionNode::ReductionTarget::User).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); + Expression ra = complexFormat == Preferences::ComplexFormat::Polar ? ecomplex.clone().convert().norm(context, angleUnit, ExpressionNode::ReductionTarget::User).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User) : ecomplex.real(); + Expression tb = complexFormat == Preferences::ComplexFormat::Polar ? ecomplex.argument(context, angleUnit, ExpressionNode::ReductionTarget::User).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User) : ecomplex.imag(); ra = ra.deepBeautify(context, angleUnit); tb = tb.deepBeautify(context, angleUnit); bool raIsNegative = false; @@ -573,6 +573,7 @@ Expression Expression::CreateComplexExpression(Expression ra, Expression tb, Pre return Undefined(); } switch (complexFormat) { + case Preferences::ComplexFormat::Real: case Preferences::ComplexFormat::Cartesian: { Expression real; From b83ee26636137add718246e3147a4870b5517e84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 20 Dec 2018 16:15:46 +0100 Subject: [PATCH 131/373] [settings] Add a message I18n: Real --- apps/settings/base.de.i18n | 1 + apps/settings/base.en.i18n | 1 + apps/settings/base.es.i18n | 1 + apps/settings/base.fr.i18n | 1 + apps/settings/base.pt.i18n | 1 + 5 files changed, 5 insertions(+) diff --git a/apps/settings/base.de.i18n b/apps/settings/base.de.i18n index 9ddd2b4f5..9be89f426 100644 --- a/apps/settings/base.de.i18n +++ b/apps/settings/base.de.i18n @@ -15,6 +15,7 @@ Radian = "Bogenmass " Decimal = "Dezimal " Scientific = "Wissenschaftlich " SignificantFigures = "Signifikante Stellen " +Real = "Reel " Cartesian = "Algebraische " Polar = "Polar " Brightness = "Helligkeit" diff --git a/apps/settings/base.en.i18n b/apps/settings/base.en.i18n index f79175be7..3b706c0e7 100644 --- a/apps/settings/base.en.i18n +++ b/apps/settings/base.en.i18n @@ -15,6 +15,7 @@ Radian = "Radians " Decimal = "Decimal " Scientific = "Scientific " SignificantFigures = "Significant figures " +Real = "Real " Cartesian = "Cartesian " Polar = "Polar " Brightness = "Brightness" diff --git a/apps/settings/base.es.i18n b/apps/settings/base.es.i18n index 94555dce2..68d1ca4b5 100644 --- a/apps/settings/base.es.i18n +++ b/apps/settings/base.es.i18n @@ -15,6 +15,7 @@ Radian = "Radianes " Decimal = "Decimal " Scientific = "Cientifico " SignificantFigures = "Cifras significativas " +Real = "Real " Cartesian = "Binómica " Polar = "Polar " Brightness = "Brillo" diff --git a/apps/settings/base.fr.i18n b/apps/settings/base.fr.i18n index d79d419ca..c2d22b74a 100644 --- a/apps/settings/base.fr.i18n +++ b/apps/settings/base.fr.i18n @@ -15,6 +15,7 @@ Radian = "Radians " Decimal = "Decimal " Scientific = "Scientifique " SignificantFigures = "Chiffres significatifs " +Real = "Réel " Cartesian = "Algébrique " Polar = "Exponentielle " Brightness = "Luminosite" diff --git a/apps/settings/base.pt.i18n b/apps/settings/base.pt.i18n index b4f6c45aa..86f277900 100644 --- a/apps/settings/base.pt.i18n +++ b/apps/settings/base.pt.i18n @@ -15,6 +15,7 @@ Radian = "Radianos " Decimal = "Decimal " Scientific = "Cientifico " SignificantFigures = "Algarismo significativo " +Real = "Real " Cartesian = "Cartesiana " Polar = "Polar " Brightness = "Brilho" From ab13d137fdde60a6e94e3b4138fe9b4878806dd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 20 Dec 2018 16:16:53 +0100 Subject: [PATCH 132/373] [settings] Update PreferencesController with new ComplexFormat::Real --- apps/settings/main_controller.cpp | 4 ++-- apps/settings/sub_menu/preferences_controller.cpp | 4 ++++ apps/settings/sub_menu/preferences_controller.h | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/apps/settings/main_controller.cpp b/apps/settings/main_controller.cpp index 0476e917a..97e03a7d3 100644 --- a/apps/settings/main_controller.cpp +++ b/apps/settings/main_controller.cpp @@ -10,7 +10,7 @@ namespace Settings { const SettingsMessageTree angleChildren[2] = {SettingsMessageTree(I18n::Message::Degres), SettingsMessageTree(I18n::Message::Radian)}; const SettingsMessageTree editionModeChildren[2] = {SettingsMessageTree(I18n::Message::Edition2D), SettingsMessageTree(I18n::Message::EditionLinear)}; const SettingsMessageTree floatDisplayModeChildren[3] = {SettingsMessageTree(I18n::Message::Decimal), SettingsMessageTree(I18n::Message::Scientific), SettingsMessageTree(I18n::Message::SignificantFigures)}; -const SettingsMessageTree complexFormatChildren[2] = {SettingsMessageTree(I18n::Message::Cartesian), SettingsMessageTree(I18n::Message::Polar)}; +const SettingsMessageTree complexFormatChildren[3] = {SettingsMessageTree(I18n::Message::Real), SettingsMessageTree(I18n::Message::Cartesian), SettingsMessageTree(I18n::Message::Polar)}; const SettingsMessageTree examChildren[1] = {SettingsMessageTree(I18n::Message::ActivateExamMode)}; const SettingsMessageTree aboutChildren[3] = {SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId)}; @@ -22,7 +22,7 @@ const SettingsMessageTree menu[8] = {SettingsMessageTree(I18n::Message::AngleUnit, angleChildren, 2), SettingsMessageTree(I18n::Message::DisplayMode, floatDisplayModeChildren, 3), SettingsMessageTree(I18n::Message::EditionMode, editionModeChildren, 2), - SettingsMessageTree(I18n::Message::ComplexFormat, complexFormatChildren, 2), + SettingsMessageTree(I18n::Message::ComplexFormat, complexFormatChildren, 3), SettingsMessageTree(I18n::Message::Brightness), SettingsMessageTree(I18n::Message::Language), SettingsMessageTree(I18n::Message::ExamMode, examChildren, 1), diff --git a/apps/settings/sub_menu/preferences_controller.cpp b/apps/settings/sub_menu/preferences_controller.cpp index eadb33627..9660b567a 100644 --- a/apps/settings/sub_menu/preferences_controller.cpp +++ b/apps/settings/sub_menu/preferences_controller.cpp @@ -82,6 +82,10 @@ Layout layoutForPreferences(I18n::Message message) { case I18n::Message::EditionLinear: return LayoutHelper::String("1+2/3", 5, KDFont::SmallFont); // Complex format + case I18n::Message::Real: + { + return CharLayout('x', KDFont::SmallFont); + } case I18n::Message::Cartesian: { const char text[] = {'a','+', Ion::Charset::IComplex, 'b'}; diff --git a/apps/settings/sub_menu/preferences_controller.h b/apps/settings/sub_menu/preferences_controller.h index 2ed186d58..5648feccb 100644 --- a/apps/settings/sub_menu/preferences_controller.h +++ b/apps/settings/sub_menu/preferences_controller.h @@ -15,7 +15,7 @@ public: void willDisplayCellForIndex(HighlightCell * cell, int index) override; KDCoordinate rowHeight(int j) override; protected: - constexpr static int k_totalNumberOfCell = 2; + constexpr static int k_totalNumberOfCell = 3; private: void setPreferenceWithValueIndex(I18n::Message message, int valueIndex); int valueIndexForPreference(I18n::Message message); From b6ec84f6a95ec74abff63220ff8eb64aa52ba2fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 20 Dec 2018 17:02:23 +0100 Subject: [PATCH 133/373] [calculation] Clean and add tests on CalculationStore --- apps/calculation/test/calculation_store.cpp | 94 +++++++++++---------- 1 file changed, 48 insertions(+), 46 deletions(-) diff --git a/apps/calculation/test/calculation_store.cpp b/apps/calculation/test/calculation_store.cpp index c621fcac4..6e43fd542 100644 --- a/apps/calculation/test/calculation_store.cpp +++ b/apps/calculation/test/calculation_store.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include "../calculation_store.h" @@ -13,7 +14,7 @@ void assert_store_is(CalculationStore * store, const char * result[10]) { } } -QUIZ_CASE(calculation_store) { +QUIZ_CASE(calculation_store_ring_buffer) { Shared::GlobalContext globalContext; CalculationStore store; quiz_assert(CalculationStore::k_maxNumberOfCalculations == 10); @@ -50,7 +51,7 @@ QUIZ_CASE(calculation_store) { store.deleteAll(); } -QUIZ_CASE(calculation_display_exact_approximate) { +QUIZ_CASE(calculation_ans) { Shared::GlobalContext globalContext; CalculationStore store; @@ -65,49 +66,50 @@ QUIZ_CASE(calculation_display_exact_approximate) { quiz_assert(lastCalculation->shouldOnlyDisplayApproximateOutput(&globalContext) == true); quiz_assert(strcmp(lastCalculation->approximateOutputText(),"2.6366666666667") == 0); - store.deleteAll(); - store.push("1/2", &globalContext); - lastCalculation = store.calculationAtIndex(1); - quiz_assert(lastCalculation->exactAndApproximateDisplayedOutputsAreEqual(&globalContext) == ::Calculation::Calculation::EqualSign::Equal); - quiz_assert(lastCalculation->shouldOnlyDisplayExactOutput() == false); - quiz_assert(lastCalculation->shouldOnlyDisplayApproximateOutput(&globalContext) == false); - - store.deleteAll(); - store.push("1/3", &globalContext); - lastCalculation = store.calculationAtIndex(1); - quiz_assert(lastCalculation->exactAndApproximateDisplayedOutputsAreEqual(&globalContext) == ::Calculation::Calculation::EqualSign::Approximation); - quiz_assert(lastCalculation->shouldOnlyDisplayExactOutput() == false); - quiz_assert(lastCalculation->shouldOnlyDisplayApproximateOutput(&globalContext) == false); - - store.deleteAll(); - store.push("1/0", &globalContext); - lastCalculation = store.calculationAtIndex(1); - quiz_assert(lastCalculation->shouldOnlyDisplayExactOutput() == true); - quiz_assert(strcmp(lastCalculation->approximateOutputText(),"undef") == 0); - - store.deleteAll(); - store.push("2x-x", &globalContext); - lastCalculation = store.calculationAtIndex(1); - quiz_assert(lastCalculation->shouldOnlyDisplayExactOutput() == true); - quiz_assert(strcmp(lastCalculation->exactOutputText(),"x") == 0); - - store.deleteAll(); - store.push("[[1,2,3]]", &globalContext); - lastCalculation = store.calculationAtIndex(1); - quiz_assert(lastCalculation->shouldOnlyDisplayExactOutput() == false); - quiz_assert(lastCalculation->shouldOnlyDisplayApproximateOutput(&globalContext) == true); - - store.deleteAll(); - store.push("[[1,x,3]]", &globalContext); - lastCalculation = store.calculationAtIndex(1); - quiz_assert(lastCalculation->shouldOnlyDisplayExactOutput() == false); - quiz_assert(lastCalculation->shouldOnlyDisplayApproximateOutput(&globalContext) == true); - - store.deleteAll(); - store.push("28^7", &globalContext); - lastCalculation = store.calculationAtIndex(1); - quiz_assert(lastCalculation->shouldOnlyDisplayExactOutput() == false); - quiz_assert(lastCalculation->shouldOnlyDisplayApproximateOutput(&globalContext) == false); - store.deleteAll(); } + +void assertCalculationDisplay(const char * input, bool displayExactOutput, bool displayApproximateOutput, ::Calculation::Calculation::EqualSign sign, const char * exactOutput, const char * approximateOutput, Context * context, CalculationStore * store) { + char buffer[500]; + strlcpy(buffer, input, sizeof(buffer)); + translate_in_special_chars(buffer); + store->push(buffer, context); + ::Calculation::Calculation * lastCalculation = store->calculationAtIndex(1); + quiz_assert(lastCalculation->shouldOnlyDisplayExactOutput() == displayExactOutput); + quiz_assert(lastCalculation->shouldOnlyDisplayApproximateOutput(context) == displayApproximateOutput); + if (sign != ::Calculation::Calculation::EqualSign::Unknown) { + quiz_assert(lastCalculation->exactAndApproximateDisplayedOutputsAreEqual(context) == sign); + } + if (exactOutput) { + strlcpy(buffer, exactOutput, sizeof(buffer)); + translate_in_special_chars(buffer); + quiz_assert(strcmp(lastCalculation->exactOutputText(), buffer) == 0); + } + if (approximateOutput) { + strlcpy(buffer, approximateOutput, sizeof(buffer)); + translate_in_special_chars(buffer); + quiz_assert(strcmp(lastCalculation->approximateOutputText(),buffer) == 0); + } + store->deleteAll(); +} + +QUIZ_CASE(calculation_display_exact_approximate) { + Shared::GlobalContext globalContext; + CalculationStore store; + + assertCalculationDisplay("1/2", false, false, ::Calculation::Calculation::EqualSign::Equal, nullptr, nullptr, &globalContext, &store); + assertCalculationDisplay("1/3", false, false, ::Calculation::Calculation::EqualSign::Approximation, nullptr, nullptr, &globalContext, &store); + assertCalculationDisplay("1/0", true, false, ::Calculation::Calculation::EqualSign::Unknown, "undef", "undef", &globalContext, &store); + assertCalculationDisplay("2x-x", true, false, ::Calculation::Calculation::EqualSign::Unknown, "x", "undef", &globalContext, &store); + assertCalculationDisplay("[[1,2,3]]", false, true, ::Calculation::Calculation::EqualSign::Unknown, nullptr, nullptr, &globalContext, &store); + assertCalculationDisplay("[[1,x,3]]", false, true, ::Calculation::Calculation::EqualSign::Unknown, nullptr, nullptr, &globalContext, &store); + assertCalculationDisplay("28^7", false, false, ::Calculation::Calculation::EqualSign::Unknown, nullptr, nullptr, &globalContext, &store); + assertCalculationDisplay("3+R(2)>a", false, false, ::Calculation::Calculation::EqualSign::Approximation, "3+R(2)", nullptr, &globalContext, &store); + Ion::Storage::sharedStorage()->recordNamed("a.exp").destroy(); + assertCalculationDisplay("3+2>a", false, false, ::Calculation::Calculation::EqualSign::Equal, "3+2", "5", &globalContext, &store); + Ion::Storage::sharedStorage()->recordNamed("a.exp").destroy(); + assertCalculationDisplay("3>a", false, true, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "3", &globalContext, &store); + Ion::Storage::sharedStorage()->recordNamed("a.exp").destroy(); + assertCalculationDisplay("3+x>f(x)", true, false, ::Calculation::Calculation::EqualSign::Unknown, "3+x", nullptr, &globalContext, &store); + Ion::Storage::sharedStorage()->recordNamed("f.func").destroy(); +} From 6fd3a155df42297a1cd4ac6f5a1749f59132ecac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 20 Dec 2018 17:25:40 +0100 Subject: [PATCH 134/373] [calculation] Take into account the complex format 'real' --- apps/calculation/calculation.cpp | 7 +++++++ apps/calculation/test/calculation_store.cpp | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/apps/calculation/calculation.cpp b/apps/calculation/calculation.cpp index 9684f13bd..a88ec8c4b 100644 --- a/apps/calculation/calculation.cpp +++ b/apps/calculation/calculation.cpp @@ -53,6 +53,13 @@ void Calculation::setContent(const char * c, Context * context, Expression ansEx PoincareHelpers::ParseAndSimplifyAndApproximate(m_inputText, &exactOutput, &approximateOutput, *context); PoincareHelpers::Serialize(exactOutput, m_exactOutputText, sizeof(m_exactOutputText)); PoincareHelpers::Serialize(approximateOutput, m_approximateOutputText, sizeof(m_approximateOutputText)); + /* Check ComplexFormat: if complex format is real and the input text doesn't + * contain any i complex, both approximate and exact result are set to + * Undefined if the approximate output is not a pure real.*/ + if (Preferences::sharedPreferences()->complexFormat() == Preferences::ComplexFormat::Real && strchr(m_inputText, Ion::Charset::IComplex) == nullptr && strchr(m_approximateOutputText, Ion::Charset::IComplex) != nullptr) { + strlcpy(m_exactOutputText, Undefined::Name(), Constant::MaxSerializedExpressionSize); + strlcpy(m_approximateOutputText, Undefined::Name(), Constant::MaxSerializedExpressionSize); + } } KDCoordinate Calculation::height(Context * context) { diff --git a/apps/calculation/test/calculation_store.cpp b/apps/calculation/test/calculation_store.cpp index 6e43fd542..f7679cc31 100644 --- a/apps/calculation/test/calculation_store.cpp +++ b/apps/calculation/test/calculation_store.cpp @@ -113,3 +113,24 @@ QUIZ_CASE(calculation_display_exact_approximate) { assertCalculationDisplay("3+x>f(x)", true, false, ::Calculation::Calculation::EqualSign::Unknown, "3+x", nullptr, &globalContext, &store); Ion::Storage::sharedStorage()->recordNamed("f.func").destroy(); } + +QUIZ_CASE(calculation_complex_format) { + Shared::GlobalContext globalContext; + CalculationStore store; + + Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Real); + assertCalculationDisplay("1+I", false, true, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "1+I", &globalContext, &store); + assertCalculationDisplay("R(-1)", true, false, ::Calculation::Calculation::EqualSign::Unknown, "undef", nullptr, &globalContext, &store); + assertCalculationDisplay("ln(-2)", true, false, ::Calculation::Calculation::EqualSign::Unknown, "undef", nullptr, &globalContext, &store); + + Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Cartesian); + assertCalculationDisplay("1+I", false, true, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "1+I", &globalContext, &store); + assertCalculationDisplay("R(-1)", false, true, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "I", &globalContext, &store); + assertCalculationDisplay("ln(-2)", false, false, ::Calculation::Calculation::EqualSign::Approximation, "ln(-2)", nullptr, &globalContext, &store); + + Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Polar); + assertCalculationDisplay("1+I", false, false, ::Calculation::Calculation::EqualSign::Approximation, "R(2)*X^(P/4*I)", nullptr, &globalContext, &store); + assertCalculationDisplay("R(-1)", false, false, ::Calculation::Calculation::EqualSign::Approximation, "X^(P/2*I)", nullptr, &globalContext, &store); + assertCalculationDisplay("ln(-2)", false, false, ::Calculation::Calculation::EqualSign::Approximation, "ln(-2)", nullptr, &globalContext, &store); + Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Cartesian); +} From aa80710f4d916c62b2cf8eb8c0b42479924ffedf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 21 Dec 2018 10:24:02 +0100 Subject: [PATCH 135/373] [solver] Take into account the complexFormat Real --- apps/solver/equation.cpp | 4 +++ apps/solver/equation.h | 1 + apps/solver/equation_store.cpp | 44 ++++++++++++++++++----- apps/solver/equation_store.h | 1 + apps/solver/test/equation_store.cpp | 55 +++++++++++++++++++++++++++++ 5 files changed, 97 insertions(+), 8 deletions(-) diff --git a/apps/solver/equation.cpp b/apps/solver/equation.cpp index 3565c86c8..7a19ab32d 100644 --- a/apps/solver/equation.cpp +++ b/apps/solver/equation.cpp @@ -43,6 +43,10 @@ Expression Equation::standardForm(Context * context) const { return m_standardForm; } +bool Equation::containsIComplex() const { + return strchr(text(), Ion::Charset::IComplex) != nullptr; +} + void Equation::tidyStandardForm() { // Free the pool of the m_standardForm m_standardForm = Expression(); diff --git a/apps/solver/equation.h b/apps/solver/equation.h index 3a079e836..de5688753 100644 --- a/apps/solver/equation.h +++ b/apps/solver/equation.h @@ -14,6 +14,7 @@ public: return false; } Poincare::Expression standardForm(Poincare::Context * context) const; + bool containsIComplex() const; private: void tidyStandardForm(); mutable Poincare::Expression m_standardForm; diff --git a/apps/solver/equation_store.cpp b/apps/solver/equation_store.cpp index caae2088d..dc5e8c251 100644 --- a/apps/solver/equation_store.cpp +++ b/apps/solver/equation_store.cpp @@ -2,6 +2,7 @@ #include "../shared/poincare_helpers.h" #include +#include #include #include #include @@ -170,21 +171,39 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) { } } /* Turn the results in layouts */ - for (int i = 0; i < k_maxNumberOfExactSolutions; i++) { + int solutionIndex = 0; + int initialNumberOfSolutions = m_numberOfSolutions; + // We iterate through the solutions and the potential delta + for (int i = 0; i < initialNumberOfSolutions+1; i++) { if (!exactSolutions[i].isUninitialized()) { - m_exactSolutionExactLayouts[i] = PoincareHelpers::CreateLayout(exactSolutions[i]); - m_exactSolutionApproximateLayouts[i] = PoincareHelpers::CreateLayout(exactSolutionsApproximations[i]); + /* Discard complex solutions if ComplexFormat is Real and the equation + * system was not explicitly complex. */ + if (Preferences::sharedPreferences()->complexFormat() == Preferences::ComplexFormat::Real && !isExplictlyComplex() && exactSolutionsApproximations[i].recursivelyMatches([](const Expression e, Context & context, bool replaceSymbols) { return e.type() == ExpressionNode::Type::Constant && static_cast(e).isIComplex(); }, *context, false)) { + if (i < initialNumberOfSolutions) { + // Discard the solution + m_numberOfSolutions--; + continue; + } else { + assert( i == initialNumberOfSolutions); + // Delta is not real + exactSolutions[i] = Undefined(); + exactSolutionsApproximations[i] = Undefined(); + } + } + m_exactSolutionExactLayouts[solutionIndex] = PoincareHelpers::CreateLayout(exactSolutions[i]); + m_exactSolutionApproximateLayouts[solutionIndex] = PoincareHelpers::CreateLayout(exactSolutionsApproximations[i]); /* Check for identity between exact and approximate layouts */ char exactBuffer[Shared::ExpressionModel::k_expressionBufferSize]; char approximateBuffer[Shared::ExpressionModel::k_expressionBufferSize]; - m_exactSolutionExactLayouts[i].serializeForParsing(exactBuffer, Shared::ExpressionModel::k_expressionBufferSize); - m_exactSolutionApproximateLayouts[i].serializeForParsing(approximateBuffer, Shared::ExpressionModel::k_expressionBufferSize); - m_exactSolutionIdentity[i] = strcmp(exactBuffer, approximateBuffer) == 0; + m_exactSolutionExactLayouts[solutionIndex].serializeForParsing(exactBuffer, Shared::ExpressionModel::k_expressionBufferSize); + m_exactSolutionApproximateLayouts[solutionIndex].serializeForParsing(approximateBuffer, Shared::ExpressionModel::k_expressionBufferSize); + m_exactSolutionIdentity[solutionIndex] = strcmp(exactBuffer, approximateBuffer) == 0; /* Check for equality between exact and approximate layouts */ - if (!m_exactSolutionIdentity[i]) { + if (!m_exactSolutionIdentity[solutionIndex]) { char buffer[Shared::ExpressionModel::k_expressionBufferSize]; - m_exactSolutionEquality[i] = exactSolutions[i].isEqualToItsApproximationLayout(exactSolutionsApproximations[i], buffer, Shared::ExpressionModel::k_expressionBufferSize, preferences->angleUnit(), preferences->displayMode(), preferences->numberOfSignificantDigits(), *context); + m_exactSolutionEquality[solutionIndex] = exactSolutions[i].isEqualToItsApproximationLayout(exactSolutionsApproximations[i], buffer, Shared::ExpressionModel::k_expressionBufferSize, preferences->angleUnit(), preferences->displayMode(), preferences->numberOfSignificantDigits(), *context); } + solutionIndex++; } } return error; @@ -337,4 +356,13 @@ void EquationStore::tidySolution() { } } +bool EquationStore::isExplictlyComplex() { + for (int i = 0; i < numberOfDefinedModels(); i++) { + if (definedModelAtIndex(i)->containsIComplex()) { + return true; + } + } + return false; +} + } diff --git a/apps/solver/equation_store.h b/apps/solver/equation_store.h index 1a12433bb..bbce1439d 100644 --- a/apps/solver/equation_store.h +++ b/apps/solver/equation_store.h @@ -82,6 +82,7 @@ private: Error resolveLinearSystem(Poincare::Expression solutions[k_maxNumberOfExactSolutions], Poincare::Expression solutionApproximations[k_maxNumberOfExactSolutions], Poincare::Expression coefficients[k_maxNumberOfEquations][Poincare::Expression::k_maxNumberOfVariables], Poincare::Expression constants[k_maxNumberOfEquations], Poincare::Context * context); Error oneDimensialPolynomialSolve(Poincare::Expression solutions[k_maxNumberOfExactSolutions], Poincare::Expression solutionApproximations[k_maxNumberOfExactSolutions], Poincare::Expression polynomialCoefficients[Poincare::Expression::k_maxNumberOfPolynomialCoefficients], int degree, Poincare::Context * context); void tidySolution(); + bool isExplictlyComplex(); Equation m_equations[k_maxNumberOfEquations]; Type m_type; diff --git a/apps/solver/test/equation_store.cpp b/apps/solver/test/equation_store.cpp index 30e1279d5..5e4f53e7f 100644 --- a/apps/solver/test/equation_store.cpp +++ b/apps/solver/test/equation_store.cpp @@ -169,4 +169,59 @@ QUIZ_CASE(equation_solve) { assert_equation_system_exact_solve_to(equations19, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesBig1Big2, solutions19, 2); } +QUIZ_CASE(equation_solve_complex_format) { + Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Real); + const char * variablesx[] = {"x", ""}; + // x+I = 0 --> x = -I + const char * equations0[] = {"x+I=0", 0}; + const char * solutions0[] = {"-I"}; + assert_equation_system_exact_solve_to(equations0, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesx, solutions0, 1); + + // x+R(-1) = 0 --> pas de solution dans R + const char * equations1[] = {"x+R(-1)=0", 0}; + assert_equation_system_exact_solve_to(equations1, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesx, nullptr, 0); + + // x^2+x+1=0 --> pas de solution dans R + const char * equations2[] = {"x^2+x+1=0", 0}; + const char * delta2[] = {"-3"}; + assert_equation_system_exact_solve_to(equations2, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, delta2, 0); + + // x^2-R(-1)=0 --> pas de solution dans R + const char * equations3[] = {"x^2-R(-1)=0", 0}; + const char * delta3[] = {"undef"}; + assert_equation_system_exact_solve_to(equations3, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, delta3, 0); + + Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Cartesian); + // x+I = 0 --> x = -I + assert_equation_system_exact_solve_to(equations0, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesx, solutions0, 1); + + // x+R(-1) = 0 --> x = -I + assert_equation_system_exact_solve_to(equations1, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesx, solutions0, 1); + + // x^2+x+1=0 + const char * solutions2[] = {"-(1)/(2)-(R(3))/(2)*I","-(1)/(2)+(R(3))/(2)*I", "-3"}; + assert_equation_system_exact_solve_to(equations2, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions2, 2); + + // x^2-R(-1)=0 + const char * solutions3[] = {"-(R(2))/(2)-(R(2))/(2)*I", "(R(2))/(2)+(R(2))/(2)*I","4*I"}; + assert_equation_system_exact_solve_to(equations3, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions3, 2); + + Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Polar); + // x+I = 0 --> x = e^(-pi/2*i) + const char * solutions0Polar[] = {"X$-(P)/(2)*I#"}; + assert_equation_system_exact_solve_to(equations0, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesx, solutions0Polar, 1); + + // x+R(-1) = 0 --> x = e^(-pi/2*i) + assert_equation_system_exact_solve_to(equations1, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesx, solutions0Polar, 1); + + // x^2+x+1=0 + const char * solutions2Polar[] = {"X$-(2*P)/(3)*I#","X$(2*P)/(3)*I#", "3*X$P*I#"}; + assert_equation_system_exact_solve_to(equations2, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions2Polar, 2); + + // x^2-R(-1)=0 + const char * solutions3Polar[] = {"X$-(3*P)/(4)*I#", "X$(P)/(4)*I#", "4*X$(P)/(2)*I#"}; + assert_equation_system_exact_solve_to(equations3, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions3Polar, 2); + +} + } From 3de8901c22f2fa9a093ed66763be98249eddf948 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 21 Dec 2018 11:10:50 +0100 Subject: [PATCH 136/373] [poincare] Use reduce instead of setting the sSimplificationHasBeenInterrupted flag and deepReducing --- poincare/src/expression.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index c2621023d..584b24042 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -148,8 +148,6 @@ bool containsVariables(const Expression e, char * variables, int maxVariableSize } bool Expression::getLinearCoefficients(char * variables, int maxVariableSize, Expression coefficients[], Expression constant[], Context & context, Preferences::AngleUnit angleUnit) const { - // Reset interrupting flag because we use deepReduce - sSimplificationHasBeenInterrupted = false; assert(!recursivelyMatches(IsMatrix, context, true)); // variables is in fact of type char[k_maxNumberOfVariables][maxVariableSize] int index = 0; @@ -185,7 +183,7 @@ bool Expression::getLinearCoefficients(char * variables, int maxVariableSize, Ex equation = polynomialCoefficients[0]; index++; } - constant[0] = Opposite(equation.clone()).deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); + constant[0] = Opposite(equation.clone()).reduce(context, angleUnit); /* The expression can be linear on all coefficients taken one by one but * non-linear (ex: xy = 2). We delete the results and return false if one of * the coefficients contains a variable. */ @@ -295,10 +293,9 @@ int Expression::defaultGetPolynomialCoefficients(Context & context, const char * int Expression::getPolynomialReducedCoefficients(const char * symbolName, Expression coefficients[], Context & context, Preferences::AngleUnit angleUnit) const { // Reset interrupting flag because we use deepReduce - sSimplificationHasBeenInterrupted = false; int degree = getPolynomialCoefficients(context, symbolName, coefficients); for (int i = 0; i <= degree; i++) { - coefficients[i] = coefficients[i].deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); + coefficients[i] = coefficients[i].reduce(context, angleUnit); } return degree; } From 1f247b731deaaa0019f2d43b30e77791358e5372 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 21 Dec 2018 11:46:35 +0100 Subject: [PATCH 137/373] [poincare] Discard useless parameters of sign and isReal methods --- poincare/include/poincare/absolute_value.h | 4 +- poincare/include/poincare/arc_tangent.h | 2 +- .../include/poincare/binomial_coefficient.h | 2 +- poincare/include/poincare/ceiling.h | 2 +- poincare/include/poincare/complex_argument.h | 2 +- poincare/include/poincare/conjugate.h | 2 +- poincare/include/poincare/constant.h | 4 +- poincare/include/poincare/cosine.h | 2 +- poincare/include/poincare/decimal.h | 2 +- poincare/include/poincare/derivative.h | 2 +- poincare/include/poincare/division_quotient.h | 2 +- .../include/poincare/division_remainder.h | 2 +- poincare/include/poincare/expression.h | 4 +- poincare/include/poincare/expression_node.h | 4 +- poincare/include/poincare/factorial.h | 4 +- poincare/include/poincare/float.h | 2 +- poincare/include/poincare/floor.h | 2 +- poincare/include/poincare/frac_part.h | 2 +- poincare/include/poincare/function.h | 2 +- .../include/poincare/great_common_divisor.h | 2 +- poincare/include/poincare/imaginary_part.h | 2 +- poincare/include/poincare/infinity.h | 2 +- poincare/include/poincare/integral.h | 2 +- .../include/poincare/least_common_multiple.h | 2 +- poincare/include/poincare/multiplication.h | 2 +- .../include/poincare/n_ary_expression_node.h | 4 +- poincare/include/poincare/number.h | 4 +- poincare/include/poincare/opposite.h | 2 +- .../include/poincare/permute_coefficient.h | 2 +- poincare/include/poincare/power.h | 4 +- poincare/include/poincare/randint.h | 2 +- poincare/include/poincare/random.h | 4 +- poincare/include/poincare/rational.h | 2 +- poincare/include/poincare/real_part.h | 2 +- poincare/include/poincare/round.h | 2 +- poincare/include/poincare/sign_function.h | 4 +- poincare/include/poincare/sine.h | 2 +- poincare/include/poincare/symbol.h | 2 +- poincare/include/poincare/symbol_abstract.h | 4 +- poincare/include/poincare/tangent.h | 2 +- poincare/include/poincare/undefined.h | 2 +- poincare/src/absolute_value.cpp | 2 +- poincare/src/addition.cpp | 2 +- poincare/src/complex_argument.cpp | 2 +- poincare/src/complex_cartesian.cpp | 2 +- poincare/src/conjugate.cpp | 2 +- poincare/src/constant.cpp | 4 +- poincare/src/expression.cpp | 6 +-- poincare/src/function.cpp | 4 +- poincare/src/imaginary_part.cpp | 2 +- poincare/src/logarithm.cpp | 6 +-- poincare/src/multiplication.cpp | 14 +++--- poincare/src/n_ary_expression_node.cpp | 8 ++-- poincare/src/opposite.cpp | 8 ++-- poincare/src/power.cpp | 44 +++++++++---------- poincare/src/rational.cpp | 2 +- poincare/src/real_part.cpp | 2 +- poincare/src/sign_function.cpp | 6 +-- poincare/src/symbol.cpp | 12 +---- poincare/src/symbol_abstract.cpp | 8 ++-- poincare/test/properties.cpp | 2 +- 61 files changed, 117 insertions(+), 125 deletions(-) diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 665d5fa4a..78ae396f7 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -20,11 +20,11 @@ public: // Properties Type type() const override { return Type::AbsoluteValue; } - Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override { return Sign::Positive; } + Sign sign(Context * context) const override { return Sign::Positive; } Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + bool isReal(Context & context) const override { return true; } // Approximation template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { diff --git a/poincare/include/poincare/arc_tangent.h b/poincare/include/poincare/arc_tangent.h index f581c2e0e..2f420652b 100644 --- a/poincare/include/poincare/arc_tangent.h +++ b/poincare/include/poincare/arc_tangent.h @@ -23,7 +23,7 @@ public: Type type() const override { return Type::ArcTangent; } // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return childAtIndex(0)->isReal(context, angleUnit); } + bool isReal(Context & context) const override { return childAtIndex(0)->isReal(context); } private: // Layout diff --git a/poincare/include/poincare/binomial_coefficient.h b/poincare/include/poincare/binomial_coefficient.h index 9dcebba2c..e6d045226 100644 --- a/poincare/include/poincare/binomial_coefficient.h +++ b/poincare/include/poincare/binomial_coefficient.h @@ -19,7 +19,7 @@ public: #endif // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + bool isReal(Context & context) const override { return true; } // Properties Type type() const override{ return Type::BinomialCoefficient; } diff --git a/poincare/include/poincare/ceiling.h b/poincare/include/poincare/ceiling.h index 9d1bb78f5..24cc2f873 100644 --- a/poincare/include/poincare/ceiling.h +++ b/poincare/include/poincare/ceiling.h @@ -19,7 +19,7 @@ public: #endif // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + bool isReal(Context & context) const override { return true; } // Properties Type type() const override { return Type::Ceiling; } diff --git a/poincare/include/poincare/complex_argument.h b/poincare/include/poincare/complex_argument.h index fa751d591..be92899af 100644 --- a/poincare/include/poincare/complex_argument.h +++ b/poincare/include/poincare/complex_argument.h @@ -18,7 +18,7 @@ public: } #endif // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + bool isReal(Context & context) const override { return true; } // Properties Type type() const override { return Type::ComplexArgument; } diff --git a/poincare/include/poincare/conjugate.h b/poincare/include/poincare/conjugate.h index 141e897fd..02907c9b2 100644 --- a/poincare/include/poincare/conjugate.h +++ b/poincare/include/poincare/conjugate.h @@ -18,7 +18,7 @@ public: } #endif - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return childAtIndex(0)->isReal(context, angleUnit); } + bool isReal(Context & context) const override { return childAtIndex(0)->isReal(context); } // Properties Type type() const override { return Type::Conjugate; } diff --git a/poincare/include/poincare/constant.h b/poincare/include/poincare/constant.h index acf8be0a4..babaf7339 100644 --- a/poincare/include/poincare/constant.h +++ b/poincare/include/poincare/constant.h @@ -18,11 +18,11 @@ public: #endif // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override; + bool isReal(Context & context) const override; // Expression Properties Type type() const override { return Type::Constant; } - Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override; + Sign sign(Context * context) const override; /* Layout */ Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index 7fd552ccb..713f4ad64 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -20,7 +20,7 @@ public: #endif // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return childAtIndex(0)->isReal(context, angleUnit); } + bool isReal(Context & context) const override { return childAtIndex(0)->isReal(context); } // Properties Type type() const override { return Type::Cosine; } diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index a19dcb552..1bf27f46e 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -47,7 +47,7 @@ public: // Properties Type type() const override { return Type::Decimal; } - Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override { return m_negative ? Sign::Negative : Sign::Positive; } + Sign sign(Context * context) const override { return m_negative ? Sign::Negative : Sign::Positive; } Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Approximation diff --git a/poincare/include/poincare/derivative.h b/poincare/include/poincare/derivative.h index afda48893..2c182c9b2 100644 --- a/poincare/include/poincare/derivative.h +++ b/poincare/include/poincare/derivative.h @@ -20,7 +20,7 @@ public: #endif // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + bool isReal(Context & context) const override { return true; } // Properties Type type() const override { return Type::Derivative; } diff --git a/poincare/include/poincare/division_quotient.h b/poincare/include/poincare/division_quotient.h index 36c3a002d..030710664 100644 --- a/poincare/include/poincare/division_quotient.h +++ b/poincare/include/poincare/division_quotient.h @@ -21,7 +21,7 @@ public: Type type() const override { return Type::DivisionQuotient; } // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + bool isReal(Context & context) const override { return true; } private: // Layout diff --git a/poincare/include/poincare/division_remainder.h b/poincare/include/poincare/division_remainder.h index c0a4ca2ab..a50d99653 100644 --- a/poincare/include/poincare/division_remainder.h +++ b/poincare/include/poincare/division_remainder.h @@ -22,7 +22,7 @@ public: Type type() const override { return Type::DivisionRemainder; } // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + bool isReal(Context & context) const override { return true; } private: // Layout diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index a31e4a5c7..a741f9949 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -119,7 +119,7 @@ public: /* Properties */ ExpressionNode::Type type() const { return node()->type(); } - ExpressionNode::Sign sign(Context * context, Preferences::AngleUnit angleUnit) const { return node()->sign(context, angleUnit); } + ExpressionNode::Sign sign(Context * context) const { return node()->sign(context); } bool isUndefined() const { return node()->type() == ExpressionNode::Type::Undefined; } bool isNumber() const { return node()->isNumber(); } bool isRationalZero() const; @@ -167,7 +167,7 @@ public: Expression defaultReplaceUnknown(const Symbol & symbol); /* Complex */ - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const { return node()->isReal(context, angleUnit); } + bool isReal(Context & context) const { return node()->isReal(context); } /* Comparison */ /* isIdenticalTo is the "easy" equality, it returns true if both trees have diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index 2f5a6be7e..488c7869b 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -112,7 +112,7 @@ public: Unknown = 0, Positive = 1 }; - virtual Sign sign(Context * context, Preferences::AngleUnit angleUnit) const { return Sign::Unknown; } + virtual Sign sign(Context * context) const { return Sign::Unknown; } virtual bool isNumber() const { return false; } /*!*/ virtual Expression replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression); /*!*/ virtual Expression replaceUnknown(const Symbol & symbol); @@ -126,7 +126,7 @@ public: bool isOfType(Type * types, int length) const; /* Complex */ - virtual bool isReal(Context & context, Preferences::AngleUnit angleUnit) const { return false; } + virtual bool isReal(Context & context) const { return false; } /* Simplification */ /* SimplificationOrder returns: diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index 2ed36e38b..5ff8b4f66 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -20,11 +20,11 @@ public: // Properties Type type() const override { return Type::Factorial; } - Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override { return Sign::Positive; } + Sign sign(Context * context) const override { return Sign::Positive; } Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + bool isReal(Context & context) const override { return true; } private: // Layout diff --git a/poincare/include/poincare/float.h b/poincare/include/poincare/float.h index 6d0998448..ea42c5d84 100644 --- a/poincare/include/poincare/float.h +++ b/poincare/include/poincare/float.h @@ -39,7 +39,7 @@ public: // Properties Type type() const override { return Type::Float; } - Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override { return m_value < 0 ? Sign::Negative : Sign::Positive; } + Sign sign(Context * context) const override { return m_value < 0 ? Sign::Negative : Sign::Positive; } Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override; diff --git a/poincare/include/poincare/floor.h b/poincare/include/poincare/floor.h index 24fc2b44f..ba7ff823f 100644 --- a/poincare/include/poincare/floor.h +++ b/poincare/include/poincare/floor.h @@ -23,7 +23,7 @@ public: // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + bool isReal(Context & context) const override { return true; } private: // Layout diff --git a/poincare/include/poincare/frac_part.h b/poincare/include/poincare/frac_part.h index b39d8e039..071a42c3d 100644 --- a/poincare/include/poincare/frac_part.h +++ b/poincare/include/poincare/frac_part.h @@ -23,7 +23,7 @@ public: // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + bool isReal(Context & context) const override { return true; } private: // Layout diff --git a/poincare/include/poincare/function.h b/poincare/include/poincare/function.h index 71aa21854..572c0557b 100644 --- a/poincare/include/poincare/function.h +++ b/poincare/include/poincare/function.h @@ -28,7 +28,7 @@ public: float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override; // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override; + bool isReal(Context & context) const override; private: char m_name[0]; // MUST be the last member variable diff --git a/poincare/include/poincare/great_common_divisor.h b/poincare/include/poincare/great_common_divisor.h index 8d601de24..8b21c67c1 100644 --- a/poincare/include/poincare/great_common_divisor.h +++ b/poincare/include/poincare/great_common_divisor.h @@ -20,7 +20,7 @@ public: // ExpressionNode Type type() const override { return Type::GreatCommonDivisor; } // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + bool isReal(Context & context) const override { return true; } private: // Layout diff --git a/poincare/include/poincare/imaginary_part.h b/poincare/include/poincare/imaginary_part.h index d6f24f590..f0e838cd9 100644 --- a/poincare/include/poincare/imaginary_part.h +++ b/poincare/include/poincare/imaginary_part.h @@ -22,7 +22,7 @@ public: Type type() const override { return Type::ImaginaryPart; } // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + bool isReal(Context & context) const override { return true; } private: // Layout diff --git a/poincare/include/poincare/infinity.h b/poincare/include/poincare/infinity.h index 5aecea410..9d3c8065d 100644 --- a/poincare/include/poincare/infinity.h +++ b/poincare/include/poincare/infinity.h @@ -24,7 +24,7 @@ public: // Properties Type type() const override { return Type::Infinity; } - Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override { return m_negative ? Sign::Negative : Sign::Positive; } + Sign sign(Context * context) const override { return m_negative ? Sign::Negative : Sign::Positive; } // Approximation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/integral.h b/poincare/include/poincare/integral.h index b9231ca71..cb7840b99 100644 --- a/poincare/include/poincare/integral.h +++ b/poincare/include/poincare/integral.h @@ -24,7 +24,7 @@ public: Expression replaceUnknown(const Symbol & symbol) override; // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + bool isReal(Context & context) const override { return true; } private: // Layout diff --git a/poincare/include/poincare/least_common_multiple.h b/poincare/include/poincare/least_common_multiple.h index 00b909bd5..78566ab35 100644 --- a/poincare/include/poincare/least_common_multiple.h +++ b/poincare/include/poincare/least_common_multiple.h @@ -20,7 +20,7 @@ public: Type type() const override { return Type::LeastCommonMultiple; } // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + bool isReal(Context & context) const override { return true; } private: /* Layout */ diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index c4a1565a3..07c621cbf 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -21,7 +21,7 @@ public: // Properties Type type() const override { return Type::Multiplication; } - Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override; + Sign sign(Context * context) const override; int polynomialDegree(Context & context, const char * symbolName) const override; int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const override; diff --git a/poincare/include/poincare/n_ary_expression_node.h b/poincare/include/poincare/n_ary_expression_node.h index c537c0a6c..09e9dc879 100644 --- a/poincare/include/poincare/n_ary_expression_node.h +++ b/poincare/include/poincare/n_ary_expression_node.h @@ -19,7 +19,7 @@ public: void eraseNumberOfChildren() override { m_numberOfChildren = 0; } // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override; + bool isReal(Context & context) const override; // Comparison typedef int (*ExpressionOrder)(const ExpressionNode * e1, const ExpressionNode * e2, bool canBeInterrupted); @@ -55,7 +55,7 @@ public: * - 1 if all children are real * - 0 if all non real children are ComplexCartesian * - -1 if some chidren are non-real and non ComplexCartesian */ - int allChildrenAreReal(Context & context, Preferences::AngleUnit angleUnit) const; + int allChildrenAreReal(Context & context) const; protected: NAryExpressionNode * node() const { return static_cast(Expression::node()); } }; diff --git a/poincare/include/poincare/number.h b/poincare/include/poincare/number.h index fe23a2dfd..6ef5635cf 100644 --- a/poincare/include/poincare/number.h +++ b/poincare/include/poincare/number.h @@ -23,7 +23,7 @@ public: double doubleApproximation() const; // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + bool isReal(Context & context) const override { return true; } }; class Number : public Expression { @@ -46,7 +46,7 @@ public: /* Number::sign() or Number::setSign does not need a context or an angle unit * (a number can be Infinity, Undefined, Float, Decimal, Rational). */ - ExpressionNode::Sign sign() { return Expression::sign(nullptr, Preferences::AngleUnit::Degree); } + ExpressionNode::Sign sign() { return Expression::sign(nullptr); } Number setSign(ExpressionNode::Sign s) { return Expression::setSign(s, nullptr, Preferences::AngleUnit::Degree, ExpressionNode::ReductionTarget::User).convert(); } protected: Number() : Expression() {} diff --git a/poincare/include/poincare/opposite.h b/poincare/include/poincare/opposite.h index 8e443f6f9..aa2fe69d3 100644 --- a/poincare/include/poincare/opposite.h +++ b/poincare/include/poincare/opposite.h @@ -25,7 +25,7 @@ public: // Properties Type type() const override { return Type::Opposite; } int polynomialDegree(Context & context, const char * symbolName) const override; - Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override; + Sign sign(Context * context) const override; // Approximation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/permute_coefficient.h b/poincare/include/poincare/permute_coefficient.h index 426a90684..c21e929d3 100644 --- a/poincare/include/poincare/permute_coefficient.h +++ b/poincare/include/poincare/permute_coefficient.h @@ -24,7 +24,7 @@ public: Type type() const override{ return Type::PermuteCoefficient; } // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + bool isReal(Context & context) const override { return true; } private: // Layout diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index cead102dc..05efc61d0 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -22,11 +22,11 @@ public: #endif // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override; + bool isReal(Context & context) const override; // Properties Type type() const override { return Type::Power; } - Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override; + Sign sign(Context * context) const override; Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; int polynomialDegree(Context & context, const char * symbolName) const override; diff --git a/poincare/include/poincare/randint.h b/poincare/include/poincare/randint.h index ce11d615c..c1e7de0c0 100644 --- a/poincare/include/poincare/randint.h +++ b/poincare/include/poincare/randint.h @@ -21,7 +21,7 @@ public: Type type() const override { return Type::Randint; } // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + bool isReal(Context & context) const override { return true; } private: // Layout diff --git a/poincare/include/poincare/random.h b/poincare/include/poincare/random.h index d6b5096d6..fad6266ad 100644 --- a/poincare/include/poincare/random.h +++ b/poincare/include/poincare/random.h @@ -19,11 +19,11 @@ public: #endif // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + bool isReal(Context & context) const override { return true; } // Properties Type type() const override { return Type::Random; } - Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override { return Sign::Positive; } + Sign sign(Context * context) const override { return Sign::Positive; } Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; private: // Layout diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index 29fc7f2a7..fc5811504 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -36,7 +36,7 @@ public: // Expression subclassing Type type() const override { return Type::Rational; } - Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override { return m_negative ? Sign::Negative : Sign::Positive; } + Sign sign(Context * context) const override { return m_negative ? Sign::Negative : Sign::Positive; } // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/real_part.h b/poincare/include/poincare/real_part.h index f1344ccc7..5295ad2f6 100644 --- a/poincare/include/poincare/real_part.h +++ b/poincare/include/poincare/real_part.h @@ -22,7 +22,7 @@ public: Type type() const override { return Type::RealPart; } // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + bool isReal(Context & context) const override { return true; } private: // Layout diff --git a/poincare/include/poincare/round.h b/poincare/include/poincare/round.h index b9007b9f4..f41d174af 100644 --- a/poincare/include/poincare/round.h +++ b/poincare/include/poincare/round.h @@ -19,7 +19,7 @@ public: #endif // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + bool isReal(Context & context) const override { return true; } // Properties Type type() const override { return Type::Round; } diff --git a/poincare/include/poincare/sign_function.h b/poincare/include/poincare/sign_function.h index b10f33c85..54ee26dc9 100644 --- a/poincare/include/poincare/sign_function.h +++ b/poincare/include/poincare/sign_function.h @@ -20,11 +20,11 @@ public: // Properties Type type() const override { return Type::SignFunction; } - Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override; + Sign sign(Context * context) const override; Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return true; } + bool isReal(Context & context) const override { return true; } private: // Layout diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index 442630cc8..91ba724fb 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -20,7 +20,7 @@ public: #endif // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return childAtIndex(0)->isReal(context, angleUnit); } + bool isReal(Context & context) const override { return childAtIndex(0)->isReal(context); } // Properties Type type() const override { return Type::Sine; } diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index d621cf0a4..56bb8461d 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -27,7 +27,7 @@ public: float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override; // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override; + bool isReal(Context & context) const override; /* Layout */ Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/symbol_abstract.h b/poincare/include/poincare/symbol_abstract.h index a60910fa4..0b0dfa24d 100644 --- a/poincare/include/poincare/symbol_abstract.h +++ b/poincare/include/poincare/symbol_abstract.h @@ -35,7 +35,7 @@ public: int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override; // Property - Sign sign(Context * context, Preferences::AngleUnit angleUnit) const override; + Sign sign(Context * context) const override; Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // TreeNode @@ -80,7 +80,7 @@ protected: SymbolAbstractNode * node() const { return static_cast(Expression::node()); } private: static Expression Expand(const SymbolAbstract & symbol, Context & context, bool clone); - static bool isReal(const SymbolAbstract & symbol, Context & context, Preferences::AngleUnit angleUnit); + static bool isReal(const SymbolAbstract & symbol, Context & context); static size_t AlignedNodeSize(size_t nameLength, size_t nodeSize); }; diff --git a/poincare/include/poincare/tangent.h b/poincare/include/poincare/tangent.h index 71c1f2b1c..c2c00d1d4 100644 --- a/poincare/include/poincare/tangent.h +++ b/poincare/include/poincare/tangent.h @@ -23,7 +23,7 @@ public: float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override; // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return childAtIndex(0)->isReal(context, angleUnit); } + bool isReal(Context & context) const override { return childAtIndex(0)->isReal(context); } private: // Layout diff --git a/poincare/include/poincare/undefined.h b/poincare/include/poincare/undefined.h index d9ce9f4db..759fc261c 100644 --- a/poincare/include/poincare/undefined.h +++ b/poincare/include/poincare/undefined.h @@ -17,7 +17,7 @@ public: #endif // Complex - bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return false; } + bool isReal(Context & context) const override { return false; } // Properties Type type() const override { return Type::Undefined; } diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 6322cd326..dc11e4f88 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -48,7 +48,7 @@ Expression AbsoluteValue::shallowReduce(Context & context, Preferences::AngleUni #endif #endif Expression c = childAtIndex(0); - if (c.isReal(context, angleUnit)) { + if (c.isReal(context)) { float app = c.approximateToScalar(context, angleUnit); if (!std::isnan(app) && app >= Expression::epsilon()) { // abs(a) = a with a > 0 diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 3afb91fba..1891befad 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -255,7 +255,7 @@ Expression Addition::shallowReduce(Context & context, Preferences::AngleUnit ang * do anything about it now (allChildrenAreReal == -1) * - All children are either real or ComplexCartesian (allChildrenAreReal == 0) * We can bubble up ComplexCartesian nodes. */ - if (allChildrenAreReal(context, angleUnit) == 0) { + if (allChildrenAreReal(context) == 0) { /* We turn (a+ib)+(c+id) into (a+c)+i(c+d)*/ Addition imag; // we store all imaginary parts in 'imag' Addition real = *this; // we store all real parts in 'real' diff --git a/poincare/src/complex_argument.cpp b/poincare/src/complex_argument.cpp index 1d7176658..046206fe8 100644 --- a/poincare/src/complex_argument.cpp +++ b/poincare/src/complex_argument.cpp @@ -46,7 +46,7 @@ Expression ComplexArgument::shallowReduce(Context & context, Preferences::AngleU return SimplificationHelper::Map(*this, context, angleUnit); } #endif - bool real = c.isReal(context, angleUnit); + bool real = c.isReal(context); if (real) { float app = c.approximateToScalar(context, angleUnit); if (!std::isnan(app) && app >= Expression::epsilon()) { diff --git a/poincare/src/complex_cartesian.cpp b/poincare/src/complex_cartesian.cpp index 73bde8b91..a83b04920 100644 --- a/poincare/src/complex_cartesian.cpp +++ b/poincare/src/complex_cartesian.cpp @@ -109,7 +109,7 @@ Expression ComplexCartesian::squareNorm(Context & context, Preferences::AngleUni Expression ComplexCartesian::norm(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { if (imag().isRationalZero()) { Expression a = real(); - ExpressionNode::Sign s = a.sign(&context, angleUnit); + ExpressionNode::Sign s = a.sign(&context); if (s == ExpressionNode::Sign::Positive) { // Case 1: the expression is positive real return a;; diff --git a/poincare/src/conjugate.cpp b/poincare/src/conjugate.cpp index 796af952e..3d2686250 100644 --- a/poincare/src/conjugate.cpp +++ b/poincare/src/conjugate.cpp @@ -45,7 +45,7 @@ Expression Conjugate::shallowReduce(Context & context, Preferences::AngleUnit an return SimplificationHelper::Map(*this, context, angleUnit); } #endif - if (c.isReal(context, angleUnit)) { + if (c.isReal(context)) { replaceWithInPlace(c); return c; } diff --git a/poincare/src/constant.cpp b/poincare/src/constant.cpp index 37f0a841d..c32ca4be0 100644 --- a/poincare/src/constant.cpp +++ b/poincare/src/constant.cpp @@ -10,14 +10,14 @@ namespace Poincare { -ExpressionNode::Sign ConstantNode::sign(Context * context, Preferences::AngleUnit angleUnit) const { +ExpressionNode::Sign ConstantNode::sign(Context * context) const { if (isPi() || isExponential()) { return Sign::Positive; } return Sign::Unknown; } -bool ConstantNode::isReal(Context & context, Preferences::AngleUnit angleUnit) const { +bool ConstantNode::isReal(Context & context) const { return !isIComplex(); } diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 584b24042..b6ac0eaac 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -248,11 +248,11 @@ Expression Expression::defaultReplaceReplaceableSymbols(Context & context) { Expression Expression::makePositiveAnyNegativeNumeralFactor(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { // The expression is a negative number - if (isNumber() && sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { + if (isNumber() && sign(&context) == ExpressionNode::Sign::Negative) { return setSign(ExpressionNode::Sign::Positive, &context, angleUnit, target); } // The expression is a multiplication whose numeral factor is negative - if (type() == ExpressionNode::Type::Multiplication && numberOfChildren() > 0 && childAtIndex(0).isNumber() && childAtIndex(0).sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { + if (type() == ExpressionNode::Type::Multiplication && numberOfChildren() > 0 && childAtIndex(0).isNumber() && childAtIndex(0).sign(&context) == ExpressionNode::Sign::Negative) { Multiplication m = convert(); if (m.childAtIndex(0).type() == ExpressionNode::Type::Rational && m.childAtIndex(0).convert().isMinusOne()) { // The negative numeral factor is -1, we just remove it @@ -405,7 +405,7 @@ void Expression::simplifyAndApproximate(Expression * simplifiedExpression, Expre if (!sSimplificationHasBeenInterrupted) { /* Case 1: the reduced expression is ComplexCartesian or pure real, we can * take into account the complex format to display a+i*b or r*e^(i*th) */ - if (e.type() == ExpressionNode::Type::ComplexCartesian || e.isReal(context, angleUnit)) { + if (e.type() == ExpressionNode::Type::ComplexCartesian || e.isReal(context)) { ComplexCartesian ecomplex = e.type() == ExpressionNode::Type::ComplexCartesian ? static_cast(e) : ComplexCartesian::Builder(e, Rational(0)); if (approximateExpression) { /* Step 2: Approximation diff --git a/poincare/src/function.cpp b/poincare/src/function.cpp index 8e2b73bcf..becd1f6ae 100644 --- a/poincare/src/function.cpp +++ b/poincare/src/function.cpp @@ -9,9 +9,9 @@ namespace Poincare { -bool FunctionNode::isReal(Context & context, Preferences::AngleUnit angleUnit) const { +bool FunctionNode::isReal(Context & context) const { Function f(this); - return SymbolAbstract::isReal(f, context, angleUnit); + return SymbolAbstract::isReal(f, context); } Expression FunctionNode::replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression) { diff --git a/poincare/src/imaginary_part.cpp b/poincare/src/imaginary_part.cpp index dfe859363..3f8e14e7d 100644 --- a/poincare/src/imaginary_part.cpp +++ b/poincare/src/imaginary_part.cpp @@ -37,7 +37,7 @@ Expression ImaginaryPart::shallowReduce(Context & context, Preferences::AngleUni return SimplificationHelper::Map(*this, context, angleUnit); } #endif - if (c.isReal(context, angleUnit)) { + if (c.isReal(context)) { Expression result = Rational(0); replaceWithInPlace(result); return result; diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 958014e2d..4295012eb 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -120,7 +120,7 @@ Expression Logarithm::shallowReduce(Context & context, Preferences::AngleUnit an } #endif #endif - if (c.sign(&context, angleUnit) == ExpressionNode::Sign::Negative || childAtIndex(1).sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { + if (c.sign(&context) == ExpressionNode::Sign::Negative || childAtIndex(1).sign(&context) == ExpressionNode::Sign::Negative) { return *this; } Expression f = simpleShallowReduce(context, angleUnit); @@ -136,7 +136,7 @@ Expression Logarithm::shallowReduce(Context & context, Preferences::AngleUnit an */ bool letLogAtRoot = target == ExpressionNode::ReductionTarget::BottomUpComputation || parentIsAPowerOfSameBase(); // log(x^y, b)->y*log(x, b) if x>0 - if (!letLogAtRoot && c.type() == ExpressionNode::Type::Power && c.childAtIndex(0).sign(&context, angleUnit) == ExpressionNode::Sign::Positive) { + if (!letLogAtRoot && c.type() == ExpressionNode::Type::Power && c.childAtIndex(0).sign(&context) == ExpressionNode::Sign::Positive) { Power p = static_cast(c); Expression x = p.childAtIndex(0); Expression y = p.childAtIndex(1); @@ -152,7 +152,7 @@ Expression Logarithm::shallowReduce(Context & context, Preferences::AngleUnit an Addition a = Addition(); for (int i = 0; i < c.numberOfChildren()-1; i++) { Expression factor = c.childAtIndex(i); - if (factor.sign(&context, angleUnit) == ExpressionNode::Sign::Positive) { + if (factor.sign(&context) == ExpressionNode::Sign::Positive) { Expression newLog = clone(); static_cast(c).removeChildInPlace(factor, factor.numberOfChildren()); newLog.replaceChildAtIndexInPlace(0, factor); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 517593ccc..2a51cf782 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -17,16 +17,16 @@ namespace Poincare { -ExpressionNode::Sign MultiplicationNode::sign(Context * context, Preferences::AngleUnit angleUnit) const { +ExpressionNode::Sign MultiplicationNode::sign(Context * context) const { if (numberOfChildren() == 0) { return Sign::Unknown; } int sign = 1; for (ExpressionNode * c : children()) { - sign *= (int)(c->sign(context, angleUnit)); + sign *= (int)(c->sign(context)); } if (sign == 0) { - return ExpressionNode::sign(context, angleUnit); + return ExpressionNode::sign(context); } return (Sign)sign; } @@ -125,7 +125,7 @@ void Multiplication::computeOnArrays(T * m, T * n, T * result, int mNumberOfColu Expression Multiplication::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { assert(s == ExpressionNode::Sign::Positive); for (int i = 0; i < numberOfChildren(); i++) { - if (childAtIndex(i).sign(context, angleUnit) == ExpressionNode::Sign::Negative) { + if (childAtIndex(i).sign(context) == ExpressionNode::Sign::Negative) { replaceChildAtIndexInPlace(i, childAtIndex(i).setSign(s, context, angleUnit, target)); } } @@ -475,7 +475,7 @@ Expression Multiplication::privateShallowReduce(Context & context, Preferences:: * do anything about it now (allChildrenAreReal == -1) * - All children are either real or ComplexCartesian (allChildrenAreReal == 0) * We can bubble up ComplexCartesian nodes. */ - if (allChildrenAreReal(context, angleUnit) == 0) { + if (allChildrenAreReal(context) == 0) { int nbChildren = numberOfChildren(); int i = nbChildren-1; // Children are sorted so ComplexCartesian nodes are at the end @@ -624,7 +624,7 @@ void Multiplication::addMissingFactors(Expression factor, Context & context, Pre for (int i = 0; i < numberOfChildren(); i++) { if (TermsHaveIdenticalBase(childAtIndex(i), factor)) { Expression sub = Subtraction(CreateExponent(childAtIndex(i)), CreateExponent(factor)).deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); - if (sub.sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { // index[0] < index[1] + if (sub.sign(&context) == ExpressionNode::Sign::Negative) { // index[0] < index[1] sub = Opposite(sub); if (factor.type() == ExpressionNode::Type::Power) { factor.replaceChildAtIndexInPlace(1, sub); @@ -633,7 +633,7 @@ void Multiplication::addMissingFactors(Expression factor, Context & context, Pre } sub.shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); mergeInChildByFactorizingBase(i, factor, context, angleUnit, ExpressionNode::ReductionTarget::User); - } else if (sub.sign(&context, angleUnit) == ExpressionNode::Sign::Unknown) { + } else if (sub.sign(&context) == ExpressionNode::Sign::Unknown) { mergeInChildByFactorizingBase(i, factor, context, angleUnit, ExpressionNode::ReductionTarget::User); } return; diff --git a/poincare/src/n_ary_expression_node.cpp b/poincare/src/n_ary_expression_node.cpp index 99f747199..6606a9650 100644 --- a/poincare/src/n_ary_expression_node.cpp +++ b/poincare/src/n_ary_expression_node.cpp @@ -28,8 +28,8 @@ void NAryExpressionNode::sortChildrenInPlace(ExpressionOrder order, bool canBeIn } } -bool NAryExpressionNode::isReal(Context & context, Preferences::AngleUnit angleUnit) const { - return NAryExpression(this).allChildrenAreReal(context, angleUnit) == 1; +bool NAryExpressionNode::isReal(Context & context) const { + return NAryExpression(this).allChildrenAreReal(context) == 1; } Expression NAryExpressionNode::squashUnaryHierarchyInPlace() { @@ -80,14 +80,14 @@ int NAryExpressionNode::simplificationOrderGreaterType(const ExpressionNode * e, return 0; } -int NAryExpression::allChildrenAreReal(Context & context, Preferences::AngleUnit angleUnit) const { +int NAryExpression::allChildrenAreReal(Context & context) const { int i = 0; int result = 1; while (i < numberOfChildren()) { Expression c = childAtIndex(i); if (c.type() == ExpressionNode::Type::ComplexCartesian) { result *= 0; - } else if (!c.isReal(context, angleUnit)) { + } else if (!c.isReal(context)) { return -1; } i++; diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index 3b65c047f..5edd341fe 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -19,14 +19,14 @@ int OppositeNode::polynomialDegree(Context & context, const char * symbolName) c return childAtIndex(0)->polynomialDegree(context, symbolName); } -ExpressionNode::Sign OppositeNode::sign(Context * context, Preferences::AngleUnit angleUnit) const { - if (childAtIndex(0)->sign(context, angleUnit) == Sign::Positive) { +ExpressionNode::Sign OppositeNode::sign(Context * context) const { + if (childAtIndex(0)->sign(context) == Sign::Positive) { return Sign::Negative; } - if (childAtIndex(0)->sign(context, angleUnit) == Sign::Negative) { + if (childAtIndex(0)->sign(context) == Sign::Negative) { return Sign::Positive; } - return ExpressionNode::sign(context,angleUnit); + return ExpressionNode::sign(context); } /* Layout */ diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 726d030a0..1baf6d147 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -26,14 +26,14 @@ namespace Poincare { // Properties -ExpressionNode::Sign PowerNode::sign(Context * context, Preferences::AngleUnit angleUnit) const { +ExpressionNode::Sign PowerNode::sign(Context * context) const { if (Expression::shouldStopProcessing()) { return Sign::Unknown; } - if (childAtIndex(0)->sign(context, angleUnit) == Sign::Positive && childAtIndex(1)->sign(context, angleUnit) != Sign::Unknown) { + if (childAtIndex(0)->sign(context) == Sign::Positive && childAtIndex(1)->sign(context) != Sign::Unknown) { return Sign::Positive; } - if (childAtIndex(0)->sign(context, angleUnit) == Sign::Negative && childAtIndex(1)->type() == ExpressionNode::Type::Rational) { + if (childAtIndex(0)->sign(context) == Sign::Negative && childAtIndex(1)->type() == ExpressionNode::Type::Rational) { RationalNode * r = static_cast(childAtIndex(1)); if (r->denominator().isOne()) { assert(!Integer::Division(r->signedNumerator(), Integer(2)).remainder.isInfinity()); @@ -79,15 +79,15 @@ int PowerNode::getPolynomialCoefficients(Context & context, const char * symbolN return Power(this).getPolynomialCoefficients(context, symbolName, coefficients); } -bool PowerNode::isReal(Context & context, Preferences::AngleUnit angleUnit) const { +bool PowerNode::isReal(Context & context) const { ExpressionNode * base = childAtIndex(0); ExpressionNode * index = childAtIndex(1); // Both base and index are real and: // - either base > 0 // - or index is an integer - if (base->isReal(context, angleUnit) && - index->isReal(context, angleUnit) && - (base->sign(&context, angleUnit) == Sign::Positive || + if (base->isReal(context) && + index->isReal(context) && + (base->sign(&context) == Sign::Positive || (index->type() == ExpressionNode::Type::Rational && static_cast(index)->denominator().isOne()))) { return true; } @@ -240,7 +240,7 @@ Power::Power(Expression base, Expression exponent) : Expression(TreePool::shared Expression Power::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { assert(s == ExpressionNode::Sign::Positive); - if (childAtIndex(0).sign(context, angleUnit) == ExpressionNode::Sign::Negative) { + if (childAtIndex(0).sign(context) == ExpressionNode::Sign::Negative) { Expression result = Power(childAtIndex(0).setSign(ExpressionNode::Sign::Positive, context, angleUnit, target), childAtIndex(1)); replaceWithInPlace(result); return result.shallowReduce(*context, angleUnit, target); @@ -334,7 +334,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU Expression base = childAtIndex(0); Expression index = childAtIndex(1); /* Step 0: if both children are true unresolved complexes, the result is not simplified. TODO? */ - if (!base.isReal(context, angleUnit) && base.type() != ExpressionNode::Type::ComplexCartesian && !index.isReal(context, angleUnit) && index.type() != ExpressionNode::Type::ComplexCartesian) { + if (!base.isReal(context) && base.type() != ExpressionNode::Type::ComplexCartesian && !index.isReal(context) && index.type() != ExpressionNode::Type::ComplexCartesian) { return *this; } @@ -374,12 +374,12 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU Rational a = childAtIndex(0).convert(); // 0^x if (a.isZero()) { - if (childAtIndex(1).sign(&context, angleUnit) == ExpressionNode::Sign::Positive) { + if (childAtIndex(1).sign(&context) == ExpressionNode::Sign::Positive) { Expression result = Rational(0); replaceWithInPlace(result); return result; } - if (childAtIndex(1).sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { + if (childAtIndex(1).sign(&context) == ExpressionNode::Sign::Negative) { Expression result = Undefined(); replaceWithInPlace(result); return result; @@ -443,8 +443,8 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU } } // All other cases where one child at least is a ComplexCartesian - if ((!letPowerAtRoot && base.isReal(context, angleUnit) && index.type() == ExpressionNode::Type::ComplexCartesian) || - (!letPowerAtRoot && base.type() == ExpressionNode::Type::ComplexCartesian && index.isReal(context, angleUnit)) || + if ((!letPowerAtRoot && base.isReal(context) && index.type() == ExpressionNode::Type::ComplexCartesian) || + (!letPowerAtRoot && base.type() == ExpressionNode::Type::ComplexCartesian && index.isReal(context)) || (!letPowerAtRoot && base.type() == ExpressionNode::Type::ComplexCartesian && index.type() == ExpressionNode::Type::ComplexCartesian)) { complexBase = base.type() == ExpressionNode::Type::ComplexCartesian ? static_cast(base) : ComplexCartesian::Builder(base, Rational(0)); complexIndex = index.type() == ExpressionNode::Type::ComplexCartesian ? static_cast(index) : ComplexCartesian::Builder(index, Rational(0)); @@ -477,13 +477,13 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU // Step 5: (±inf)^x = 0 or ±inf if (childAtIndex(0).type() == ExpressionNode::Type::Infinity) { Expression result; - if (childAtIndex(1).sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { + if (childAtIndex(1).sign(&context) == ExpressionNode::Sign::Negative) { // --> 0 if x < 0 result = Rational(0); - } else if (childAtIndex(1).sign(&context, angleUnit) == ExpressionNode::Sign::Positive) { + } else if (childAtIndex(1).sign(&context) == ExpressionNode::Sign::Positive) { // --> (±inf) if x > 0 result = Infinity(false); - if (childAtIndex(0).sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { + if (childAtIndex(0).sign(&context) == ExpressionNode::Sign::Negative) { // (-inf)^x --> (-1)^x*inf Power p(Rational(-1), childAtIndex(1)); result = Multiplication(p, result); @@ -512,7 +512,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU // Step 7: (a)^(1/2) with a < 0 --> i*(-a)^(1/2) // WARNING: this rule true only if a real (ex: (-1*i)^(1/2) != i*i^(1/2) if (!letPowerAtRoot - && childAtIndex(0).isReal(context, angleUnit) + && childAtIndex(0).isReal(context) && childAtIndex(1).type() == ExpressionNode::Type::Rational && childAtIndex(1).convert().isHalf()) { @@ -554,7 +554,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU if (childAtIndex(1).type() == ExpressionNode::Type::Logarithm) { if (childAtIndex(1).numberOfChildren() == 2 && childAtIndex(0).isIdenticalTo(childAtIndex(1).childAtIndex(1))) { // y > 0 - if (childAtIndex(1).childAtIndex(0).sign(&context, angleUnit) == ExpressionNode::Sign::Positive) { + if (childAtIndex(1).childAtIndex(0).sign(&context) == ExpressionNode::Sign::Positive) { Expression result = childAtIndex(1).childAtIndex(0); replaceWithInPlace(result); return result; @@ -574,7 +574,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU if (childAtIndex(0).type() == ExpressionNode::Type::Power) { Power p = childAtIndex(0).convert(); // Check if a > 0 or c is Integer - if (p.childAtIndex(0).sign(&context, angleUnit) == ExpressionNode::Sign::Positive + if (p.childAtIndex(0).sign(&context) == ExpressionNode::Sign::Positive || (childAtIndex(1).type() == ExpressionNode::Type::Rational && childAtIndex(1).convert().integerDenominator().isOne())) { @@ -591,7 +591,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU // Case 2: (a*b*...)^r -> |a|^r*(sign(a)*b*...)^r if a not -1 for (int i = 0; i < m.numberOfChildren(); i++) { // a is signed and a != -1 - if (m.childAtIndex(i).sign(&context, angleUnit) != ExpressionNode::Sign::Unknown + if (m.childAtIndex(i).sign(&context) != ExpressionNode::Sign::Unknown && (m.childAtIndex(i).type() != ExpressionNode::Type::Rational || !m.childAtIndex(i).convert().isMinusOne())) { @@ -600,7 +600,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU Expression factor = m.childAtIndex(i); // (sign(a)*b*...)^r - if (factor.sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { + if (factor.sign(&context) == ExpressionNode::Sign::Negative) { m.replaceChildAtIndexInPlace(i, Rational(-1)); factor = factor.setSign(ExpressionNode::Sign::Positive, &context, angleUnit, target); } else { @@ -734,7 +734,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU a->addOperand(m); m->shallowReduce(context, angleUnit, target); } - if (nr->sign(&context, angleUnit) == Sign::Negative) { + if (nr->sign(&context) == Sign::Negative) { nr->replaceWith(new Rational(-1), true); childAtIndex(0)->replaceWith(a, true)->shallowReduce(context, angleUnit, target); return shallowReduce(context, angleUnit, target); diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index dd76bde78..48fb40659 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -247,7 +247,7 @@ Expression Rational::shallowReduce(Context & context, Preferences::AngleUnit ang // Turn into Infinite if the numerator is too big. if (unsignedIntegerNumerator().isInfinity()) { assert(false); - return Infinity(sign(&context, angleUnit) == ExpressionNode::Sign::Negative); + return Infinity(sign(&context) == ExpressionNode::Sign::Negative); } // Turn into 0 if the denominator is too big. if (integerDenominator().isInfinity()) { diff --git a/poincare/src/real_part.cpp b/poincare/src/real_part.cpp index cf5254634..0458f0038 100644 --- a/poincare/src/real_part.cpp +++ b/poincare/src/real_part.cpp @@ -37,7 +37,7 @@ Expression RealPart::shallowReduce(Context & context, Preferences::AngleUnit ang return SimplificationHelper::Map(*this, context, angleUnit); } #endif - if (c.isReal(context, angleUnit)) { + if (c.isReal(context)) { replaceWithInPlace(c); return c; } diff --git a/poincare/src/sign_function.cpp b/poincare/src/sign_function.cpp index 99a691044..88867021c 100644 --- a/poincare/src/sign_function.cpp +++ b/poincare/src/sign_function.cpp @@ -13,8 +13,8 @@ constexpr Expression::FunctionHelper SignFunction::s_functionHelper; int SignFunctionNode::numberOfChildren() const { return SignFunction::s_functionHelper.numberOfChildren(); } -ExpressionNode::Sign SignFunctionNode::sign(Context * context, Preferences::AngleUnit angleUnit) const { - return childAtIndex(0)->sign(context, angleUnit); +ExpressionNode::Sign SignFunctionNode::sign(Context * context) const { + return childAtIndex(0)->sign(context); } Expression SignFunctionNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) { @@ -61,7 +61,7 @@ Expression SignFunction::shallowReduce(Context & context, Preferences::AngleUnit #endif Rational one(1); Expression child = childAtIndex(0); - ExpressionNode::Sign s = child.sign(&context, angleUnit); + ExpressionNode::Sign s = child.sign(&context); if (s != ExpressionNode::Sign::Unknown) { if (s == ExpressionNode::Sign::Negative) { one = Rational(-1); diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index c4746ba5c..7fe6e3e06 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -15,14 +15,6 @@ namespace Poincare { constexpr char Symbol::k_ans[]; -/*ExpressionNode::Sign SymbolNode::sign(Context * context, Preferences::AngleUnit angleUnit) const { - TODO: Maybe, we will want to know that from a context given in parameter: - if (context.expressionForSymbol(this, false) != nullptr) { - return context.expressionForSymbol(this, false)->sign(context); - } -} -*/ - Expression SymbolNode::replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression) { return Symbol(this).replaceSymbolWithExpression(symbol, expression); } @@ -77,9 +69,9 @@ float SymbolNode::characteristicXRange(Context & context, Preferences::AngleUnit return 0.0f; } -bool SymbolNode::isReal(Context & context, Preferences::AngleUnit angleUnit) const { +bool SymbolNode::isReal(Context & context) const { Symbol s(this); - return SymbolAbstract::isReal(s, context, angleUnit); + return SymbolAbstract::isReal(s, context); } Layout SymbolNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { diff --git a/poincare/src/symbol_abstract.cpp b/poincare/src/symbol_abstract.cpp index 0dab4e75b..91eedcf46 100644 --- a/poincare/src/symbol_abstract.cpp +++ b/poincare/src/symbol_abstract.cpp @@ -28,13 +28,13 @@ void SymbolAbstractNode::initToMatchSize(size_t goalSize) { assert(size() == goalSize); } -ExpressionNode::Sign SymbolAbstractNode::sign(Context * context, Preferences::AngleUnit angleUnit) const { +ExpressionNode::Sign SymbolAbstractNode::sign(Context * context) const { SymbolAbstract s(this); Expression e = SymbolAbstract::Expand(s, *context, false); if (e.isUninitialized()) { return Sign::Unknown; } - return e.sign(context, angleUnit); + return e.sign(context); } Expression SymbolAbstractNode::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) { @@ -79,12 +79,12 @@ Expression SymbolAbstract::Expand(const SymbolAbstract & symbol, Context & conte return e; } -bool SymbolAbstract::isReal(const SymbolAbstract & symbol, Context & context, Preferences::AngleUnit angleUnit) { +bool SymbolAbstract::isReal(const SymbolAbstract & symbol, Context & context) { Expression e = SymbolAbstract::Expand(symbol, context, false); if (e.isUninitialized()) { return true; } - return e.isReal(context, angleUnit); + return e.isReal(context); } /* TreePool uses adresses and sizes that are multiples of 4 in order to make diff --git a/poincare/test/properties.cpp b/poincare/test/properties.cpp index eedcfe6e6..b5ac572d8 100644 --- a/poincare/test/properties.cpp +++ b/poincare/test/properties.cpp @@ -16,7 +16,7 @@ void assert_parsed_expression_sign(const char * expression, Poincare::Expression Expression e = parse_expression(expression); quiz_assert(!e.isUninitialized()); e = e.reduce(globalContext, Degree); - quiz_assert(e.sign(&globalContext, Degree) == sign); + quiz_assert(e.sign(&globalContext) == sign); } QUIZ_CASE(poincare_sign) { From 26e2e9be0d954883aa6732e17b79d09fd9e0fbea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 21 Dec 2018 16:18:15 +0100 Subject: [PATCH 138/373] [poincare] Add complex format as an argument of simplification --- apps/calculation/calculation.cpp | 2 +- apps/shared/poincare_helpers.h | 22 ++- apps/solver/equation.cpp | 3 +- apps/solver/equation_store.cpp | 22 ++- apps/solver/equation_store.h | 1 + poincare/include/poincare/absolute_value.h | 8 +- poincare/include/poincare/addition.h | 12 +- poincare/include/poincare/arc_cosine.h | 4 +- poincare/include/poincare/arc_sine.h | 4 +- poincare/include/poincare/arc_tangent.h | 4 +- .../include/poincare/binomial_coefficient.h | 4 +- poincare/include/poincare/ceiling.h | 4 +- poincare/include/poincare/complex_argument.h | 4 +- poincare/include/poincare/complex_cartesian.h | 30 +-- .../include/poincare/confidence_interval.h | 4 +- poincare/include/poincare/conjugate.h | 4 +- poincare/include/poincare/constant.h | 4 +- poincare/include/poincare/cosine.h | 4 +- poincare/include/poincare/decimal.h | 10 +- poincare/include/poincare/derivative.h | 4 +- poincare/include/poincare/determinant.h | 4 +- poincare/include/poincare/division.h | 4 +- poincare/include/poincare/division_quotient.h | 4 +- .../include/poincare/division_remainder.h | 4 +- poincare/include/poincare/equal.h | 6 +- poincare/include/poincare/expression.h | 46 ++--- poincare/include/poincare/expression_node.h | 10 +- poincare/include/poincare/factor.h | 6 +- poincare/include/poincare/factorial.h | 10 +- poincare/include/poincare/float.h | 2 +- poincare/include/poincare/floor.h | 4 +- poincare/include/poincare/frac_part.h | 4 +- poincare/include/poincare/function.h | 4 +- .../include/poincare/great_common_divisor.h | 4 +- .../hyperbolic_trigonometric_function.h | 4 +- poincare/include/poincare/imaginary_part.h | 4 +- poincare/include/poincare/infinity.h | 4 +- poincare/include/poincare/integral.h | 4 +- .../include/poincare/least_common_multiple.h | 4 +- poincare/include/poincare/logarithm.h | 14 +- poincare/include/poincare/matrix.h | 6 +- poincare/include/poincare/matrix_dimension.h | 4 +- poincare/include/poincare/matrix_inverse.h | 4 +- poincare/include/poincare/matrix_trace.h | 4 +- poincare/include/poincare/matrix_transpose.h | 4 +- poincare/include/poincare/multiplication.h | 32 +-- .../include/poincare/naperian_logarithm.h | 4 +- poincare/include/poincare/nth_root.h | 4 +- poincare/include/poincare/number.h | 2 +- poincare/include/poincare/opposite.h | 4 +- poincare/include/poincare/parenthesis.h | 4 +- .../include/poincare/permute_coefficient.h | 4 +- poincare/include/poincare/power.h | 28 +-- .../include/poincare/prediction_interval.h | 4 +- poincare/include/poincare/random.h | 4 +- poincare/include/poincare/rational.h | 14 +- poincare/include/poincare/real_part.h | 4 +- poincare/include/poincare/round.h | 4 +- poincare/include/poincare/sign_function.h | 6 +- poincare/include/poincare/sine.h | 4 +- poincare/include/poincare/square_root.h | 4 +- poincare/include/poincare/store.h | 6 +- poincare/include/poincare/subtraction.h | 4 +- poincare/include/poincare/symbol.h | 4 +- poincare/include/poincare/symbol_abstract.h | 2 +- poincare/include/poincare/tangent.h | 4 +- poincare/include/poincare/trigonometry.h | 6 +- poincare/include/poincare/undefined.h | 2 +- poincare/src/absolute_value.cpp | 22 +-- poincare/src/addition.cpp | 50 ++--- poincare/src/arc_cosine.cpp | 10 +- poincare/src/arc_sine.cpp | 10 +- poincare/src/arc_tangent.cpp | 10 +- poincare/src/binomial_coefficient.cpp | 8 +- poincare/src/ceiling.cpp | 8 +- poincare/src/complex_argument.cpp | 12 +- poincare/src/complex_cartesian.cpp | 182 +++++++++--------- poincare/src/confidence_interval.cpp | 10 +- poincare/src/conjugate.cpp | 10 +- poincare/src/constant.cpp | 6 +- poincare/src/cosine.cpp | 10 +- poincare/src/decimal.cpp | 16 +- poincare/src/derivative.cpp | 8 +- poincare/src/determinant.cpp | 8 +- poincare/src/division.cpp | 12 +- poincare/src/division_quotient.cpp | 8 +- poincare/src/division_remainder.cpp | 8 +- poincare/src/equal.cpp | 12 +- poincare/src/expression.cpp | 120 +++++++----- poincare/src/expression_node.cpp | 16 +- poincare/src/factor.cpp | 12 +- poincare/src/factorial.cpp | 16 +- poincare/src/float.cpp | 2 +- poincare/src/floor.cpp | 8 +- poincare/src/frac_part.cpp | 8 +- poincare/src/function.cpp | 8 +- poincare/src/great_common_divisor.cpp | 8 +- .../src/hyperbolic_trigonometric_function.cpp | 8 +- poincare/src/imaginary_part.cpp | 10 +- poincare/src/infinity.cpp | 6 +- poincare/src/integral.cpp | 8 +- poincare/src/least_common_multiple.cpp | 8 +- poincare/src/logarithm.cpp | 54 +++--- poincare/src/matrix.cpp | 18 +- poincare/src/matrix_dimension.cpp | 8 +- poincare/src/matrix_inverse.cpp | 12 +- poincare/src/matrix_trace.cpp | 10 +- poincare/src/matrix_transpose.cpp | 8 +- poincare/src/multiplication.cpp | 122 ++++++------ poincare/src/naperian_logarithm.cpp | 10 +- poincare/src/nth_root.cpp | 12 +- poincare/src/opposite.cpp | 10 +- poincare/src/parenthesis.cpp | 8 +- poincare/src/permute_coefficient.cpp | 8 +- poincare/src/power.cpp | 182 +++++++++--------- poincare/src/prediction_interval.cpp | 10 +- poincare/src/random.cpp | 6 +- poincare/src/rational.cpp | 20 +- poincare/src/real_part.cpp | 10 +- poincare/src/round.cpp | 8 +- poincare/src/sign_function.cpp | 12 +- poincare/src/simplification_helper.cpp | 6 +- poincare/src/sine.cpp | 10 +- poincare/src/square_root.cpp | 10 +- poincare/src/store.cpp | 8 +- poincare/src/subtraction.cpp | 12 +- poincare/src/symbol.cpp | 8 +- poincare/src/symbol_abstract.cpp | 4 +- poincare/src/tangent.cpp | 16 +- poincare/src/trigonometry.cpp | 62 +++--- poincare/src/undefined.cpp | 2 +- poincare/test/float.cpp | 2 +- poincare/test/helper.cpp | 24 +-- poincare/test/helper.h | 3 +- poincare/test/layouts.cpp | 4 +- poincare/test/properties.cpp | 18 +- 136 files changed, 943 insertions(+), 908 deletions(-) diff --git a/apps/calculation/calculation.cpp b/apps/calculation/calculation.cpp index a88ec8c4b..c37502501 100644 --- a/apps/calculation/calculation.cpp +++ b/apps/calculation/calculation.cpp @@ -186,7 +186,7 @@ Calculation::EqualSign Calculation::exactAndApproximateDisplayedOutputsAreEqual( if (exactOutputExpression.isUninitialized()) { exactOutputExpression = Undefined(); } - m_equalSign = exactOutputExpression.isEqualToItsApproximationLayout(approximateOutput(context), buffer, bufferSize, preferences->angleUnit(), preferences->displayMode(), preferences->numberOfSignificantDigits(), *context) ? EqualSign::Equal : EqualSign::Approximation; + m_equalSign = exactOutputExpression.isEqualToItsApproximationLayout(approximateOutput(context), buffer, bufferSize, preferences->complexFormat(), preferences->angleUnit(), preferences->displayMode(), preferences->numberOfSignificantDigits(), *context) ? EqualSign::Equal : EqualSign::Approximation; return m_equalSign; } diff --git a/apps/shared/poincare_helpers.h b/apps/shared/poincare_helpers.h index b666dd159..eb4162dcb 100644 --- a/apps/shared/poincare_helpers.h +++ b/apps/shared/poincare_helpers.h @@ -24,7 +24,9 @@ inline int Serialize(const Poincare::Expression e, char * buffer, int bufferSize template inline Poincare::Expression Approximate(const Poincare::Expression e, Poincare::Context & context) { - return e.approximate(context, Poincare::Preferences::sharedPreferences()->angleUnit(), Poincare::Preferences::sharedPreferences()->complexFormat()); + Poincare::Preferences::ComplexFormat complexFormat = Poincare::Preferences::sharedPreferences()->complexFormat(); + complexFormat = Poincare::Expression::UpdatedComplexFormatWithExpressionInput(complexFormat, e, context); + return e.approximate(context, complexFormat, Poincare::Preferences::sharedPreferences()->angleUnit()); } template @@ -34,23 +36,27 @@ inline T ApproximateToScalar(const Poincare::Expression e, Poincare::Context & c template inline T ApproximateToScalar(const char * text, Poincare::Context & context) { - return Poincare::Expression::approximateToScalar(text, context, Poincare::Preferences::sharedPreferences()->angleUnit()); + Poincare::Preferences::ComplexFormat complexFormat = Poincare::Preferences::sharedPreferences()->complexFormat(); + complexFormat = Poincare::Expression::UpdatedComplexFormatWithTextInput(complexFormat, text); + return Poincare::Expression::approximateToScalar(text, context, complexFormat, Poincare::Preferences::sharedPreferences()->angleUnit()); } inline Poincare::Expression ParseAndSimplify(const char * text, Poincare::Context & context) { - return Poincare::Expression::ParseAndSimplify(text, context, Poincare::Preferences::sharedPreferences()->angleUnit()); + return Poincare::Expression::ParseAndSimplify(text, context, Poincare::Preferences::sharedPreferences()->complexFormat(), Poincare::Preferences::sharedPreferences()->angleUnit()); } -inline void Simplify(Poincare::Expression * e, Poincare::Context & context) { - *e = e->simplify(context, Poincare::Preferences::sharedPreferences()->angleUnit()); +inline void Simplify(Poincare::Expression * e, Poincare::Context & context, Poincare::Preferences::ComplexFormat complexFormat = Poincare::Preferences::sharedPreferences()->complexFormat()) { + complexFormat = Poincare::Expression::UpdatedComplexFormatWithExpressionInput(complexFormat, *e, context); + *e = e->simplify(context, complexFormat, Poincare::Preferences::sharedPreferences()->angleUnit()); } inline void ParseAndSimplifyAndApproximate(const char * text, Poincare::Expression * simplifiedExpression, Poincare::Expression * approximateExpression, Poincare::Context & context) { - Poincare::Expression::ParseAndSimplifyAndApproximate(text, simplifiedExpression, approximateExpression, context, Poincare::Preferences::sharedPreferences()->angleUnit(), Poincare::Preferences::sharedPreferences()->complexFormat()); + Poincare::Expression::ParseAndSimplifyAndApproximate(text, simplifiedExpression, approximateExpression, context, Poincare::Preferences::sharedPreferences()->complexFormat(), Poincare::Preferences::sharedPreferences()->angleUnit()); } -inline void SimplifyAndApproximate(Poincare::Expression * e, Poincare::Expression * approximate, Poincare::Context & context) { - e->simplifyAndApproximate(e, approximate, context, Poincare::Preferences::sharedPreferences()->angleUnit(), Poincare::Preferences::sharedPreferences()->complexFormat()); +inline void SimplifyAndApproximate(Poincare::Expression * e, Poincare::Expression * approximate, Poincare::Context & context, Poincare::Preferences::ComplexFormat complexFormat = Poincare::Preferences::sharedPreferences()->complexFormat()) { + complexFormat = Poincare::Expression::UpdatedComplexFormatWithExpressionInput(complexFormat, *e, context); + e->simplifyAndApproximate(e, approximate, context, complexFormat, Poincare::Preferences::sharedPreferences()->angleUnit()); } } diff --git a/apps/solver/equation.cpp b/apps/solver/equation.cpp index 7a19ab32d..8032a9824 100644 --- a/apps/solver/equation.cpp +++ b/apps/solver/equation.cpp @@ -33,7 +33,8 @@ Expression Equation::standardForm(Context * context) const { return m_standardForm; } if (e.type() == ExpressionNode::Type::Equal) { - m_standardForm = static_cast(e).standardEquation(*context, Preferences::sharedPreferences()->angleUnit()); + Preferences * preferences = Preferences::sharedPreferences(); + m_standardForm = static_cast(e).standardEquation(*context, Expression::UpdatedComplexFormatWithTextInput(preferences->complexFormat(), text()), preferences->angleUnit()); } else { assert(e.type() == ExpressionNode::Type::Rational && static_cast(e).isOne()); // The equality was reduced which means the equality was always true. diff --git a/apps/solver/equation_store.cpp b/apps/solver/equation_store.cpp index dc5e8c251..708837b4d 100644 --- a/apps/solver/equation_store.cpp +++ b/apps/solver/equation_store.cpp @@ -126,7 +126,7 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) { bool isLinear = true; // Invalid the linear system if one equation is non-linear Preferences * preferences = Preferences::sharedPreferences(); for (int i = 0; i < numberOfDefinedModels(); i++) { - isLinear = isLinear && definedModelAtIndex(i)->standardForm(context).getLinearCoefficients((char *)m_variables, Poincare::SymbolAbstract::k_maxNameSize, coefficients[i], &constants[i], *context, preferences->angleUnit()); + isLinear = isLinear && definedModelAtIndex(i)->standardForm(context).getLinearCoefficients((char *)m_variables, Poincare::SymbolAbstract::k_maxNameSize, coefficients[i], &constants[i], *context, updatedComplexFormat(), preferences->angleUnit()); if (!isLinear) { // TODO: should we clean pool allocated memory if the system is not linear #if 0 @@ -157,7 +157,7 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) { /* 2- Polynomial & Monovariable? */ assert(numberOfVariables == 1 && numberOfDefinedModels() == 1); Expression polynomialCoefficients[Expression::k_maxNumberOfPolynomialCoefficients]; - int degree = definedModelAtIndex(0)->standardForm(context).getPolynomialReducedCoefficients(m_variables[0], polynomialCoefficients, *context, preferences->angleUnit()); + int degree = definedModelAtIndex(0)->standardForm(context).getPolynomialReducedCoefficients(m_variables[0], polynomialCoefficients, *context, updatedComplexFormat(), preferences->angleUnit()); if (degree == 2) { /* Polynomial degree <= 2*/ m_type = Type::PolynomialMonovariable; @@ -201,7 +201,7 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) { /* Check for equality between exact and approximate layouts */ if (!m_exactSolutionIdentity[solutionIndex]) { char buffer[Shared::ExpressionModel::k_expressionBufferSize]; - m_exactSolutionEquality[solutionIndex] = exactSolutions[i].isEqualToItsApproximationLayout(exactSolutionsApproximations[i], buffer, Shared::ExpressionModel::k_expressionBufferSize, preferences->angleUnit(), preferences->displayMode(), preferences->numberOfSignificantDigits(), *context); + m_exactSolutionEquality[solutionIndex] = exactSolutions[i].isEqualToItsApproximationLayout(exactSolutionsApproximations[i], buffer, Shared::ExpressionModel::k_expressionBufferSize, preferences->complexFormat(), preferences->angleUnit(), preferences->displayMode(), preferences->numberOfSignificantDigits(), *context); } solutionIndex++; } @@ -226,7 +226,7 @@ EquationStore::Error EquationStore::resolveLinearSystem(Expression exactSolution Ab.setDimensions(m, n+1); // Compute the rank of (A | b) - int rankAb = Ab.rank(*context, angleUnit, true); + int rankAb = Ab.rank(*context, updatedComplexFormat(), angleUnit, true); // Initialize the number of solutions m_numberOfSolutions = INT_MAX; @@ -251,7 +251,7 @@ EquationStore::Error EquationStore::resolveLinearSystem(Expression exactSolution m_numberOfSolutions = n; for (int i = 0; i < m_numberOfSolutions; i++) { exactSolutions[i] = Ab.matrixChild(i,n); - PoincareHelpers::SimplifyAndApproximate(&exactSolutions[i], &exactSolutionsApproximations[i], *context); + PoincareHelpers::SimplifyAndApproximate(&exactSolutions[i], &exactSolutionsApproximations[i], *context, updatedComplexFormat()); } } } @@ -263,7 +263,7 @@ EquationStore::Error EquationStore::oneDimensialPolynomialSolve(Expression exact assert(degree == 2); // Compute delta = b*b-4ac Expression delta = Subtraction(Power(coefficients[1].clone(), Rational(2)), Multiplication(Rational(4), coefficients[0].clone(), coefficients[2].clone())); - PoincareHelpers::Simplify(&delta, *context); + PoincareHelpers::Simplify(&delta, *context, updatedComplexFormat()); if (delta.isUninitialized()) { delta = Poincare::Undefined(); } @@ -280,7 +280,7 @@ EquationStore::Error EquationStore::oneDimensialPolynomialSolve(Expression exact } exactSolutions[m_numberOfSolutions] = delta; for (int i = 0; i <= m_numberOfSolutions; i++) { - PoincareHelpers::SimplifyAndApproximate(&exactSolutions[i], &exactSolutionsApproximations[i], *context); + PoincareHelpers::SimplifyAndApproximate(&exactSolutions[i], &exactSolutionsApproximations[i], *context, updatedComplexFormat()); } return Error::NoError; #if 0 @@ -356,6 +356,14 @@ void EquationStore::tidySolution() { } } +Preferences::ComplexFormat EquationStore::updatedComplexFormat() { + Preferences::ComplexFormat complexFormat = Preferences::sharedPreferences()->complexFormat(); + if (complexFormat == Preferences::ComplexFormat::Real && isExplictlyComplex()) { + return Preferences::ComplexFormat::Cartesian; + } + return complexFormat; +} + bool EquationStore::isExplictlyComplex() { for (int i = 0; i < numberOfDefinedModels(); i++) { if (definedModelAtIndex(i)->containsIComplex()) { diff --git a/apps/solver/equation_store.h b/apps/solver/equation_store.h index bbce1439d..be4d91ff2 100644 --- a/apps/solver/equation_store.h +++ b/apps/solver/equation_store.h @@ -83,6 +83,7 @@ private: Error oneDimensialPolynomialSolve(Poincare::Expression solutions[k_maxNumberOfExactSolutions], Poincare::Expression solutionApproximations[k_maxNumberOfExactSolutions], Poincare::Expression polynomialCoefficients[Poincare::Expression::k_maxNumberOfPolynomialCoefficients], int degree, Poincare::Context * context); void tidySolution(); bool isExplictlyComplex(); + Poincare::Preferences::ComplexFormat updatedComplexFormat(); Equation m_equations[k_maxNumberOfEquations]; Type m_type; diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 78ae396f7..f58d45944 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -21,7 +21,7 @@ public: // Properties Type type() const override { return Type::AbsoluteValue; } Sign sign(Context * context) const override { return Sign::Positive; } - Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Complex bool isReal(Context & context) const override { return true; } @@ -42,7 +42,7 @@ public: int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; }; class AbsoluteValue final : public Expression { @@ -53,12 +53,12 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("abs", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit AbsoluteValue(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); } - Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit); + Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); }; } diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index ca822b7a5..3b48de687 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -42,8 +42,8 @@ private: int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; - Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) override; /* Evaluation */ template static MatrixComplex computeOnMatrixAndComplex(const MatrixComplex m, const std::complex c) { @@ -74,8 +74,8 @@ public: } } // Expression - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const; private: static const Number NumeralFactor(const Expression & e); @@ -83,8 +83,8 @@ private: static inline const Expression FirstNonNumeralFactor(const Expression & e); static bool TermsHaveIdenticalNonNumeralFactors(const Expression & e1, const Expression & e2); - Expression factorizeOnCommonDenominator(Context & context, Preferences::AngleUnit angleUnit); - void factorizeChildrenAtIndexesInPlace(int index1, int index2, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression factorizeOnCommonDenominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + void factorizeChildrenAtIndexesInPlace(int index1, int index2, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); AdditionNode * node() const { return static_cast(Expression::node()); } }; diff --git a/poincare/include/poincare/arc_cosine.h b/poincare/include/poincare/arc_cosine.h index ac84719cb..0a73494a2 100644 --- a/poincare/include/poincare/arc_cosine.h +++ b/poincare/include/poincare/arc_cosine.h @@ -27,7 +27,7 @@ private: int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; //Evaluation template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { @@ -45,7 +45,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("acos", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit ArcCosine(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/arc_sine.h b/poincare/include/poincare/arc_sine.h index 1a0928e86..77a2c9ab8 100644 --- a/poincare/include/poincare/arc_sine.h +++ b/poincare/include/poincare/arc_sine.h @@ -26,7 +26,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; //Evaluation template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { @@ -44,7 +44,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("asin", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit ArcSine(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/arc_tangent.h b/poincare/include/poincare/arc_tangent.h index 2f420652b..71fff6a69 100644 --- a/poincare/include/poincare/arc_tangent.h +++ b/poincare/include/poincare/arc_tangent.h @@ -30,7 +30,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; //Evaluation template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { @@ -48,7 +48,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("atan", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit ArcTangent(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/binomial_coefficient.h b/poincare/include/poincare/binomial_coefficient.h index e6d045226..0587257cf 100644 --- a/poincare/include/poincare/binomial_coefficient.h +++ b/poincare/include/poincare/binomial_coefficient.h @@ -29,7 +29,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } @@ -44,7 +44,7 @@ public: static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("binomial", 2, &UntypedBuilder); // Expression - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); private: BinomialCoefficient(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child0); diff --git a/poincare/include/poincare/ceiling.h b/poincare/include/poincare/ceiling.h index 24cc2f873..44dafdbdf 100644 --- a/poincare/include/poincare/ceiling.h +++ b/poincare/include/poincare/ceiling.h @@ -28,7 +28,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { @@ -46,7 +46,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("ceil", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); private: explicit Ceiling(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/complex_argument.h b/poincare/include/poincare/complex_argument.h index be92899af..dee7b6aed 100644 --- a/poincare/include/poincare/complex_argument.h +++ b/poincare/include/poincare/complex_argument.h @@ -27,7 +27,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { @@ -45,7 +45,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("arg", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit ComplexArgument(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/complex_cartesian.h b/poincare/include/poincare/complex_cartesian.h index d1ab221b1..324dcf303 100644 --- a/poincare/include/poincare/complex_cartesian.h +++ b/poincare/include/poincare/complex_cartesian.h @@ -27,8 +27,8 @@ private: Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; - Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) override; private: template Complex templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; @@ -46,28 +46,28 @@ public: Expression imag() { return childAtIndex(1); } // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); - Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); // Common operations (done in-place) - Expression squareNorm(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - Expression norm(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - Expression argument(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - ComplexCartesian inverse(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - ComplexCartesian squareRoot(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - ComplexCartesian powerInteger(int n, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - ComplexCartesian multiply(ComplexCartesian & other, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - ComplexCartesian power(ComplexCartesian & other, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression squareNorm(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression norm(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression argument(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + ComplexCartesian inverse(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + ComplexCartesian squareRoot(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + ComplexCartesian powerInteger(int n, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + ComplexCartesian multiply(ComplexCartesian & other, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + ComplexCartesian power(ComplexCartesian & other, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: static constexpr int k_maxNumberOfNodesBeforeInterrupting = 50; ComplexCartesian(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child0); replaceChildAtIndexInPlace(1, child1); } - void factorAndArgumentOfFunction(Expression e, ExpressionNode::Type searchedType, Expression * factor, Expression * argument, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + void factorAndArgumentOfFunction(Expression e, ExpressionNode::Type searchedType, Expression * factor, Expression * argument, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); ComplexCartesian interruptComputationIfManyNodes(); - static Multiplication squareRootHelper(Expression e, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - static Expression powerHelper(Expression norm, Expression trigo, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + static Multiplication squareRootHelper(Expression e, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + static Expression powerHelper(Expression norm, Expression trigo, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); }; diff --git a/poincare/include/poincare/confidence_interval.h b/poincare/include/poincare/confidence_interval.h index 78c526f68..9990c74d2 100644 --- a/poincare/include/poincare/confidence_interval.h +++ b/poincare/include/poincare/confidence_interval.h @@ -27,7 +27,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } @@ -50,7 +50,7 @@ public: static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("confidence", 2, &UntypedBuilder); // Expression - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: ConfidenceInterval(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child0); diff --git a/poincare/include/poincare/conjugate.h b/poincare/include/poincare/conjugate.h index 02907c9b2..8807657cf 100644 --- a/poincare/include/poincare/conjugate.h +++ b/poincare/include/poincare/conjugate.h @@ -27,7 +27,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { @@ -45,7 +45,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("conj", 1, &UntypedBuilder);; - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit Conjugate(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/constant.h b/poincare/include/poincare/constant.h index babaf7339..14e98e29f 100644 --- a/poincare/include/poincare/constant.h +++ b/poincare/include/poincare/constant.h @@ -38,7 +38,7 @@ public: bool isIComplex() const { return isConstantChar(Ion::Charset::IComplex); } // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; private: char m_name[0]; // MUST be the last member variable @@ -58,7 +58,7 @@ public: bool isIComplex() const { return node()->isIComplex(); } // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: ConstantNode * node() const { return static_cast(Expression::node()); } diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index 713f4ad64..bc9e69322 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -33,7 +33,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplication - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return ApproximationHelper::Map(this, context, angleUnit,computeOnComplex); @@ -50,7 +50,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("cos", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit Cosine(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index 1bf27f46e..f86bde4a7 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -48,7 +48,7 @@ public: // Properties Type type() const override { return Type::Decimal; } Sign sign(Context * context) const override { return m_negative ? Sign::Negative : Sign::Positive; } - Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Approximation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { @@ -62,8 +62,8 @@ public: int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; - Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) override; // Serialization int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = 0) const override; @@ -104,8 +104,8 @@ private: Decimal(size_t size, const Integer & m, int e); Expression setSign(ExpressionNode::Sign s); // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); - Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); }; } diff --git a/poincare/include/poincare/derivative.h b/poincare/include/poincare/derivative.h index 2c182c9b2..f22b9b66e 100644 --- a/poincare/include/poincare/derivative.h +++ b/poincare/include/poincare/derivative.h @@ -33,7 +33,7 @@ private: int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } @@ -61,7 +61,7 @@ public: } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("diff", 3, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); private: Derivative(Expression child0, Expression child1, Expression child2) : Expression(TreePool::sharedPool()->createTreeNode()) { assert(child1.type() == ExpressionNode::Type::Symbol); diff --git a/poincare/include/poincare/determinant.h b/poincare/include/poincare/determinant.h index e48c0ffc4..62a36a7bd 100644 --- a/poincare/include/poincare/determinant.h +++ b/poincare/include/poincare/determinant.h @@ -24,7 +24,7 @@ private: /* Serialization */ int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; /* Simplification */ - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; /* Approximation */ Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } @@ -39,7 +39,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("det", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); private: explicit Determinant(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/division.h b/poincare/include/poincare/division.h index 728f514aa..b14b45b4c 100644 --- a/poincare/include/poincare/division.h +++ b/poincare/include/poincare/division.h @@ -46,7 +46,7 @@ public: int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; private: // Approximation @@ -67,7 +67,7 @@ public: } Division(const DivisionNode * n) : Expression(n) {} - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); }; } diff --git a/poincare/include/poincare/division_quotient.h b/poincare/include/poincare/division_quotient.h index 030710664..3849503d5 100644 --- a/poincare/include/poincare/division_quotient.h +++ b/poincare/include/poincare/division_quotient.h @@ -28,7 +28,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } @@ -43,7 +43,7 @@ public: static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("quo", 2, &UntypedBuilder); // Expression - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); private: DivisionQuotient(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child0); diff --git a/poincare/include/poincare/division_remainder.h b/poincare/include/poincare/division_remainder.h index a50d99653..1710553bf 100644 --- a/poincare/include/poincare/division_remainder.h +++ b/poincare/include/poincare/division_remainder.h @@ -29,7 +29,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } @@ -44,7 +44,7 @@ public: static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("rem", 2, &UntypedBuilder); // Expression - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); private: DivisionRemainder(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child0); diff --git a/poincare/include/poincare/equal.h b/poincare/include/poincare/equal.h index cb20d3bf4..0056082ba 100644 --- a/poincare/include/poincare/equal.h +++ b/poincare/include/poincare/equal.h @@ -22,7 +22,7 @@ public: int polynomialDegree(Context & context, const char * symbolName) const override { return -1; } private: // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; @@ -41,9 +41,9 @@ public: } // For the equation A = B, create the reduced expression A-B - Expression standardEquation(Context & context, Preferences::AngleUnit angleUnit) const; + Expression standardEquation(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; // Expression - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); }; } diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index a741f9949..4f8bddee7 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -154,19 +154,21 @@ public: * the variables hold in 'variables'. Otherwise, it fills 'coefficients' with * the coefficients of the variables hold in 'variables' (following the same * order) and 'constant' with the constant of the expression. */ - bool getLinearCoefficients(char * variables, int maxVariableLength, Expression coefficients[], Expression constant[], Context & context, Preferences::AngleUnit angleUnit) const; + bool getLinearCoefficients(char * variables, int maxVariableLength, Expression coefficients[], Expression constant[], Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; /* getPolynomialCoefficients fills the table coefficients with the expressions * of the first 3 polynomial coefficients and returns the polynomial degree. * It is supposed to be called on a reduced expression. * coefficients has up to 3 entries. */ static constexpr int k_maxPolynomialDegree = 2; static constexpr int k_maxNumberOfPolynomialCoefficients = k_maxPolynomialDegree+1; - int getPolynomialReducedCoefficients(const char * symbolName, Expression coefficients[], Context & context, Preferences::AngleUnit angleUnit) const; + int getPolynomialReducedCoefficients(const char * symbolName, Expression coefficients[], Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; Expression replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression) { return node()->replaceSymbolWithExpression(symbol, expression); } Expression replaceUnknown(const Symbol & symbol); Expression defaultReplaceUnknown(const Symbol & symbol); /* Complex */ + static Preferences::ComplexFormat UpdatedComplexFormatWithTextInput(Preferences::ComplexFormat complexFormat, const char * textInput); + static Preferences::ComplexFormat UpdatedComplexFormatWithExpressionInput(Preferences::ComplexFormat complexFormat, const Expression & e, Context & context); bool isReal(Context & context) const { return node()->isReal(context); } /* Comparison */ @@ -174,27 +176,27 @@ public: * same structures and all their nodes have same types and values (ie, * sqrt(pi^2) is NOT identical to pi). */ bool isIdenticalTo(const Expression e) const; - bool isEqualToItsApproximationLayout(Expression approximation, char * buffer, int bufferSize, Preferences::AngleUnit angleUnit, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits, Context & context); + bool isEqualToItsApproximationLayout(Expression approximation, char * buffer, int bufferSize, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits, Context & context); /* Layout Helper */ Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const; /* Simplification */ - static Expression ParseAndSimplify(const char * text, Context & context, Preferences::AngleUnit angleUnit); - static void ParseAndSimplifyAndApproximate(const char * text, Expression * simplifiedExpression, Expression * approximateExpression, Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat); - Expression simplify(Context & context, Preferences::AngleUnit angleUnit); - void simplifyAndApproximate(Expression * simplifiedExpression, Expression * approximateExpression, Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat); - Expression reduce(Context & context, Preferences::AngleUnit angleUnit); + static Expression ParseAndSimplify(const char * text, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + static void ParseAndSimplifyAndApproximate(const char * text, Expression * simplifiedExpression, Expression * approximateExpression, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression simplify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + void simplifyAndApproximate(Expression * simplifiedExpression, Expression * approximateExpression, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression reduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); static Expression ExpressionWithoutSymbols(Expression expressionWithSymbols, Context & context); Expression radianToDegree(); Expression degreeToRadian(); /* Approximation Helper */ template static U epsilon(); - template Expression approximate(Context& context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) const; + template Expression approximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; template U approximateToScalar(Context& context, Preferences::AngleUnit angleUnit) const; - template static U approximateToScalar(const char * text, Context& context, Preferences::AngleUnit angleUnit); + template static U approximateToScalar(const char * text, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); template U approximateWithValueForSymbol(const char * symbol, U x, Context & context, Preferences::AngleUnit angleUnit) const; /* Expression roots/extrema solver */ struct Coordinate2D { @@ -276,24 +278,24 @@ protected: * is reduced (only a numeral factor was potentially made positive, and if it * was -1, it was removed from the multiplication). */ - Expression makePositiveAnyNegativeNumeralFactor(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - Expression denominator(Context & context, Preferences::AngleUnit angleUnit) const { return node()->denominator(context, angleUnit); } - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { return node()->shallowReduce(context, angleUnit, target); } - Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { return node()->shallowBeautify(context, angleUnit); } - Expression deepBeautify(Context & context, Preferences::AngleUnit angleUnit); - Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression makePositiveAnyNegativeNumeralFactor(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { return node()->denominator(context, complexFormat, angleUnit); } + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { return node()->shallowReduce(context, complexFormat, angleUnit, target); } + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { return node()->shallowBeautify(context, complexFormat, angleUnit); } + Expression deepBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: static constexpr int k_maxSymbolReplacementsCount = 10; static bool sSymbolReplacementsCountLock; /* Simplification */ - Expression deepReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - void deepReduceChildren(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { - return node()->deepReduceChildren(context, angleUnit, target); + Expression deepReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + void deepReduceChildren(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + return node()->deepReduceChildren(context, complexFormat, angleUnit, target); } - void defaultDeepReduceChildren(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - Expression defaultShallowReduce(Context & context, Preferences::AngleUnit angleUnit); - Expression defaultShallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { return *this; } + void defaultDeepReduceChildren(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression defaultShallowReduce(); + Expression defaultShallowBeautify() { return *this; } /* Approximation */ template Evaluation approximateToEvaluation(Context& context, Preferences::AngleUnit angleUnit) const; diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index 488c7869b..c5baa792a 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -116,7 +116,7 @@ public: virtual bool isNumber() const { return false; } /*!*/ virtual Expression replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression); /*!*/ virtual Expression replaceUnknown(const Symbol & symbol); - /*!*/ virtual Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target); + /*!*/ virtual Expression setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target); virtual int polynomialDegree(Context & context, const char * symbolName) const; /*!*/ virtual int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const; /*!*/ virtual Expression shallowReplaceReplaceableSymbols(Context & context); @@ -160,11 +160,11 @@ public: virtual Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const = 0; /* Simplification */ - /*!*/ virtual void deepReduceChildren(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target); - /*!*/ virtual Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target); - /*!*/ virtual Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit); + /*!*/ virtual void deepReduceChildren(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target); + /*!*/ virtual Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target); + /*!*/ virtual Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); /* Return a clone of the denominator part of the expression */ - /*!*/ virtual Expression denominator(Context & context, Preferences::AngleUnit angleUnit) const; + /*!*/ virtual Expression denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; /* Hierarchy */ ExpressionNode * childAtIndex(int i) const override { return static_cast(TreeNode::childAtIndex(i)); } diff --git a/poincare/include/poincare/factor.h b/poincare/include/poincare/factor.h index 1663727de..421c6744b 100644 --- a/poincare/include/poincare/factor.h +++ b/poincare/include/poincare/factor.h @@ -25,7 +25,7 @@ private: /* Serialization */ int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; /* Simplification */ - Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) override; + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) override; /* Evaluation */ Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } @@ -41,8 +41,8 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("factor", 1, &UntypedBuilder); - Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit); - Multiplication createMultiplicationOfIntegerPrimeDecomposition(Integer i, Context & context, Preferences::AngleUnit angleUnit) const; + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Multiplication createMultiplicationOfIntegerPrimeDecomposition(Integer i, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; private: explicit Factor(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index 5ff8b4f66..52955b808 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -21,7 +21,7 @@ public: // Properties Type type() const override { return Type::Factorial; } Sign sign(Context * context) const override { return Sign::Positive; } - Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Complex bool isReal(Context & context) const override { return true; } @@ -32,8 +32,8 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplication - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; - Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) override; // Evaluation template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { @@ -57,8 +57,8 @@ public: replaceChildAtIndexInPlace(0, child); } - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); - Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); private: constexpr static int k_maxOperandValue = 100; }; diff --git a/poincare/include/poincare/float.h b/poincare/include/poincare/float.h index ea42c5d84..0f488f094 100644 --- a/poincare/include/poincare/float.h +++ b/poincare/include/poincare/float.h @@ -40,7 +40,7 @@ public: // Properties Type type() const override { return Type::Float; } Sign sign(Context * context) const override { return m_value < 0 ? Sign::Negative : Sign::Positive; } - Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override; // Layout diff --git a/poincare/include/poincare/floor.h b/poincare/include/poincare/floor.h index ba7ff823f..47606158b 100644 --- a/poincare/include/poincare/floor.h +++ b/poincare/include/poincare/floor.h @@ -30,7 +30,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { @@ -48,7 +48,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("floor", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); private: explicit Floor(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/frac_part.h b/poincare/include/poincare/frac_part.h index 071a42c3d..7df4b717b 100644 --- a/poincare/include/poincare/frac_part.h +++ b/poincare/include/poincare/frac_part.h @@ -30,7 +30,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { @@ -48,7 +48,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("frac", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); private: explicit FracPart(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/function.h b/poincare/include/poincare/function.h index 572c0557b..bc4de3f24 100644 --- a/poincare/include/poincare/function.h +++ b/poincare/include/poincare/function.h @@ -38,7 +38,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; Expression shallowReplaceReplaceableSymbols(Context & context) override; // Evaluation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override; @@ -66,7 +66,7 @@ public: // Simplification Expression replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); Expression shallowReplaceReplaceableSymbols(Context & context); private: //VariableContext unknownXContext(Context & parentContext) const; diff --git a/poincare/include/poincare/great_common_divisor.h b/poincare/include/poincare/great_common_divisor.h index 8b21c67c1..3bdc5b8fb 100644 --- a/poincare/include/poincare/great_common_divisor.h +++ b/poincare/include/poincare/great_common_divisor.h @@ -27,7 +27,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } @@ -42,7 +42,7 @@ public: static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("gcd", 2, &UntypedBuilder); // Expression - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); private: GreatCommonDivisor(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child0); diff --git a/poincare/include/poincare/hyperbolic_trigonometric_function.h b/poincare/include/poincare/hyperbolic_trigonometric_function.h index 3f9edac25..18eaf7d54 100644 --- a/poincare/include/poincare/hyperbolic_trigonometric_function.h +++ b/poincare/include/poincare/hyperbolic_trigonometric_function.h @@ -12,13 +12,13 @@ public: int numberOfChildren() const override { return 1; } private: // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; }; class HyperbolicTrigonometricFunction : public Expression { public: HyperbolicTrigonometricFunction(const HyperbolicTrigonometricFunctionNode * n) : Expression(n) {} - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); }; } diff --git a/poincare/include/poincare/imaginary_part.h b/poincare/include/poincare/imaginary_part.h index f0e838cd9..4637cfac5 100644 --- a/poincare/include/poincare/imaginary_part.h +++ b/poincare/include/poincare/imaginary_part.h @@ -29,7 +29,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { return Complex(std::imag(c)); @@ -49,7 +49,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("im", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit ImaginaryPart(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/infinity.h b/poincare/include/poincare/infinity.h index 9d3c8065d..66e9a37c2 100644 --- a/poincare/include/poincare/infinity.h +++ b/poincare/include/poincare/infinity.h @@ -9,7 +9,7 @@ class InfinityNode final : public NumberNode { public: void setNegative(bool negative) { m_negative = negative; } - Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // TreeNode size_t size() const override { return sizeof(InfinityNode); } @@ -48,7 +48,7 @@ public: Infinity(bool negative) : Number(TreePool::sharedPool()->createTreeNode()) { node()->setNegative(negative); } - Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit); + Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); static const char * Name() { return "inf"; } diff --git a/poincare/include/poincare/integral.h b/poincare/include/poincare/integral.h index cb7840b99..4860f80ad 100644 --- a/poincare/include/poincare/integral.h +++ b/poincare/include/poincare/integral.h @@ -31,7 +31,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } @@ -66,7 +66,7 @@ public: static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("int", 4, &UntypedBuilder); // Expression - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); private: Integral(Expression child0, Expression child1, Expression child2, Expression child3) : Expression(TreePool::sharedPool()->createTreeNode()) { assert(child1.type() == ExpressionNode::Type::Symbol); diff --git a/poincare/include/poincare/least_common_multiple.h b/poincare/include/poincare/least_common_multiple.h index 78566ab35..f501b5ebc 100644 --- a/poincare/include/poincare/least_common_multiple.h +++ b/poincare/include/poincare/least_common_multiple.h @@ -27,7 +27,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; /* Simplification */ - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; /* Evaluation */ Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } @@ -42,7 +42,7 @@ public: static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("lcm", 2, &UntypedBuilder); // Expression - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); private: LeastCommonMultiple(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child0); diff --git a/poincare/include/poincare/logarithm.h b/poincare/include/poincare/logarithm.h index c3cf81943..e77e46dfd 100644 --- a/poincare/include/poincare/logarithm.h +++ b/poincare/include/poincare/logarithm.h @@ -27,8 +27,8 @@ public: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; - Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) override; // Evaluation template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { /* log has a branch cut on ]-inf, 0]: it is then multivalued on this cut. We @@ -48,17 +48,17 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("log", 2, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); private: Logarithm(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode >()) { replaceChildAtIndexInPlace(0, child0); replaceChildAtIndexInPlace(1, child1); } - Expression simpleShallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression simpleShallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); Integer simplifyLogarithmIntegerBaseInteger(Integer i, Integer & base, Addition & a, bool isDenominator); - Expression splitLogarithmInteger(Integer i, bool isDenominator, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression splitLogarithmInteger(Integer i, bool isDenominator, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); bool parentIsAPowerOfSameBase() const; }; @@ -69,7 +69,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("log", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit CommonLogarithm(Expression child) : Expression(TreePool::sharedPool()->createTreeNode >()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/matrix.h b/poincare/include/poincare/matrix.h index 1742543ec..270a6267f 100644 --- a/poincare/include/poincare/matrix.h +++ b/poincare/include/poincare/matrix.h @@ -79,7 +79,7 @@ public: Expression matrixChild(int i, int j) { return childAtIndex(i*numberOfColumns()+j); } /* Operation on matrix */ - int rank(Context & context, Preferences::AngleUnit angleUnit, bool inPlace = false); + int rank(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, bool inPlace = false); // Inverse the array in-place. Array has to be given in the form array[row_index][column_index] template static int ArrayInverse(T * array, int numberOfRows, int numberOfColumns); #if MATRIX_EXACT_REDUCING @@ -88,7 +88,7 @@ public: Matrix transpose() const; static Matrix createIdentity(int dim); /* createInverse can be called on any matrix reduce or not, approximate or not. */ - Expression inverse(Context & context, Preferences::AngleUnit angleUnit) const; + Expression inverse(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; #endif private: // TODO: find another solution for inverse and determinant (avoid capping the matrix) @@ -98,7 +98,7 @@ private: void setNumberOfRows(int rows) { assert(rows >= 0); node()->setNumberOfRows(rows); } void setNumberOfColumns(int columns) { assert(columns >= 0); node()->setNumberOfColumns(columns); } /* rowCanonize turns a matrix in its reduced row echelon form. */ - Matrix rowCanonize(Context & context, Preferences::AngleUnit angleUnit, Multiplication m = Multiplication()); + Matrix rowCanonize(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, Multiplication m = Multiplication()); // Row canonize the array in place template static void ArrayRowCanonize(T * array, int numberOfRows, int numberOfColumns, T * c = nullptr); }; diff --git a/poincare/include/poincare/matrix_dimension.h b/poincare/include/poincare/matrix_dimension.h index 66fe2d550..ce5b3a796 100644 --- a/poincare/include/poincare/matrix_dimension.h +++ b/poincare/include/poincare/matrix_dimension.h @@ -25,7 +25,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } @@ -39,7 +39,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("dim", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); private: explicit MatrixDimension(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/matrix_inverse.h b/poincare/include/poincare/matrix_inverse.h index 119d63108..d61bbf1e9 100644 --- a/poincare/include/poincare/matrix_inverse.h +++ b/poincare/include/poincare/matrix_inverse.h @@ -24,7 +24,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } @@ -38,7 +38,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("inverse", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit MatrixInverse(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/matrix_trace.h b/poincare/include/poincare/matrix_trace.h index c5aec75d2..27bc2234d 100644 --- a/poincare/include/poincare/matrix_trace.h +++ b/poincare/include/poincare/matrix_trace.h @@ -24,7 +24,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } @@ -38,7 +38,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("trace", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); private: explicit MatrixTrace(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/matrix_transpose.h b/poincare/include/poincare/matrix_transpose.h index eba119f8e..97abb0234 100644 --- a/poincare/include/poincare/matrix_transpose.h +++ b/poincare/include/poincare/matrix_transpose.h @@ -24,7 +24,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } @@ -38,7 +38,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("transpose", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); private: explicit MatrixTranspose(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 07c621cbf..2f861777f 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -34,7 +34,7 @@ public: private: // Property - Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Layout bool childNeedsParenthesis(const TreeNode * child) const override; @@ -44,9 +44,9 @@ private: int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; - Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) override; - Expression denominator(Context & context, Preferences::AngleUnit angleUnit) const override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) override; + Expression denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override; /* Approximation */ template static MatrixComplex computeOnMatrixAndComplex(const MatrixComplex m, const std::complex c) { @@ -80,21 +80,21 @@ public: template static void computeOnArrays(T * m, T * n, T * result, int mNumberOfColumns, int mNumberOfRows, int nNumberOfColumns); // Expression - Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit); + Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const; - Expression denominator(Context & context, Preferences::AngleUnit angleUnit) const; + Expression denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; private: // Simplification - Expression privateShallowReduce(Context& context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target, bool expand, bool canBeInterrupted); + Expression privateShallowReduce(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target, bool expand, bool canBeInterrupted); void mergeMultiplicationChildrenInPlace(); - void factorizeBase(int i, int j, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - void mergeInChildByFactorizingBase(int i, Expression e, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - void factorizeExponent(int i, int j, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - Expression distributeOnOperandAtIndex(int index, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - void addMissingFactors(Expression factor, Context & context, Preferences::AngleUnit angleUnit); - void factorizeSineAndCosine(int i, int j, Context & context, Preferences::AngleUnit angleUnit); + void factorizeBase(int i, int j, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + void mergeInChildByFactorizingBase(int i, Expression e, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + void factorizeExponent(int i, int j, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression distributeOnOperandAtIndex(int index, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + void addMissingFactors(Expression factor, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + void factorizeSineAndCosine(int i, int j, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); static bool HaveSameNonNumeralFactors(const Expression & e1, const Expression & e2); static bool TermsHaveIdenticalBase(const Expression & e1, const Expression & e2); static bool TermsHaveIdenticalExponent(const Expression & e1, const Expression & e2); @@ -103,7 +103,7 @@ private: static const Expression CreateExponent(Expression e); /* Warning: mergeNegativePower doesnot always return a multiplication: * *(b^-1,c^-1) -> (bc)^-1 */ - Expression mergeNegativePower(Context & context, Preferences::AngleUnit angleUnit); + Expression mergeNegativePower(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); static inline const Expression Base(const Expression e); }; diff --git a/poincare/include/poincare/naperian_logarithm.h b/poincare/include/poincare/naperian_logarithm.h index 26c4ca390..c8e4dca32 100644 --- a/poincare/include/poincare/naperian_logarithm.h +++ b/poincare/include/poincare/naperian_logarithm.h @@ -25,7 +25,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; /* Evaluation */ template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { /* ln has a branch cut on ]-inf, 0]: it is then multivalued on this cut. We @@ -48,7 +48,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("ln", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit NaperianLogarithm(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/nth_root.h b/poincare/include/poincare/nth_root.h index 191d881db..2b23add02 100644 --- a/poincare/include/poincare/nth_root.h +++ b/poincare/include/poincare/nth_root.h @@ -24,7 +24,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } @@ -39,7 +39,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("root", 2, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: NthRoot(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child0); diff --git a/poincare/include/poincare/number.h b/poincare/include/poincare/number.h index 6ef5635cf..557fa5b0b 100644 --- a/poincare/include/poincare/number.h +++ b/poincare/include/poincare/number.h @@ -47,7 +47,7 @@ public: /* Number::sign() or Number::setSign does not need a context or an angle unit * (a number can be Infinity, Undefined, Float, Decimal, Rational). */ ExpressionNode::Sign sign() { return Expression::sign(nullptr); } - Number setSign(ExpressionNode::Sign s) { return Expression::setSign(s, nullptr, Preferences::AngleUnit::Degree, ExpressionNode::ReductionTarget::User).convert(); } + Number setSign(ExpressionNode::Sign s) { return Expression::setSign(s, nullptr, Preferences::ComplexFormat::Real, Preferences::AngleUnit::Degree, ExpressionNode::ReductionTarget::User).convert(); } protected: Number() : Expression() {} NumberNode * node() const { return static_cast(Expression::node()); } diff --git a/poincare/include/poincare/opposite.h b/poincare/include/poincare/opposite.h index aa2fe69d3..91722cff9 100644 --- a/poincare/include/poincare/opposite.h +++ b/poincare/include/poincare/opposite.h @@ -41,7 +41,7 @@ public: int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = 0) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; }; class Opposite final : public Expression { @@ -52,7 +52,7 @@ public: replaceChildAtIndexInPlace(0, child); } - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); }; } diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index bd8e7d7ed..1e594500d 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -26,7 +26,7 @@ public: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Approximation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } @@ -42,7 +42,7 @@ public: replaceChildAtIndexInPlace(0, exp); } // Expression - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); }; } diff --git a/poincare/include/poincare/permute_coefficient.h b/poincare/include/poincare/permute_coefficient.h index c21e929d3..2c3f1a093 100644 --- a/poincare/include/poincare/permute_coefficient.h +++ b/poincare/include/poincare/permute_coefficient.h @@ -31,7 +31,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } @@ -46,7 +46,7 @@ public: static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("permute", 2, &UntypedBuilder); // Expression - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); private: PermuteCoefficient(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child0); diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 05efc61d0..f99c1b530 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -27,7 +27,7 @@ public: // Properties Type type() const override { return Type::Power; } Sign sign(Context * context) const override; - Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; int polynomialDegree(Context & context, const char * symbolName) const override; int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const override; @@ -45,11 +45,11 @@ private: int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplify - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; - Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) override; int simplificationOrderGreaterType(const ExpressionNode * e, bool canBeInterrupted) const override; int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override; - Expression denominator(Context & context, Preferences::AngleUnit angleUnit) const override; + Expression denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override; // Evaluation template static MatrixComplex computeOnComplexAndMatrix(const std::complex c, const MatrixComplex n); template static MatrixComplex computeOnMatrixAndComplex(const MatrixComplex m, const std::complex d); @@ -68,28 +68,28 @@ class Power final : public Expression { public: Power(Expression base, Expression exponent); Power(const PowerNode * n) : Expression(n) {} - Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const; - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); private: constexpr static int k_maxExactPowerMatrix = 100; constexpr static int k_maxNumberOfTermsInExpandedMultinome = 25; // Simplification - Expression denominator(Context & context, Preferences::AngleUnit angleUnit) const; + Expression denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; - Expression simplifyPowerPower(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - Expression simplifyPowerMultiplication(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - Expression simplifyRationalRationalPower(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression simplifyPowerPower(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression simplifyPowerMultiplication(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression simplifyRationalRationalPower(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - static Expression CreateSimplifiedIntegerRationalPower(Integer i, Rational r, bool isDenominator, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - Expression removeSquareRootsFromDenominator(Context & context, Preferences::AngleUnit angleUnit); + static Expression CreateSimplifiedIntegerRationalPower(Integer i, Rational r, bool isDenominator, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression removeSquareRootsFromDenominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); bool parentIsALogarithmOfSameBase() const; bool isNthRootOfUnity() const; Expression equivalentExpressionUsingStandardExpression() const; - static Expression CreateComplexExponent(const Expression & r, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); // Returns e^(i*pi*r) + static Expression CreateComplexExponent(const Expression & r, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); // Returns e^(i*pi*r) static bool TermIsARationalSquareRootOrRational(const Expression& e); static const Rational RadicandInExpression(const Expression & e); static const Rational RationalFactorInExpression(const Expression & e); diff --git a/poincare/include/poincare/prediction_interval.h b/poincare/include/poincare/prediction_interval.h index 9b27a7861..0c79083ed 100644 --- a/poincare/include/poincare/prediction_interval.h +++ b/poincare/include/poincare/prediction_interval.h @@ -27,7 +27,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } @@ -42,7 +42,7 @@ public: static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("prediction95", 2, &UntypedBuilder); // Expression - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: PredictionInterval(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child0); diff --git a/poincare/include/poincare/random.h b/poincare/include/poincare/random.h index fad6266ad..524da8c9c 100644 --- a/poincare/include/poincare/random.h +++ b/poincare/include/poincare/random.h @@ -24,7 +24,7 @@ public: // Properties Type type() const override { return Type::Random; } Sign sign(Context * context) const override { return Sign::Positive; } - Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; @@ -50,7 +50,7 @@ public: template static T random(); private: Random() : Expression(TreePool::sharedPool()->createTreeNode()) {} - Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit); + Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); }; } diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index fc5811504..6b98ec1f0 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -57,10 +57,10 @@ public: static int NaturalOrder(const RationalNode * i, const RationalNode * j); private: int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override; - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; - Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) override; - Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; - Expression denominator(Context & context, Preferences::AngleUnit angleUnit) const override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) override; + Expression setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override; bool m_negative; uint8_t m_numberOfDigitsNumerator; uint8_t m_numberOfDigitsDenominator; @@ -108,15 +108,15 @@ public: static int NaturalOrder(const Rational & i, const Rational & j) { return RationalNode::NaturalOrder(i.node(), j.node()); } // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); private: Rational(const native_uint_t * i, uint8_t numeratorSize, const native_uint_t * j, uint8_t denominatorSize, bool negative); RationalNode * node() { return static_cast(Number::node()); } /* Simplification */ - Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit); - Expression denominator(Context & context, Preferences::AngleUnit angleUnit) const; + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; Expression setSign(ExpressionNode::Sign s); }; diff --git a/poincare/include/poincare/real_part.h b/poincare/include/poincare/real_part.h index 5295ad2f6..28aa30832 100644 --- a/poincare/include/poincare/real_part.h +++ b/poincare/include/poincare/real_part.h @@ -29,7 +29,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { return Complex(std::real(c)); @@ -49,7 +49,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("re", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit RealPart(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/round.h b/poincare/include/poincare/round.h index f41d174af..7876622d6 100644 --- a/poincare/include/poincare/round.h +++ b/poincare/include/poincare/round.h @@ -28,7 +28,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } @@ -42,7 +42,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("round", 2, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); private: Round(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child0); diff --git a/poincare/include/poincare/sign_function.h b/poincare/include/poincare/sign_function.h index 54ee26dc9..464c79829 100644 --- a/poincare/include/poincare/sign_function.h +++ b/poincare/include/poincare/sign_function.h @@ -21,7 +21,7 @@ public: // Properties Type type() const override { return Type::SignFunction; } Sign sign(Context * context) const override; - Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Complex bool isReal(Context & context) const override { return true; } @@ -31,7 +31,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { @@ -49,7 +49,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("sign", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit SignFunction(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index 91ba724fb..a36f2b3e0 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -34,7 +34,7 @@ private: int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplication - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { @@ -52,7 +52,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("sin", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit Sine(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/square_root.h b/poincare/include/poincare/square_root.h index 3b815898f..7c692a0c2 100644 --- a/poincare/include/poincare/square_root.h +++ b/poincare/include/poincare/square_root.h @@ -27,7 +27,7 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { @@ -46,7 +46,7 @@ public: static_assert('\x91' == Ion::Charset::Root, "Charset error"); static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("\x91", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit SquareRoot(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/store.h b/poincare/include/poincare/store.h index eeb6f9573..223973bbd 100644 --- a/poincare/include/poincare/store.h +++ b/poincare/include/poincare/store.h @@ -25,8 +25,8 @@ public: private: // Simplification - void deepReduceChildren(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) override; - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + void deepReduceChildren(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; @@ -55,7 +55,7 @@ public: } // Expression - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); }; } diff --git a/poincare/include/poincare/subtraction.h b/poincare/include/poincare/subtraction.h index 122c4f994..34df24d31 100644 --- a/poincare/include/poincare/subtraction.h +++ b/poincare/include/poincare/subtraction.h @@ -39,7 +39,7 @@ public: int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; /* Simplification */ - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; private: /* Evaluation */ @@ -62,7 +62,7 @@ public: } // Expression - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); }; } diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index 56bb8461d..027730740 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -34,7 +34,7 @@ public: int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; /* Simplification */ - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; Expression shallowReplaceReplaceableSymbols(Context & context) override; /* Approximation */ @@ -79,7 +79,7 @@ public: static bool isRegressionSymbol(const char * c); // Expression - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); Expression replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression); Expression replaceUnknown(const Symbol & symbol); int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const; diff --git a/poincare/include/poincare/symbol_abstract.h b/poincare/include/poincare/symbol_abstract.h index 0b0dfa24d..cab0fc9d3 100644 --- a/poincare/include/poincare/symbol_abstract.h +++ b/poincare/include/poincare/symbol_abstract.h @@ -36,7 +36,7 @@ public: // Property Sign sign(Context * context) const override; - Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // TreeNode #if POINCARE_TREE_LOG diff --git a/poincare/include/poincare/tangent.h b/poincare/include/poincare/tangent.h index c2c00d1d4..53535af37 100644 --- a/poincare/include/poincare/tangent.h +++ b/poincare/include/poincare/tangent.h @@ -31,7 +31,7 @@ private: int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplication - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Radian); @@ -50,7 +50,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("tan", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit Tangent(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/trigonometry.h b/poincare/include/poincare/trigonometry.h index 27787022b..5e46c82a7 100644 --- a/poincare/include/poincare/trigonometry.h +++ b/poincare/include/poincare/trigonometry.h @@ -17,10 +17,10 @@ public: static bool isInverseTrigonometryFunction(const Expression & e); static bool AreInverseFunctions(const Expression & directFunction, const Expression & inverseFunction); static bool ExpressionIsEquivalentToTangent(const Expression & e); - static Expression shallowReduceDirectFunction(Expression & e, Context& context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - static Expression shallowReduceInverseFunction(Expression & e, Context& context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + static Expression shallowReduceDirectFunction(Expression & e, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + static Expression shallowReduceInverseFunction(Expression & e, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); constexpr static int k_numberOfEntries = 37; - static Expression table(const Expression e, ExpressionNode::Type type, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); // , Function f, bool inverse + static Expression table(const Expression e, ExpressionNode::Type type, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); // , Function f, bool inverse template static std::complex ConvertToRadian(const std::complex c, Preferences::AngleUnit angleUnit); template static std::complex ConvertRadianToAngleUnit(const std::complex c, Preferences::AngleUnit angleUnit); template static std::complex RoundToMeaningfulDigits(const std::complex result, const std::complex input); diff --git a/poincare/include/poincare/undefined.h b/poincare/include/poincare/undefined.h index 759fc261c..f31e02096 100644 --- a/poincare/include/poincare/undefined.h +++ b/poincare/include/poincare/undefined.h @@ -22,7 +22,7 @@ public: // Properties Type type() const override { return Type::Undefined; } int polynomialDegree(Context & context, const char * symbolName) const override; - Expression setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) override; + Expression setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Approximation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index dc11e4f88..8a053454b 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -14,8 +14,8 @@ constexpr Expression::FunctionHelper AbsoluteValue::s_functionHelper; int AbsoluteValueNode::numberOfChildren() const { return AbsoluteValue::s_functionHelper.numberOfChildren(); } -Expression AbsoluteValueNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return AbsoluteValue(this).setSign(s, context, angleUnit); +Expression AbsoluteValueNode::setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return AbsoluteValue(this).setSign(s, context, complexFormat, angleUnit); } Layout AbsoluteValueNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -26,17 +26,17 @@ int AbsoluteValueNode::serialize(char * buffer, int bufferSize, Preferences::Pri return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, AbsoluteValue::s_functionHelper.name()); } -Expression AbsoluteValueNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return AbsoluteValue(this).shallowReduce(context, angleUnit, target); +Expression AbsoluteValueNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return AbsoluteValue(this).shallowReduce(context, complexFormat, angleUnit, target); } -Expression AbsoluteValue::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit) { +Expression AbsoluteValue::setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { assert(s == ExpressionNode::Sign::Positive); return *this; } -Expression AbsoluteValue::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { - Expression e = Expression::defaultShallowReduce(context, angleUnit); +Expression AbsoluteValue::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } @@ -58,17 +58,17 @@ Expression AbsoluteValue::shallowReduce(Context & context, Preferences::AngleUni // abs(a) = -a with a < 0 Multiplication m(Rational(-1), c); replaceWithInPlace(m); - return m.shallowReduce(context, angleUnit, target); + return m.shallowReduce(context, complexFormat, angleUnit, target); } } if (c.type() == ExpressionNode::Type::ComplexCartesian) { ComplexCartesian complexChild = static_cast(c); - Expression childNorm = complexChild.norm(context, angleUnit, target); + Expression childNorm = complexChild.norm(context, complexFormat, angleUnit, target); replaceWithInPlace(childNorm); - return childNorm.shallowReduce(context, angleUnit, target); + return childNorm.shallowReduce(context, complexFormat, angleUnit, target); } // abs(-x) = abs(x) - c.makePositiveAnyNegativeNumeralFactor(context, angleUnit, target); + c.makePositiveAnyNegativeNumeralFactor(context, complexFormat, angleUnit, target); return *this; } diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 1891befad..179e4425b 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -50,12 +50,12 @@ int AdditionNode::serialize(char * buffer, int bufferSize, Preferences::PrintFlo // Simplication -Expression AdditionNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Addition(this).shallowReduce(context, angleUnit, target); +Expression AdditionNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Addition(this).shallowReduce(context, complexFormat, angleUnit, target); } -Expression AdditionNode::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { - return Addition(this).shallowBeautify(context, angleUnit); +Expression AdditionNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { + return Addition(this).shallowBeautify(context, complexFormat, angleUnit); } // Addition @@ -88,7 +88,7 @@ int Addition::getPolynomialCoefficients(Context & context, const char * symbolNa return deg; } -Expression Addition::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { +Expression Addition::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { /* Beautifying AdditionNode essentially consists in adding Subtractions if * needed. * In practice, we want to turn "a+(-1)*b" into "a-b". Or, more precisely, any @@ -101,7 +101,7 @@ Expression Addition::shallowBeautify(Context & context, Preferences::AngleUnit a for (int i = 0; i < numberOfChildren(); i++) { // Try to make the child i positive if any negative numeral factor is found - Expression subtractant = childAtIndex(i).makePositiveAnyNegativeNumeralFactor(context, angleUnit, ExpressionNode::ReductionTarget::User); + Expression subtractant = childAtIndex(i).makePositiveAnyNegativeNumeralFactor(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); if (subtractant.isUninitialized()) { // if subtractant is not initialized, it means the child i had no negative numeral factor @@ -131,9 +131,9 @@ Expression Addition::shallowBeautify(Context & context, Preferences::AngleUnit a return result; } -Expression Addition::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression Addition::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } @@ -187,7 +187,7 @@ Expression Addition::shallowReduce(Context & context, Preferences::AngleUnit ang resultMatrix->replaceOperand(resultMatrixEntryJ, a, false); a->addOperand(currentMatrix->childAtIndex(j)); a->addOperand(resultMatrixEntryJ); - a->shallowReduce(context, angleUnit); + a->shallowReduce(context, complexFormat, angleUnit); } currentMatrix->detachOperands(); removeOperand(currentMatrix, true); @@ -199,9 +199,9 @@ Expression Addition::shallowReduce(Context & context, Preferences::AngleUnit ang Expression * entryI = resultMatrix->childAtIndex(i); resultMatrix->replaceOperand(entryI, a, false); a->addOperand(entryI); - a->shallowReduce(context, angleUnit); + a->shallowReduce(context, complexFormat, angleUnit); } - return replaceWith(resultMatrix, true)->shallowReduce(context, angleUnit); + return replaceWith(resultMatrix, true)->shallowReduce(context, complexFormat, angleUnit); } #endif #endif @@ -221,7 +221,7 @@ Expression Addition::shallowReduce(Context & context, Preferences::AngleUnit ang continue; } if (TermsHaveIdenticalNonNumeralFactors(e1, e2)) { - factorizeChildrenAtIndexesInPlace(i, i+1, context, angleUnit, target); + factorizeChildrenAtIndexesInPlace(i, i+1, context, complexFormat, angleUnit, target); continue; } i++; @@ -275,9 +275,9 @@ Expression Addition::shallowReduce(Context & context, Preferences::AngleUnit ang replaceWithInPlace(newComplexCartesian); newComplexCartesian.replaceChildAtIndexInPlace(0, real); newComplexCartesian.replaceChildAtIndexInPlace(1, imag); - real.shallowReduce(context, angleUnit, target); - imag.shallowReduce(context, angleUnit, target); - return newComplexCartesian.shallowReduce(context, angleUnit); + real.shallowReduce(context, complexFormat, angleUnit, target); + imag.shallowReduce(context, complexFormat, angleUnit, target); + return newComplexCartesian.shallowReduce(context, complexFormat, angleUnit); } /* Step 7: Let's put everything under a common denominator. @@ -286,7 +286,7 @@ Expression Addition::shallowReduce(Context & context, Preferences::AngleUnit ang Expression p = result.parent(); if (target == ExpressionNode::ReductionTarget::User && result == *this && (p.isUninitialized() || p.type() != ExpressionNode::Type::Addition)) { // squashUnaryHierarchy didn't do anything: we're not an unary hierarchy - result = factorizeOnCommonDenominator(context, angleUnit); + result = factorizeOnCommonDenominator(context, complexFormat, angleUnit); } return result; } @@ -332,16 +332,16 @@ bool Addition::TermsHaveIdenticalNonNumeralFactors(const Expression & e1, const } } -Expression Addition::factorizeOnCommonDenominator(Context & context, Preferences::AngleUnit angleUnit) { +Expression Addition::factorizeOnCommonDenominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { // We want to turn (a/b+c/d+e/b) into (a*d+b*c+e*d)/(b*d) // Step 1: We want to compute the common denominator, b*d Multiplication commonDenominator = Multiplication(); for (int i = 0; i < numberOfChildren(); i++) { - Expression currentDenominator = childAtIndex(i).denominator(context, angleUnit); + Expression currentDenominator = childAtIndex(i).denominator(context, complexFormat, angleUnit); if (!currentDenominator.isUninitialized()) { // Make commonDenominator = LeastCommonMultiple(commonDenominator, denominator); - commonDenominator.addMissingFactors(currentDenominator, context, angleUnit); + commonDenominator.addMissingFactors(currentDenominator, context, complexFormat, angleUnit); } } if (commonDenominator.numberOfChildren() == 0) { @@ -355,7 +355,7 @@ Expression Addition::factorizeOnCommonDenominator(Context & context, Preferences for (int i = 0; i < numberOfChildren(); i++) { Multiplication m = Multiplication(childAtIndex(i), commonDenominator.clone()); numerator.addChildAtIndexInPlace(m, numerator.numberOfChildren(), numerator.numberOfChildren()); - m.privateShallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User, true, false); + m.privateShallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User, true, false); } // Step 3: Add the denominator @@ -363,18 +363,18 @@ Expression Addition::factorizeOnCommonDenominator(Context & context, Preferences Multiplication result = Multiplication(numerator, inverseDenominator); // Step 4: Simplify the numerator - numerator.shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); + numerator.shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); // Step 5: Simplify the denominator (in case it's a rational number) - inverseDenominator.deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); + inverseDenominator.deepReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); /* Step 6: We simplify the resulting multiplication forbidding any * distribution of multiplication on additions (to avoid an infinite loop). */ replaceWithInPlace(result); - return result.privateShallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User, false, true); + return result.privateShallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User, false, true); } -void Addition::factorizeChildrenAtIndexesInPlace(int index1, int index2, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +void Addition::factorizeChildrenAtIndexesInPlace(int index1, int index2, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { /* This function factorizes two children which only differ by a rational * factor. For example, if this is AdditionNode(2*pi, 3*pi), then 2*pi and 3*pi * could be merged, and this turned into AdditionNode(5*pi). */ @@ -410,7 +410,7 @@ void Addition::factorizeChildrenAtIndexesInPlace(int index1, int index2, Context } // Step 5: Reduce the multiplication (in case the new rational factor is zero) - m.shallowReduce(context, angleUnit, target); + m.shallowReduce(context, complexFormat, angleUnit, target); } template Complex Poincare::AdditionNode::compute(std::complex, std::complex); diff --git a/poincare/src/arc_cosine.cpp b/poincare/src/arc_cosine.cpp index 8bd1baae2..6e5538a2e 100644 --- a/poincare/src/arc_cosine.cpp +++ b/poincare/src/arc_cosine.cpp @@ -19,8 +19,8 @@ int ArcCosineNode::serialize(char * buffer, int bufferSize, Preferences::PrintFl return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, ArcCosine::s_functionHelper.name()); } -Expression ArcCosineNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return ArcCosine(this).shallowReduce(context, angleUnit, target); +Expression ArcCosineNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return ArcCosine(this).shallowReduce(context, complexFormat, angleUnit, target); } template @@ -48,9 +48,9 @@ Complex ArcCosineNode::computeOnComplex(const std::complex c, Preferences: return Complex(Trigonometry::ConvertRadianToAngleUnit(result, angleUnit)); } -Expression ArcCosine::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression ArcCosine::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } @@ -60,7 +60,7 @@ Expression ArcCosine::shallowReduce(Context & context, Preferences::AngleUnit an return SimplificationHelper::Map(*this, context, angleUnit); } #endif - return Trigonometry::shallowReduceInverseFunction(*this, context, angleUnit, target); + return Trigonometry::shallowReduceInverseFunction(*this, context, complexFormat, angleUnit, target); } } diff --git a/poincare/src/arc_sine.cpp b/poincare/src/arc_sine.cpp index cd28c1fcf..d117a404a 100644 --- a/poincare/src/arc_sine.cpp +++ b/poincare/src/arc_sine.cpp @@ -19,8 +19,8 @@ int ArcSineNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloa return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, ArcSine::s_functionHelper.name()); } -Expression ArcSineNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return ArcSine(this).shallowReduce(context, angleUnit, target); +Expression ArcSineNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return ArcSine(this).shallowReduce(context, complexFormat, angleUnit, target); } template @@ -48,9 +48,9 @@ Complex ArcSineNode::computeOnComplex(const std::complex c, Preferences::A return Complex(Trigonometry::ConvertRadianToAngleUnit(result, angleUnit)); } -Expression ArcSine::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression ArcSine::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } @@ -60,7 +60,7 @@ Expression ArcSine::shallowReduce(Context & context, Preferences::AngleUnit angl return SimplificationHelper::Map(*this, context, angleUnit); } #endif - return Trigonometry::shallowReduceInverseFunction(*this, context, angleUnit, target); + return Trigonometry::shallowReduceInverseFunction(*this, context, complexFormat, angleUnit, target); } } diff --git a/poincare/src/arc_tangent.cpp b/poincare/src/arc_tangent.cpp index e5cc533d7..e73346485 100644 --- a/poincare/src/arc_tangent.cpp +++ b/poincare/src/arc_tangent.cpp @@ -44,13 +44,13 @@ Complex ArcTangentNode::computeOnComplex(const std::complex c, Preferences return Complex(Trigonometry::ConvertRadianToAngleUnit(result, angleUnit)); } -Expression ArcTangentNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return ArcTangent(this).shallowReduce(context, angleUnit, target); +Expression ArcTangentNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return ArcTangent(this).shallowReduce(context, complexFormat, angleUnit, target); } -Expression ArcTangent::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression ArcTangent::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } @@ -60,7 +60,7 @@ Expression ArcTangent::shallowReduce(Context & context, Preferences::AngleUnit a return SimplificationHelper::Map(*this, context, angleUnit); } #endif - return Trigonometry::shallowReduceInverseFunction(*this, context, angleUnit, target); + return Trigonometry::shallowReduceInverseFunction(*this, context, complexFormat, angleUnit, target); } } diff --git a/poincare/src/binomial_coefficient.cpp b/poincare/src/binomial_coefficient.cpp index 9269fd53d..398aa24cd 100644 --- a/poincare/src/binomial_coefficient.cpp +++ b/poincare/src/binomial_coefficient.cpp @@ -14,8 +14,8 @@ constexpr Expression::FunctionHelper BinomialCoefficient::s_functionHelper; int BinomialCoefficientNode::numberOfChildren() const { return BinomialCoefficient::s_functionHelper.numberOfChildren(); } -Expression BinomialCoefficientNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return BinomialCoefficient(this).shallowReduce(context, angleUnit); +Expression BinomialCoefficientNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return BinomialCoefficient(this).shallowReduce(context, complexFormat, angleUnit); } Layout BinomialCoefficientNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -53,9 +53,9 @@ T BinomialCoefficientNode::compute(T k, T n) { return std::round(result); } -Expression BinomialCoefficient::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression BinomialCoefficient::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } diff --git a/poincare/src/ceiling.cpp b/poincare/src/ceiling.cpp index cc0ab7f1f..1afb83571 100644 --- a/poincare/src/ceiling.cpp +++ b/poincare/src/ceiling.cpp @@ -31,13 +31,13 @@ Complex CeilingNode::computeOnComplex(const std::complex c, Preferences::A return Complex(std::ceil(c.real())); } -Expression CeilingNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Ceiling(this).shallowReduce(context, angleUnit); +Expression CeilingNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Ceiling(this).shallowReduce(context, complexFormat, angleUnit); } -Expression Ceiling::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression Ceiling::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } diff --git a/poincare/src/complex_argument.cpp b/poincare/src/complex_argument.cpp index 046206fe8..c0aec6212 100644 --- a/poincare/src/complex_argument.cpp +++ b/poincare/src/complex_argument.cpp @@ -24,8 +24,8 @@ int ComplexArgumentNode::serialize(char * buffer, int bufferSize, Preferences::P return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, ComplexArgument::s_functionHelper.name()); } -Expression ComplexArgumentNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return ComplexArgument(this).shallowReduce(context, angleUnit, target); +Expression ComplexArgumentNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return ComplexArgument(this).shallowReduce(context, complexFormat, angleUnit, target); } template @@ -33,9 +33,9 @@ Complex ComplexArgumentNode::computeOnComplex(const std::complex c, Prefer return Complex(std::arg(c)); } -Expression ComplexArgument::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression ComplexArgument::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } @@ -63,9 +63,9 @@ Expression ComplexArgument::shallowReduce(Context & context, Preferences::AngleU } if (real || c.type() == ExpressionNode::Type::ComplexCartesian) { ComplexCartesian complexChild = real ? ComplexCartesian::Builder(c, Rational(0)) : static_cast(c); - Expression childArg = complexChild.argument(context, angleUnit, target); + Expression childArg = complexChild.argument(context, complexFormat, angleUnit, target); replaceWithInPlace(childArg); - return childArg.shallowReduce(context, angleUnit, target); + return childArg.shallowReduce(context, complexFormat, angleUnit, target); } return *this; } diff --git a/poincare/src/complex_cartesian.cpp b/poincare/src/complex_cartesian.cpp index a83b04920..e0a9b2331 100644 --- a/poincare/src/complex_cartesian.cpp +++ b/poincare/src/complex_cartesian.cpp @@ -19,12 +19,12 @@ namespace Poincare { -Expression ComplexCartesianNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return ComplexCartesian(this).shallowReduce(context, angleUnit); +Expression ComplexCartesianNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return ComplexCartesian(this).shallowReduce(context, complexFormat, angleUnit); } -Expression ComplexCartesianNode::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { - return ComplexCartesian(this).shallowBeautify(context, angleUnit); +Expression ComplexCartesianNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { + return ComplexCartesian(this).shallowBeautify(context, complexFormat, angleUnit); } template @@ -40,7 +40,7 @@ Complex ComplexCartesianNode::templatedApproximate(Context& context, Preferen return Complex(a.real(), b.real()); } -Expression ComplexCartesian::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression ComplexCartesian::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { if (imag().isRationalZero()) { Expression r = real(); replaceWithInPlace(r); @@ -49,11 +49,11 @@ Expression ComplexCartesian::shallowReduce(Context & context, Preferences::Angle return *this; } -Expression ComplexCartesian::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { +Expression ComplexCartesian::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { Expression a = real(); Expression b = imag(); - Expression oppositeA = a.makePositiveAnyNegativeNumeralFactor(context, angleUnit, ExpressionNode::ReductionTarget::User); - Expression oppositeB = b.makePositiveAnyNegativeNumeralFactor(context, angleUnit, ExpressionNode::ReductionTarget::User); + Expression oppositeA = a.makePositiveAnyNegativeNumeralFactor(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); + Expression oppositeB = b.makePositiveAnyNegativeNumeralFactor(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); a = oppositeA.isUninitialized() ? a : oppositeA; b = oppositeB.isUninitialized() ? b : oppositeB; Expression e = Expression::CreateComplexExpression(a, b, Preferences::ComplexFormat::Cartesian, @@ -66,7 +66,7 @@ Expression ComplexCartesian::shallowBeautify(Context & context, Preferences::Ang return e; } -void ComplexCartesian::factorAndArgumentOfFunction(Expression e, ExpressionNode::Type searchedType, Expression * factor, Expression * argument, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +void ComplexCartesian::factorAndArgumentOfFunction(Expression e, ExpressionNode::Type searchedType, Expression * factor, Expression * argument, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { if (e.type() == searchedType) { *factor = Rational(1); *argument = e.childAtIndex(0); @@ -78,8 +78,8 @@ void ComplexCartesian::factorAndArgumentOfFunction(Expression e, ExpressionNode: *argument = e.childAtIndex(i).childAtIndex(0); *factor = e.clone(); static_cast(factor)->removeChildAtIndexInPlace(i); - *factor = factor->shallowReduce(context, angleUnit, target); - Expression positiveFactor = factor->makePositiveAnyNegativeNumeralFactor(context, angleUnit, target); + *factor = factor->shallowReduce(context, complexFormat, angleUnit, target); + Expression positiveFactor = factor->makePositiveAnyNegativeNumeralFactor(context, complexFormat, angleUnit, target); *factor = positiveFactor.isUninitialized() ? *factor : positiveFactor; return; } @@ -87,26 +87,26 @@ void ComplexCartesian::factorAndArgumentOfFunction(Expression e, ExpressionNode: } } -Expression ComplexCartesian::squareNorm(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression ComplexCartesian::squareNorm(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { Expression a = real(); Expression b = imag(); Expression aFactor, bFactor, aArgument, bArgument; - factorAndArgumentOfFunction(a, ExpressionNode::Type::Cosine, &aFactor, &aArgument, context, angleUnit, target); - factorAndArgumentOfFunction(b, ExpressionNode::Type::Sine, &bFactor, &bArgument, context, angleUnit, target); + factorAndArgumentOfFunction(a, ExpressionNode::Type::Cosine, &aFactor, &aArgument, context, complexFormat, angleUnit, target); + factorAndArgumentOfFunction(b, ExpressionNode::Type::Sine, &bFactor, &bArgument, context, complexFormat, angleUnit, target); if (!aFactor.isUninitialized() && !aArgument.isUninitialized() && !bFactor.isUninitialized() && !bArgument.isUninitialized() && aFactor.isIdenticalTo(bFactor) && aArgument.isIdenticalTo(bArgument)) { Power result(aFactor, Rational(2)); - aFactor.shallowReduce(context, angleUnit, target); + aFactor.shallowReduce(context, complexFormat, angleUnit, target); return result; } Expression a2 = Power(a, Rational(2)); Expression b2 = Power(b, Rational(2)); Addition add(a2, b2); - a2.shallowReduce(context, angleUnit, target); - b2.shallowReduce(context, angleUnit, target); + a2.shallowReduce(context, complexFormat, angleUnit, target); + b2.shallowReduce(context, complexFormat, angleUnit, target); return add; } -Expression ComplexCartesian::norm(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression ComplexCartesian::norm(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { if (imag().isRationalZero()) { Expression a = real(); ExpressionNode::Sign s = a.sign(&context); @@ -115,16 +115,16 @@ Expression ComplexCartesian::norm(Context & context, Preferences::AngleUnit angl return a;; } else if (s == ExpressionNode::Sign::Negative) { // Case 2: the argument is negative real - return a.setSign(ExpressionNode::Sign::Positive, &context, angleUnit, target); + return a.setSign(ExpressionNode::Sign::Positive, &context, complexFormat, angleUnit, target); } } - Expression n2 = squareNorm(context, angleUnit, target); + Expression n2 = squareNorm(context, complexFormat, angleUnit, target); Expression n = SquareRoot::Builder(n2); - n2.shallowReduce(context, angleUnit, target); + n2.shallowReduce(context, complexFormat, angleUnit, target); return n; } -Expression ComplexCartesian::argument(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression ComplexCartesian::argument(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { Expression a = real(); Expression b = imag(); if (!b.isRationalZero()) { @@ -132,91 +132,91 @@ Expression ComplexCartesian::argument(Context & context, Preferences::AngleUnit // First, compute arctan(a/b) or (Pi/180)*arctan(a/b) Expression divab = Division(a, b.clone()); Expression arcTangent = ArcTangent::Builder(divab); - divab.shallowReduce(context, angleUnit, target); + divab.shallowReduce(context, complexFormat, angleUnit, target); if (angleUnit == Preferences::AngleUnit::Degree) { Expression temp = arcTangent.degreeToRadian(); - arcTangent.shallowReduce(context, angleUnit, target); + arcTangent.shallowReduce(context, complexFormat, angleUnit, target); arcTangent = temp; } // Then, compute sign(b) * Pi/2 - arctan(a/b) Expression signb = SignFunction::Builder(b); Expression signbPi2 = Multiplication(Rational(1,2), signb, Constant(Ion::Charset::SmallPi)); - signb.shallowReduce(context, angleUnit, target); + signb.shallowReduce(context, complexFormat, angleUnit, target); Expression sub = Subtraction(signbPi2, arcTangent); - signbPi2.shallowReduce(context, angleUnit, target); - arcTangent.shallowReduce(context, angleUnit, target); + signbPi2.shallowReduce(context, complexFormat, angleUnit, target); + arcTangent.shallowReduce(context, complexFormat, angleUnit, target); return sub; } else { // if b == 0, argument = (1-sign(a))*Pi/2 - Expression signa = SignFunction::Builder(a).shallowReduce(context, angleUnit, target); + Expression signa = SignFunction::Builder(a).shallowReduce(context, complexFormat, angleUnit, target); Subtraction sub(Rational(1), signa); - signa.shallowReduce(context, angleUnit, target); + signa.shallowReduce(context, complexFormat, angleUnit, target); Multiplication mul(Rational(1,2), Constant(Ion::Charset::SmallPi), sub); - sub.shallowReduce(context, angleUnit, target); + sub.shallowReduce(context, complexFormat, angleUnit, target); return mul; } } -ComplexCartesian ComplexCartesian::inverse(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +ComplexCartesian ComplexCartesian::inverse(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { Expression a = real(); Expression b = imag(); // 1/(a+ib) = a/(a^2+b^2)+i*(-b/(a^2+b^2)) - Expression denominatorReal = clone().convert().squareNorm(context, angleUnit, target); + Expression denominatorReal = clone().convert().squareNorm(context, complexFormat, angleUnit, target); Expression denominatorImag = denominatorReal.clone(); Expression denominatorRealInv = Power(denominatorReal, Rational(-1)); - denominatorReal.shallowReduce(context, angleUnit, target); + denominatorReal.shallowReduce(context, complexFormat, angleUnit, target); Expression denominatorImagInv = Power(denominatorImag, Rational(-1)); - denominatorImag.shallowReduce(context, angleUnit, target); + denominatorImag.shallowReduce(context, complexFormat, angleUnit, target); Multiplication A(a, denominatorRealInv); - denominatorRealInv.shallowReduce(context, angleUnit, target); + denominatorRealInv.shallowReduce(context, complexFormat, angleUnit, target); Expression numeratorImag = Multiplication(Rational(-1), b); Multiplication B(numeratorImag, denominatorImagInv); - numeratorImag.shallowReduce(context, angleUnit, target); - denominatorImagInv.shallowReduce(context, angleUnit, target); + numeratorImag.shallowReduce(context, complexFormat, angleUnit, target); + denominatorImagInv.shallowReduce(context, complexFormat, angleUnit, target); ComplexCartesian result(A,B); - A.shallowReduce(context, angleUnit, target); - B.shallowReduce(context, angleUnit, target); + A.shallowReduce(context, complexFormat, angleUnit, target); + B.shallowReduce(context, complexFormat, angleUnit, target); return result.interruptComputationIfManyNodes(); } -Multiplication ComplexCartesian::squareRootHelper(Expression e, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Multiplication ComplexCartesian::squareRootHelper(Expression e, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { //(1/2)*sqrt(2*e) Multiplication doubleE(Rational(2), e); - e.shallowReduce(context, angleUnit, target); + e.shallowReduce(context, complexFormat, angleUnit, target); Expression sqrt = SquareRoot::Builder(doubleE); - doubleE.shallowReduce(context, angleUnit, target); + doubleE.shallowReduce(context, complexFormat, angleUnit, target); Multiplication result(Rational(1,2), sqrt); - sqrt.shallowReduce(context, angleUnit, target); + sqrt.shallowReduce(context, complexFormat, angleUnit, target); return result; } -ComplexCartesian ComplexCartesian::squareRoot(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +ComplexCartesian ComplexCartesian::squareRoot(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { Expression a = real(); Expression b = imag(); // A: (1/2)*sqrt(2*(sqrt(a^2+b^2)+a)) // B: (1/2)*sqrt(2*(sqrt(a^2+b^2)-a))*sign(b) - Expression normA = clone().convert().norm(context, angleUnit, target); + Expression normA = clone().convert().norm(context, complexFormat, angleUnit, target); Expression normB = normA.clone(); // A = (1/2)*sqrt(2*(sqrt(a^2+b^2)+a)) Addition normAdda(normA, a.clone()); - normA.shallowReduce(context, angleUnit, target); - Multiplication A = squareRootHelper(normAdda, context, angleUnit, target); + normA.shallowReduce(context, complexFormat, angleUnit, target); + Multiplication A = squareRootHelper(normAdda, context, complexFormat, angleUnit, target); // B = B: (1/2)*sqrt(2*(sqrt(a^2+b^2)-a)) Subtraction normSuba(normB, a); - normB.shallowReduce(context, angleUnit, target); - Multiplication B = squareRootHelper(normSuba, context, angleUnit, target); + normB.shallowReduce(context, complexFormat, angleUnit, target); + Multiplication B = squareRootHelper(normSuba, context, complexFormat, angleUnit, target); // B = B: (1/2)*sqrt(2*(sqrt(a^2+b^2)-a))*sign(b) Expression signb = SignFunction::Builder(b); B.addChildAtIndexInPlace(signb, B.numberOfChildren(), B.numberOfChildren()); - signb.shallowReduce(context, angleUnit, target); + signb.shallowReduce(context, complexFormat, angleUnit, target); ComplexCartesian result = ComplexCartesian::Builder(A, B); - A.shallowReduce(context, angleUnit, target); - B.shallowReduce(context, angleUnit, target); + A.shallowReduce(context, complexFormat, angleUnit, target); + B.shallowReduce(context, complexFormat, angleUnit, target); return result.interruptComputationIfManyNodes(); } -ComplexCartesian ComplexCartesian::powerInteger(int n, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +ComplexCartesian ComplexCartesian::powerInteger(int n, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { Expression a = real(); Expression b = imag(); assert(n > 0); @@ -229,7 +229,7 @@ ComplexCartesian ComplexCartesian::powerInteger(int n, Context & context, Prefer Expression bpow = Power(b, Rational(n)); if (n/2%2 == 1) { Expression temp = Multiplication(Rational(-1), bpow); - bpow.shallowReduce(context, angleUnit, target); + bpow.shallowReduce(context, complexFormat, angleUnit, target); bpow = temp; } if (n%2 == 0) { @@ -237,7 +237,7 @@ ComplexCartesian ComplexCartesian::powerInteger(int n, Context & context, Prefer } else { result = ComplexCartesian(Rational(0), bpow); } - bpow.shallowReduce(context, angleUnit, target); + bpow.shallowReduce(context, complexFormat, angleUnit, target); return result; } // (a+ib) = a^n+i*b*a^(n-1)+(-1)*b^2*a^(n-2)+(-i)*b^3*a^(n-3)+b^3*a^(n-4)+... @@ -253,9 +253,9 @@ ComplexCartesian ComplexCartesian::powerInteger(int n, Context & context, Prefer Power apow(aclone, Rational(n-i)); Power bpow(bclone, Rational(i)); Multiplication m(binom, apow, bpow); - binom.shallowReduce(context, angleUnit); - apow.shallowReduce(context, angleUnit, target); - bpow.shallowReduce(context, angleUnit, target); + binom.shallowReduce(context, complexFormat, angleUnit); + apow.shallowReduce(context, complexFormat, angleUnit, target); + bpow.shallowReduce(context, complexFormat, angleUnit, target); if (i/2%2 == 1) { m.addChildAtIndexInPlace(Rational(-1), 0, m.numberOfChildren()); } @@ -264,18 +264,18 @@ ComplexCartesian ComplexCartesian::powerInteger(int n, Context & context, Prefer } else { B.addChildAtIndexInPlace(m, B.numberOfChildren(), B.numberOfChildren()); } - m.shallowReduce(context, angleUnit, target); + m.shallowReduce(context, complexFormat, angleUnit, target); result = result.interruptComputationIfManyNodes(); if (result.real().isUndefined()) { return result; } } - A.shallowReduce(context, angleUnit, target); - B.shallowReduce(context, angleUnit, target); + A.shallowReduce(context, complexFormat, angleUnit, target); + B.shallowReduce(context, complexFormat, angleUnit, target); return result; } -ComplexCartesian ComplexCartesian::multiply(ComplexCartesian & other, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +ComplexCartesian ComplexCartesian::multiply(ComplexCartesian & other, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { Expression a = real(); Expression b = imag(); Expression c = other.real(); @@ -285,73 +285,73 @@ ComplexCartesian ComplexCartesian::multiply(ComplexCartesian & other, Context & Expression ac = Multiplication(a.clone(), c.clone()); Expression bd = Multiplication(b.clone(), d.clone()); Subtraction A(ac, bd); - ac.shallowReduce(context, angleUnit, target); - bd.shallowReduce(context, angleUnit, target); + ac.shallowReduce(context, complexFormat, angleUnit, target); + bd.shallowReduce(context, complexFormat, angleUnit, target); // Compute ad+bc Expression ad = Multiplication(a, d); Expression bc = Multiplication(b, c); Addition B(ad, bc); - ad.shallowReduce(context, angleUnit, target); - bc.shallowReduce(context, angleUnit, target); + ad.shallowReduce(context, complexFormat, angleUnit, target); + bc.shallowReduce(context, complexFormat, angleUnit, target); ComplexCartesian result = ComplexCartesian::Builder(A, B); - A.shallowReduce(context, angleUnit, target); - B.shallowReduce(context, angleUnit, target); + A.shallowReduce(context, complexFormat, angleUnit, target); + B.shallowReduce(context, complexFormat, angleUnit, target); return result.interruptComputationIfManyNodes(); } -Expression ComplexCartesian::powerHelper(Expression norm, Expression trigo, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression ComplexCartesian::powerHelper(Expression norm, Expression trigo, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { Multiplication m(norm, trigo); - norm.shallowReduce(context, angleUnit, target); - trigo.shallowReduce(context, angleUnit, target); + norm.shallowReduce(context, complexFormat, angleUnit, target); + trigo.shallowReduce(context, complexFormat, angleUnit, target); return m; } -ComplexCartesian ComplexCartesian::power(ComplexCartesian & other, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { - Expression r = clone().convert().norm(context, angleUnit, target); +ComplexCartesian ComplexCartesian::power(ComplexCartesian & other, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + Expression r = clone().convert().norm(context, complexFormat, angleUnit, target); Expression rclone = r.clone(); - Expression th = argument(context, angleUnit, target); + Expression th = argument(context, complexFormat, angleUnit, target); Expression thclone = th.clone(); Expression c = other.real(); Expression d = other.imag(); // R = r^c*e^(-th*d) Expression rpowc = Power(rclone, c.clone()); - rclone.shallowReduce(context, angleUnit, target); + rclone.shallowReduce(context, complexFormat, angleUnit, target); Expression thmuld = Multiplication(Rational(-1), thclone, d.clone()); - thclone.shallowReduce(context, angleUnit, target); + thclone.shallowReduce(context, complexFormat, angleUnit, target); Expression exp = Power(Constant(Ion::Charset::Exponential), thmuld); - thmuld.shallowReduce(context, angleUnit, target); + thmuld.shallowReduce(context, complexFormat, angleUnit, target); Multiplication norm(rpowc, exp); - rpowc.shallowReduce(context, angleUnit, target); - exp.shallowReduce(context, angleUnit, target); + rpowc.shallowReduce(context, complexFormat, angleUnit, target); + exp.shallowReduce(context, complexFormat, angleUnit, target); // TH = d*ln(r)+c*th Expression lnr = NaperianLogarithm::Builder(r); - r.shallowReduce(context, angleUnit, target); + r.shallowReduce(context, complexFormat, angleUnit, target); Multiplication dlnr(d, lnr); - lnr.shallowReduce(context, angleUnit, target); + lnr.shallowReduce(context, complexFormat, angleUnit, target); Multiplication thc(th, c); - th.shallowReduce(context, angleUnit, target); + th.shallowReduce(context, complexFormat, angleUnit, target); Expression argument = Addition(thc, dlnr); - thc.shallowReduce(context, angleUnit, target); - dlnr.shallowReduce(context, angleUnit, target); + thc.shallowReduce(context, complexFormat, angleUnit, target); + dlnr.shallowReduce(context, complexFormat, angleUnit, target); if (angleUnit == Preferences::AngleUnit::Degree) { Expression temp = argument.radianToDegree(); - argument.shallowReduce(context, angleUnit, target); + argument.shallowReduce(context, complexFormat, angleUnit, target); argument = temp; } // Result = (norm*cos(argument), norm*sin(argument)) Expression normClone = norm.clone(); Expression argClone = argument.clone(); Expression cos = Cosine::Builder(argClone); - argClone.shallowReduce(context, angleUnit, target); - Expression normcosarg = powerHelper(normClone, cos, context, angleUnit, target); + argClone.shallowReduce(context, complexFormat, angleUnit, target); + Expression normcosarg = powerHelper(normClone, cos, context, complexFormat, angleUnit, target); Expression sin = Sine::Builder(argument); - argument.shallowReduce(context, angleUnit, target); - Expression normsinarg = powerHelper(norm, sin, context, angleUnit, target); + argument.shallowReduce(context, complexFormat, angleUnit, target); + Expression normsinarg = powerHelper(norm, sin, context, complexFormat, angleUnit, target); ComplexCartesian result = ComplexCartesian::Builder(normcosarg, normsinarg); - normcosarg.shallowReduce(context, angleUnit, target); - normsinarg.shallowReduce(context, angleUnit, target); + normcosarg.shallowReduce(context, complexFormat, angleUnit, target); + normsinarg.shallowReduce(context, complexFormat, angleUnit, target); return result.interruptComputationIfManyNodes(); } diff --git a/poincare/src/confidence_interval.cpp b/poincare/src/confidence_interval.cpp index 1d99e4644..f110f94a8 100644 --- a/poincare/src/confidence_interval.cpp +++ b/poincare/src/confidence_interval.cpp @@ -25,8 +25,8 @@ int ConfidenceIntervalNode::serialize(char * buffer, int bufferSize, Preferences return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, ConfidenceInterval::s_functionHelper.name()); } -Expression ConfidenceIntervalNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return ConfidenceInterval(this).shallowReduce(context, angleUnit, target); +Expression ConfidenceIntervalNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return ConfidenceInterval(this).shallowReduce(context, complexFormat, angleUnit, target); } template @@ -52,9 +52,9 @@ int SimplePredictionIntervalNode::serialize(char * buffer, int bufferSize, Prefe return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, SimplePredictionInterval::s_functionHelper.name()); } -Expression ConfidenceInterval::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression ConfidenceInterval::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } @@ -94,7 +94,7 @@ Expression ConfidenceInterval::shallowReduce(Context & context, Preferences::Ang matrix.addChildAtIndexInPlace(Addition(r0, sqr), 1, 1); matrix.setDimensions(1, 2); replaceWithInPlace(matrix); - matrix.deepReduceChildren(context, angleUnit, target); + matrix.deepReduceChildren(context, complexFormat, angleUnit, target); return matrix; } diff --git a/poincare/src/conjugate.cpp b/poincare/src/conjugate.cpp index 3d2686250..8593b1053 100644 --- a/poincare/src/conjugate.cpp +++ b/poincare/src/conjugate.cpp @@ -23,8 +23,8 @@ int ConjugateNode::serialize(char * buffer, int bufferSize, Preferences::PrintFl return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, Conjugate::s_functionHelper.name()); } -Expression ConjugateNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Conjugate(this).shallowReduce(context, angleUnit, target); +Expression ConjugateNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Conjugate(this).shallowReduce(context, complexFormat, angleUnit, target); } template @@ -32,9 +32,9 @@ Complex ConjugateNode::computeOnComplex(const std::complex c, Preferences: return Complex(std::conj(c)); } -Expression Conjugate::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression Conjugate::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } @@ -53,7 +53,7 @@ Expression Conjugate::shallowReduce(Context & context, Preferences::AngleUnit an ComplexCartesian complexChild = static_cast(c); Multiplication m(Rational(-1), complexChild.imag()); complexChild.replaceChildAtIndexInPlace(1, m); - m.shallowReduce(context, angleUnit, target); + m.shallowReduce(context, complexFormat, angleUnit, target); replaceWithInPlace(complexChild); return complexChild; } diff --git a/poincare/src/constant.cpp b/poincare/src/constant.cpp index c32ca4be0..038ab3400 100644 --- a/poincare/src/constant.cpp +++ b/poincare/src/constant.cpp @@ -45,15 +45,15 @@ Evaluation ConstantNode::templatedApproximate(Context& context, Preferences:: return Complex(M_E); } -Expression ConstantNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Constant(this).shallowReduce(context, angleUnit, target); +Expression ConstantNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Constant(this).shallowReduce(context, complexFormat, angleUnit, target); } Constant::Constant(char name) : SymbolAbstract(TreePool::sharedPool()->createTreeNode(SymbolAbstract::AlignedNodeSize(1, sizeof(ConstantNode)))) { node()->setName(&name, 1); } -Expression Constant::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression Constant::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { if (target == ExpressionNode::ReductionTarget::User && isIComplex()) { ComplexCartesian c = ComplexCartesian::Builder(Rational(0), Rational(1)); replaceWithInPlace(c); diff --git a/poincare/src/cosine.cpp b/poincare/src/cosine.cpp index f5e9fbf04..84c66fc5c 100644 --- a/poincare/src/cosine.cpp +++ b/poincare/src/cosine.cpp @@ -30,13 +30,13 @@ int CosineNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloat return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, Cosine::s_functionHelper.name()); } -Expression CosineNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Cosine(this).shallowReduce(context, angleUnit, target); +Expression CosineNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Cosine(this).shallowReduce(context, complexFormat, angleUnit, target); } -Expression Cosine::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression Cosine::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } @@ -47,7 +47,7 @@ Expression Cosine::shallowReduce(Context & context, Preferences::AngleUnit angle return SimplificationHelper::Map(*this, context, angleUnit); } #endif - return Trigonometry::shallowReduceDirectFunction(*this, context, angleUnit, target); + return Trigonometry::shallowReduceDirectFunction(*this, context, complexFormat, angleUnit, target); } } diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index 5be3623a8..94adda80e 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -56,7 +56,7 @@ size_t DecimalNode::size() const { return DecimalSize(m_numberOfDigitsInMantissa); } -Expression DecimalNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) { +Expression DecimalNode::setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { return Decimal(this).setSign(s); } @@ -85,12 +85,12 @@ int DecimalNode::simplificationOrderSameType(const ExpressionNode * e, bool canB return ((int)Number(this).sign())*unsignedComparison; } -Expression DecimalNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Decimal(this).shallowReduce(context, angleUnit); +Expression DecimalNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Decimal(this).shallowReduce(context, complexFormat, angleUnit); } -Expression DecimalNode::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { - return Decimal(this).shallowBeautify(context, angleUnit); +Expression DecimalNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { + return Decimal(this).shallowBeautify(context, complexFormat, angleUnit); } Layout DecimalNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -342,8 +342,8 @@ Expression Decimal::setSign(ExpressionNode::Sign s) { return result; } -Expression Decimal::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { - Expression e = Expression::defaultShallowReduce(context, angleUnit); +Expression Decimal::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } @@ -370,7 +370,7 @@ Expression Decimal::shallowReduce(Context & context, Preferences::AngleUnit angl return result; } -Expression Decimal::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { +Expression Decimal::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { if (sign() == ExpressionNode::Sign::Negative) { Expression abs = setSign(ExpressionNode::Sign::Positive); Opposite o; diff --git a/poincare/src/derivative.cpp b/poincare/src/derivative.cpp index 33ac1b490..4163b59ae 100644 --- a/poincare/src/derivative.cpp +++ b/poincare/src/derivative.cpp @@ -39,8 +39,8 @@ int DerivativeNode::serialize(char * buffer, int bufferSize, Preferences::PrintF return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, Derivative::s_functionHelper.name()); } -Expression DerivativeNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Derivative(this).shallowReduce(context, angleUnit); +Expression DerivativeNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Derivative(this).shallowReduce(context, complexFormat, angleUnit); } template @@ -137,9 +137,9 @@ T DerivativeNode::riddersApproximation(Context & context, Preferences::AngleUnit return ans; } -Expression Derivative::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression Derivative::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } diff --git a/poincare/src/determinant.cpp b/poincare/src/determinant.cpp index 36bed8767..d73746c53 100644 --- a/poincare/src/determinant.cpp +++ b/poincare/src/determinant.cpp @@ -28,13 +28,13 @@ Evaluation DeterminantNode::templatedApproximate(Context& context, Preference return Complex(input.determinant()); } -Expression DeterminantNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Determinant(this).shallowReduce(context, angleUnit); +Expression DeterminantNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Determinant(this).shallowReduce(context, complexFormat, angleUnit); } -Expression Determinant::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression Determinant::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index 34fbd6c79..d5a8f63ce 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -42,8 +42,8 @@ int DivisionNode::serialize(char * buffer, int bufferSize, Preferences::PrintFlo return SerializationHelper::Infix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, "/"); } -Expression DivisionNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Division(this).shallowReduce(context, angleUnit, target); +Expression DivisionNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Division(this).shallowReduce(context, complexFormat, angleUnit, target); } template Complex DivisionNode::compute(const std::complex c, const std::complex d) { @@ -72,18 +72,18 @@ template MatrixComplex DivisionNode::computeOnMatrices(const Matr Division::Division() : Expression(TreePool::sharedPool()->createTreeNode()) {} -Expression Division::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression Division::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } } Expression p = Power(childAtIndex(1), Rational(-1)); Multiplication m = Multiplication(childAtIndex(0), p); - p.shallowReduce(context, angleUnit, target); // Imagine Division(2,1). p would be 1^(-1) which can be simplified + p.shallowReduce(context, complexFormat, angleUnit, target); // Imagine Division(2,1). p would be 1^(-1) which can be simplified replaceWithInPlace(m); - return m.shallowReduce(context, angleUnit, target); + return m.shallowReduce(context, complexFormat, angleUnit, target); } } diff --git a/poincare/src/division_quotient.cpp b/poincare/src/division_quotient.cpp index bb2e5f4d2..acd244c53 100644 --- a/poincare/src/division_quotient.cpp +++ b/poincare/src/division_quotient.cpp @@ -12,8 +12,8 @@ constexpr Expression::FunctionHelper DivisionQuotient::s_functionHelper; int DivisionQuotientNode::numberOfChildren() const { return DivisionQuotient::s_functionHelper.numberOfChildren(); } -Expression DivisionQuotientNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return DivisionQuotient(this).shallowReduce(context, angleUnit); +Expression DivisionQuotientNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return DivisionQuotient(this).shallowReduce(context, complexFormat, angleUnit); } Layout DivisionQuotientNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -35,9 +35,9 @@ Evaluation DivisionQuotientNode::templatedApproximate(Context& context, Prefe return Complex(std::floor(f1/f2)); } -Expression DivisionQuotient::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression DivisionQuotient::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } diff --git a/poincare/src/division_remainder.cpp b/poincare/src/division_remainder.cpp index 6551d115d..4ed9a1bc5 100644 --- a/poincare/src/division_remainder.cpp +++ b/poincare/src/division_remainder.cpp @@ -20,8 +20,8 @@ int DivisionRemainderNode::serialize(char * buffer, int bufferSize, Preferences: return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, DivisionRemainder::s_functionHelper.name()); } -Expression DivisionRemainderNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return DivisionRemainder(this).shallowReduce(context, angleUnit); +Expression DivisionRemainderNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return DivisionRemainder(this).shallowReduce(context, complexFormat, angleUnit); } template @@ -36,9 +36,9 @@ Evaluation DivisionRemainderNode::templatedApproximate(Context& context, Pref return Complex(std::round(f1-f2*std::floor(f1/f2))); } -Expression DivisionRemainder::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression DivisionRemainder::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } diff --git a/poincare/src/equal.cpp b/poincare/src/equal.cpp index a9e898d22..1c44a35b2 100644 --- a/poincare/src/equal.cpp +++ b/poincare/src/equal.cpp @@ -20,8 +20,8 @@ extern "C" { } namespace Poincare { -Expression EqualNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Equal(this).shallowReduce(context, angleUnit); +Expression EqualNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Equal(this).shallowReduce(context, complexFormat, angleUnit); } Layout EqualNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -41,14 +41,14 @@ Evaluation EqualNode::templatedApproximate(Context& context, Preferences::Ang return Complex::Undefined(); } -Expression Equal::standardEquation(Context & context, Preferences::AngleUnit angleUnit) const { +Expression Equal::standardEquation(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { Expression sub = Subtraction(childAtIndex(0).clone(), childAtIndex(1).clone()); - return sub.reduce(context, angleUnit); + return sub.reduce(context, complexFormat, angleUnit); } -Expression Equal::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression Equal::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index b6ac0eaac..63606669c 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -147,7 +147,7 @@ bool containsVariables(const Expression e, char * variables, int maxVariableSize return false; } -bool Expression::getLinearCoefficients(char * variables, int maxVariableSize, Expression coefficients[], Expression constant[], Context & context, Preferences::AngleUnit angleUnit) const { +bool Expression::getLinearCoefficients(char * variables, int maxVariableSize, Expression coefficients[], Expression constant[], Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { assert(!recursivelyMatches(IsMatrix, context, true)); // variables is in fact of type char[k_maxNumberOfVariables][maxVariableSize] int index = 0; @@ -162,7 +162,7 @@ bool Expression::getLinearCoefficients(char * variables, int maxVariableSize, Ex index = 0; Expression polynomialCoefficients[k_maxNumberOfPolynomialCoefficients]; while (variables[index*maxVariableSize] != 0) { - int degree = equation.getPolynomialReducedCoefficients(&variables[index*maxVariableSize], polynomialCoefficients, context, angleUnit); + int degree = equation.getPolynomialReducedCoefficients(&variables[index*maxVariableSize], polynomialCoefficients, context, complexFormat, angleUnit); switch (degree) { case 0: coefficients[index] = Rational(0); @@ -183,7 +183,7 @@ bool Expression::getLinearCoefficients(char * variables, int maxVariableSize, Ex equation = polynomialCoefficients[0]; index++; } - constant[0] = Opposite(equation.clone()).reduce(context, angleUnit); + constant[0] = Opposite(equation.clone()).reduce(context, complexFormat, angleUnit); /* The expression can be linear on all coefficients taken one by one but * non-linear (ex: xy = 2). We delete the results and return false if one of * the coefficients contains a variable. */ @@ -199,13 +199,13 @@ bool Expression::getLinearCoefficients(char * variables, int maxVariableSize, Ex // Private -void Expression::defaultDeepReduceChildren(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +void Expression::defaultDeepReduceChildren(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { for (int i = 0; i < numberOfChildren(); i++) { - childAtIndex(i).deepReduce(context, angleUnit, target); + childAtIndex(i).deepReduce(context, complexFormat, angleUnit, target); } } -Expression Expression::defaultShallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression Expression::defaultShallowReduce() { for (int i = 0; i < numberOfChildren(); i++) { if (childAtIndex(i).type() == ExpressionNode::Type::Undefined) { Expression result = Undefined(); @@ -246,10 +246,10 @@ Expression Expression::defaultReplaceReplaceableSymbols(Context & context) { return *this; } -Expression Expression::makePositiveAnyNegativeNumeralFactor(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression Expression::makePositiveAnyNegativeNumeralFactor(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { // The expression is a negative number if (isNumber() && sign(&context) == ExpressionNode::Sign::Negative) { - return setSign(ExpressionNode::Sign::Positive, &context, angleUnit, target); + return setSign(ExpressionNode::Sign::Positive, &context, complexFormat, angleUnit, target); } // The expression is a multiplication whose numeral factor is negative if (type() == ExpressionNode::Type::Multiplication && numberOfChildren() > 0 && childAtIndex(0).isNumber() && childAtIndex(0).sign(&context) == ExpressionNode::Sign::Negative) { @@ -261,7 +261,7 @@ Expression Expression::makePositiveAnyNegativeNumeralFactor(Context & context, P return m.squashUnaryHierarchyInPlace(); } else { // Otherwise, we make it positive - m.childAtIndex(0).setSign(ExpressionNode::Sign::Positive, &context, angleUnit, target); + m.childAtIndex(0).setSign(ExpressionNode::Sign::Positive, &context, complexFormat, angleUnit, target); } return m; } @@ -291,11 +291,11 @@ int Expression::defaultGetPolynomialCoefficients(Context & context, const char * return -1; } -int Expression::getPolynomialReducedCoefficients(const char * symbolName, Expression coefficients[], Context & context, Preferences::AngleUnit angleUnit) const { +int Expression::getPolynomialReducedCoefficients(const char * symbolName, Expression coefficients[], Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { // Reset interrupting flag because we use deepReduce int degree = getPolynomialCoefficients(context, symbolName, coefficients); for (int i = 0; i <= degree; i++) { - coefficients[i] = coefficients[i].reduce(context, angleUnit); + coefficients[i] = coefficients[i].reduce(context, complexFormat, angleUnit); } return degree; } @@ -312,6 +312,22 @@ Expression Expression::defaultReplaceUnknown(const Symbol & symbol) { return *this; } +/* Complex */ + +Preferences::ComplexFormat Expression::UpdatedComplexFormatWithTextInput(Preferences::ComplexFormat complexFormat, const char * textInput) { + if (complexFormat == Preferences::ComplexFormat::Real && strchr(textInput, Ion::Charset::IComplex) != nullptr) { + return Preferences::ComplexFormat::Cartesian; + } + return complexFormat; +} + +Preferences::ComplexFormat Expression::UpdatedComplexFormatWithExpressionInput(Preferences::ComplexFormat complexFormat, const Expression & exp, Context & context) { + if (complexFormat == Preferences::ComplexFormat::Real && exp.recursivelyMatches([](const Expression e, Context & context, bool replaceSymbols) { return e.type() == ExpressionNode::Type::Constant && static_cast(e).isIComplex(); }, context, true)) { + return Preferences::ComplexFormat::Cartesian; + } + return complexFormat; +} + /* Comparison */ bool Expression::isIdenticalTo(const Expression e) const { @@ -320,7 +336,7 @@ bool Expression::isIdenticalTo(const Expression e) const { return ExpressionNode::SimplificationOrder(node(), e.node(), true) == 0; } -bool Expression::isEqualToItsApproximationLayout(Expression approximation, char * buffer, int bufferSize, Preferences::AngleUnit angleUnit, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits, Context & context) { +bool Expression::isEqualToItsApproximationLayout(Expression approximation, char * buffer, int bufferSize, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits, Context & context) { approximation.serialize(buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits); /* Warning: we cannot use directly the the approximate expression but we have * to re-serialize it because the number of stored significative @@ -328,7 +344,7 @@ bool Expression::isEqualToItsApproximationLayout(Expression approximation, char * identical. (For example, 0.000025 might be displayed "0.00003" and stored * as Decimal(0.000025) and isEqualToItsApproximationLayout should return * false) */ - Expression approximateOutput = Expression::ParseAndSimplify(buffer, context, angleUnit); + Expression approximateOutput = Expression::ParseAndSimplify(buffer, context, complexFormat, angleUnit); bool equal = isIdenticalTo(approximateOutput); return equal; } @@ -343,12 +359,12 @@ int Expression::serialize(char * buffer, int bufferSize, Preferences::PrintFloat /* Simplification */ -Expression Expression::ParseAndSimplify(const char * text, Context & context, Preferences::AngleUnit angleUnit) { +Expression Expression::ParseAndSimplify(const char * text, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { Expression exp = Parse(text); if (exp.isUninitialized()) { return Undefined(); } - exp = exp.simplify(context, angleUnit); + exp = exp.simplify(context, UpdatedComplexFormatWithTextInput(complexFormat, text), angleUnit); /* simplify might have been interrupted, in which case the resulting * expression is uninitialized, so we need to check that. */ if (exp.isUninitialized()) { @@ -357,7 +373,7 @@ Expression Expression::ParseAndSimplify(const char * text, Context & context, Pr return exp; } -void Expression::ParseAndSimplifyAndApproximate(const char * text, Expression * simplifiedExpression, Expression * approximateExpression, Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) { +void Expression::ParseAndSimplifyAndApproximate(const char * text, Expression * simplifiedExpression, Expression * approximateExpression, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { assert(simplifiedExpression); Expression exp = Parse(text); if (exp.isUninitialized()) { @@ -365,22 +381,22 @@ void Expression::ParseAndSimplifyAndApproximate(const char * text, Expression * *approximateExpression = Undefined(); return; } - exp.simplifyAndApproximate(simplifiedExpression, approximateExpression, context, angleUnit, complexFormat); + exp.simplifyAndApproximate(simplifiedExpression, approximateExpression, context, UpdatedComplexFormatWithTextInput(complexFormat, text), angleUnit); /* simplify might have been interrupted, in which case the resulting * expression is uninitialized, so we need to check that. */ if (simplifiedExpression->isUninitialized()) { *simplifiedExpression = Parse(text); if (approximateExpression) { - *approximateExpression = simplifiedExpression->approximate(context, angleUnit, complexFormat); + *approximateExpression = simplifiedExpression->approximate(context, complexFormat, angleUnit); } } } -Expression Expression::simplify(Context & context, Preferences::AngleUnit angleUnit) { +Expression Expression::simplify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { sSimplificationHasBeenInterrupted = false; - Expression e = deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); + Expression e = deepReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); if (!sSimplificationHasBeenInterrupted) { - e = e.deepBeautify(context, angleUnit); + e = e.deepBeautify(context, complexFormat, angleUnit); } return sSimplificationHasBeenInterrupted ? Expression() : e; } @@ -392,14 +408,14 @@ void makePositive(Expression * e, bool * isNegative) { } } -void Expression::simplifyAndApproximate(Expression * simplifiedExpression, Expression * approximateExpression, Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) { +void Expression::simplifyAndApproximate(Expression * simplifiedExpression, Expression * approximateExpression, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { assert(simplifiedExpression); sSimplificationHasBeenInterrupted = false; // Step 1: we reduce the expression - Expression e = clone().deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); + Expression e = clone().deepReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); if (sSimplificationHasBeenInterrupted) { sSimplificationHasBeenInterrupted = false; - e = deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); + e = deepReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); } *simplifiedExpression = Expression(); if (!sSimplificationHasBeenInterrupted) { @@ -418,15 +434,15 @@ void Expression::simplifyAndApproximate(Expression * simplifiedExpression, Expre // Clone the ComplexCartesian to use it to compute the approximation ComplexCartesian ecomplexClone = ecomplex.clone().convert(); // To minimize the error on the approximation, we reduce the number of nodes in the expression by beautifying - ecomplexClone.real().deepBeautify(context, angleUnit); - ecomplexClone.imag().deepBeautify(context, angleUnit); - *approximateExpression = ecomplexClone.approximate(context, angleUnit, complexFormat); + ecomplexClone.real().deepBeautify(context, complexFormat, angleUnit); + ecomplexClone.imag().deepBeautify(context, complexFormat, angleUnit); + *approximateExpression = ecomplexClone.approximate(context, complexFormat, angleUnit); } // Step 3: create the simplied expression with the required complex format - Expression ra = complexFormat == Preferences::ComplexFormat::Polar ? ecomplex.clone().convert().norm(context, angleUnit, ExpressionNode::ReductionTarget::User).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User) : ecomplex.real(); - Expression tb = complexFormat == Preferences::ComplexFormat::Polar ? ecomplex.argument(context, angleUnit, ExpressionNode::ReductionTarget::User).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User) : ecomplex.imag(); - ra = ra.deepBeautify(context, angleUnit); - tb = tb.deepBeautify(context, angleUnit); + Expression ra = complexFormat == Preferences::ComplexFormat::Polar ? ecomplex.clone().convert().norm(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User).shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User) : ecomplex.real(); + Expression tb = complexFormat == Preferences::ComplexFormat::Polar ? ecomplex.argument(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User).shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User) : ecomplex.imag(); + ra = ra.deepBeautify(context, complexFormat, angleUnit); + tb = tb.deepBeautify(context, complexFormat, angleUnit); bool raIsNegative = false; bool tbIsNegative = false; makePositive(&ra, &raIsNegative); @@ -435,9 +451,9 @@ void Expression::simplifyAndApproximate(Expression * simplifiedExpression, Expre } else { /* Case 2: The reduced expression has a complex component that could not * be bubbled up. */ - *simplifiedExpression = e.deepBeautify(context, angleUnit); + *simplifiedExpression = e.deepBeautify(context, complexFormat, angleUnit); if (approximateExpression) { - *approximateExpression = simplifiedExpression->approximate(context, angleUnit, complexFormat); + *approximateExpression = simplifiedExpression->approximate(context, complexFormat, angleUnit); } } } @@ -484,12 +500,12 @@ Expression Expression::degreeToRadian() { return Multiplication(*this, Rational(1, 180), Constant(Ion::Charset::SmallPi)); } -Expression Expression::reduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression Expression::reduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { sSimplificationHasBeenInterrupted = false; - return deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); + return deepReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); } -Expression Expression::deepReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression Expression::deepReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { #if MATRIX_EXACT_REDUCING #else if (IsMatrix(*this, context, true)) { @@ -498,30 +514,30 @@ Expression Expression::deepReduce(Context & context, Preferences::AngleUnit angl } #endif - deepReduceChildren(context, angleUnit, target); + deepReduceChildren(context, complexFormat, angleUnit, target); if (sSimplificationHasBeenInterrupted) { return *this; } - return shallowReduce(context, angleUnit, target); + return shallowReduce(context, complexFormat, angleUnit, target); } -Expression Expression::deepBeautify(Context & context, Preferences::AngleUnit angleUnit) { - Expression e = shallowBeautify(context, angleUnit); +Expression Expression::deepBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { + Expression e = shallowBeautify(context, complexFormat, angleUnit); int nbChildren = e.numberOfChildren(); for (int i = 0; i < nbChildren; i++) { - e.childAtIndex(i).deepBeautify(context, angleUnit); + e.childAtIndex(i).deepBeautify(context, complexFormat, angleUnit); } return e; } -Expression Expression::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { - return node()->setSign(s, context, angleUnit, target); +Expression Expression::setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + return node()->setSign(s, context, complexFormat, angleUnit, target); } /* Evaluation */ template -Expression Expression::approximate(Context& context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) const { +Expression Expression::approximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { return isUninitialized() ? Undefined() : approximateToEvaluation(context, angleUnit).complexToExpression(complexFormat); } @@ -532,11 +548,9 @@ U Expression::approximateToScalar(Context& context, Preferences::AngleUnit angle } template -U Expression::approximateToScalar(const char * text, Context& context, Preferences::AngleUnit angleUnit) { - Expression exp = ParseAndSimplify(text, context, angleUnit); - if (exp.isUninitialized()) { - return NAN; - } +U Expression::approximateToScalar(const char * text, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { + Expression exp = ParseAndSimplify(text, context, UpdatedComplexFormatWithTextInput(complexFormat, text), angleUnit); + assert(!exp.isUninitialized()); return exp.approximateToScalar(context, angleUnit); } @@ -958,14 +972,14 @@ double Expression::brentRoot(const char * symbol, double ax, double bx, double p template float Expression::epsilon(); template double Expression::epsilon(); -template Expression Expression::approximate(Context& context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) const; -template Expression Expression::approximate(Context& context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) const; +template Expression Expression::approximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; +template Expression Expression::approximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; template float Expression::approximateToScalar(Context& context, Preferences::AngleUnit angleUnit) const; template double Expression::approximateToScalar(Context& context, Preferences::AngleUnit angleUnit) const; -template float Expression::approximateToScalar(const char * text, Context& context, Preferences::AngleUnit angleUnit); -template double Expression::approximateToScalar(const char * text, Context& context, Preferences::AngleUnit angleUnit); +template float Expression::approximateToScalar(const char * text, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); +template double Expression::approximateToScalar(const char * text, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); template Evaluation Expression::approximateToEvaluation(Context& context, Preferences::AngleUnit angleUnit) const; template Evaluation Expression::approximateToEvaluation(Context& context, Preferences::AngleUnit angleUnit) const; diff --git a/poincare/src/expression_node.cpp b/poincare/src/expression_node.cpp index 0a9bbcc63..df89e10c7 100644 --- a/poincare/src/expression_node.cpp +++ b/poincare/src/expression_node.cpp @@ -22,7 +22,7 @@ Expression ExpressionNode::replaceUnknown(const Symbol & symbol) { return Expression(this).defaultReplaceUnknown(symbol); } -Expression ExpressionNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) { +Expression ExpressionNode::setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { assert(false); return Expression(); } @@ -108,16 +108,16 @@ int ExpressionNode::simplificationOrderSameType(const ExpressionNode * e, bool c return 0; } -void ExpressionNode::deepReduceChildren(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { - Expression(this).defaultDeepReduceChildren(context, angleUnit, target); +void ExpressionNode::deepReduceChildren(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + Expression(this).defaultDeepReduceChildren(context, complexFormat, angleUnit, target); } -Expression ExpressionNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Expression(this).defaultShallowReduce(context, angleUnit); +Expression ExpressionNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Expression(this).defaultShallowReduce(); } -Expression ExpressionNode::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { - return Expression(this).defaultShallowBeautify(context, angleUnit); +Expression ExpressionNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { + return Expression(this).defaultShallowBeautify(); } bool ExpressionNode::isOfType(Type * types, int length) const { @@ -133,7 +133,7 @@ void ExpressionNode::setChildrenInPlace(Expression other) { Expression(this).defaultSetChildrenInPlace(other); } -Expression ExpressionNode::denominator(Context & context, Preferences::AngleUnit angleUnit) const { +Expression ExpressionNode::denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { return Expression(); } diff --git a/poincare/src/factor.cpp b/poincare/src/factor.cpp index 1cb6078b3..e1da25442 100644 --- a/poincare/src/factor.cpp +++ b/poincare/src/factor.cpp @@ -26,11 +26,11 @@ int FactorNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloat return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, Factor::s_functionHelper.name()); } -Expression FactorNode::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { - return Factor(this).shallowBeautify(context, angleUnit); +Expression FactorNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { + return Factor(this).shallowBeautify(context, complexFormat, angleUnit); } -Expression Factor::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { +Expression Factor::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { Expression c = childAtIndex(0); if (c.type() != ExpressionNode::Type::Rational) { Expression result = Undefined(); @@ -42,7 +42,7 @@ Expression Factor::shallowBeautify(Context & context, Preferences::AngleUnit ang replaceWithInPlace(r); return r; } - Multiplication numeratorDecomp = createMultiplicationOfIntegerPrimeDecomposition(r.unsignedIntegerNumerator(), context, angleUnit); + Multiplication numeratorDecomp = createMultiplicationOfIntegerPrimeDecomposition(r.unsignedIntegerNumerator(), context, complexFormat, angleUnit); if (numeratorDecomp.numberOfChildren() == 0) { Expression result = Undefined(); replaceWithInPlace(result); @@ -50,7 +50,7 @@ Expression Factor::shallowBeautify(Context & context, Preferences::AngleUnit ang } Expression result = numeratorDecomp.squashUnaryHierarchyInPlace(); if (!r.integerDenominator().isOne()) { - Multiplication denominatorDecomp = createMultiplicationOfIntegerPrimeDecomposition(r.integerDenominator(), context, angleUnit); + Multiplication denominatorDecomp = createMultiplicationOfIntegerPrimeDecomposition(r.integerDenominator(), context, complexFormat, angleUnit); if (denominatorDecomp.numberOfChildren() == 0) { Expression result = Undefined(); replaceWithInPlace(result); @@ -65,7 +65,7 @@ Expression Factor::shallowBeautify(Context & context, Preferences::AngleUnit ang return result; } -Multiplication Factor::createMultiplicationOfIntegerPrimeDecomposition(Integer i, Context & context, Preferences::AngleUnit angleUnit) const { +Multiplication Factor::createMultiplicationOfIntegerPrimeDecomposition(Integer i, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { assert(!i.isZero()); assert(!i.isNegative()); Multiplication m; diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index 5929a02a1..3e4d8d60d 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -14,7 +14,7 @@ namespace Poincare { // Property -Expression FactorialNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) { +Expression FactorialNode::setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { assert(s == Sign::Positive); return Factorial(this); } @@ -34,12 +34,12 @@ bool FactorialNode::childNeedsParenthesis(const TreeNode * child) const { // Simplification -Expression FactorialNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Factorial(this).shallowReduce(context, angleUnit); +Expression FactorialNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Factorial(this).shallowReduce(context, complexFormat, angleUnit); } -Expression FactorialNode::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { - return Factorial(this).shallowBeautify(context, angleUnit); +Expression FactorialNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { + return Factorial(this).shallowBeautify(context, complexFormat, angleUnit); } template @@ -91,9 +91,9 @@ int FactorialNode::serialize(char * buffer, int bufferSize, Preferences::PrintFl Factorial::Factorial() : Expression(TreePool::sharedPool()->createTreeNode()) {} -Expression Factorial::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression Factorial::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } @@ -127,7 +127,7 @@ Expression Factorial::shallowReduce(Context & context, Preferences::AngleUnit an return *this; } -Expression Factorial::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { +Expression Factorial::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { // +(a,b)! ->(+(a,b))! if (childAtIndex(0).type() == ExpressionNode::Type::Addition || childAtIndex(0).type() == ExpressionNode::Type::Multiplication diff --git a/poincare/src/float.cpp b/poincare/src/float.cpp index eecf004ee..8fb98d2e1 100644 --- a/poincare/src/float.cpp +++ b/poincare/src/float.cpp @@ -4,7 +4,7 @@ namespace Poincare { template -Expression FloatNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) { +Expression FloatNode::setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { assert(s != Sign::Unknown); Sign currentSign = m_value < 0 ? Sign::Negative : Sign::Positive; Expression thisExpr = Number(this); diff --git a/poincare/src/floor.cpp b/poincare/src/floor.cpp index 1fa2bc521..97236d5f0 100644 --- a/poincare/src/floor.cpp +++ b/poincare/src/floor.cpp @@ -31,13 +31,13 @@ Complex FloorNode::computeOnComplex(const std::complex c, Preferences::Ang return Complex(std::floor(c.real())); } -Expression FloorNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Floor(this).shallowReduce(context, angleUnit); +Expression FloorNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Floor(this).shallowReduce(context, complexFormat, angleUnit); } -Expression Floor::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression Floor::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } diff --git a/poincare/src/frac_part.cpp b/poincare/src/frac_part.cpp index 3cfd30f64..beae8c161 100644 --- a/poincare/src/frac_part.cpp +++ b/poincare/src/frac_part.cpp @@ -19,8 +19,8 @@ int FracPartNode::serialize(char * buffer, int bufferSize, Preferences::PrintFlo return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, FracPart::s_functionHelper.name()); } -Expression FracPartNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return FracPart(this).shallowReduce(context, angleUnit); +Expression FracPartNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return FracPart(this).shallowReduce(context, complexFormat, angleUnit); } template @@ -31,9 +31,9 @@ Complex FracPartNode::computeOnComplex(const std::complex c, Preferences:: return Complex(c.real()-std::floor(c.real())); } -Expression FracPart::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression FracPart::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } diff --git a/poincare/src/function.cpp b/poincare/src/function.cpp index becd1f6ae..f21d0066e 100644 --- a/poincare/src/function.cpp +++ b/poincare/src/function.cpp @@ -62,8 +62,8 @@ int FunctionNode::serialize(char * buffer, int bufferSize, Preferences::PrintFlo return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, name()); } -Expression FunctionNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Function(this).shallowReduce(context, angleUnit, target); // This uses Symbol::shallowReduce +Expression FunctionNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Function(this).shallowReduce(context, complexFormat, angleUnit, target); // This uses Symbol::shallowReduce } Expression FunctionNode::shallowReplaceReplaceableSymbols(Context & context) { @@ -113,12 +113,12 @@ Expression Function::replaceSymbolWithExpression(const SymbolAbstract & symbol, return *this; } -Expression Function::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression Function::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { Function f(*this); Expression e = SymbolAbstract::Expand(f, context, true); if (!e.isUninitialized()) { replaceWithInPlace(e); - return e.deepReduce(context, angleUnit, target); + return e.deepReduce(context, complexFormat, angleUnit, target); } return *this; } diff --git a/poincare/src/great_common_divisor.cpp b/poincare/src/great_common_divisor.cpp index 5d1cd2265..0dda60aa5 100644 --- a/poincare/src/great_common_divisor.cpp +++ b/poincare/src/great_common_divisor.cpp @@ -20,8 +20,8 @@ int GreatCommonDivisorNode::serialize(char * buffer, int bufferSize, Preferences return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, GreatCommonDivisor::s_functionHelper.name()); } -Expression GreatCommonDivisorNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return GreatCommonDivisor(this).shallowReduce(context, angleUnit); +Expression GreatCommonDivisorNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return GreatCommonDivisor(this).shallowReduce(context, complexFormat, angleUnit); } template @@ -48,9 +48,9 @@ Evaluation GreatCommonDivisorNode::templatedApproximate(Context& context, Pre return Complex(std::round((T)a)); } -Expression GreatCommonDivisor::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression GreatCommonDivisor::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } diff --git a/poincare/src/hyperbolic_trigonometric_function.cpp b/poincare/src/hyperbolic_trigonometric_function.cpp index 812c51d9a..d8f27740b 100644 --- a/poincare/src/hyperbolic_trigonometric_function.cpp +++ b/poincare/src/hyperbolic_trigonometric_function.cpp @@ -2,13 +2,13 @@ namespace Poincare { -Expression HyperbolicTrigonometricFunctionNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return HyperbolicTrigonometricFunction(this).shallowReduce(context, angleUnit); +Expression HyperbolicTrigonometricFunctionNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return HyperbolicTrigonometricFunction(this).shallowReduce(context, complexFormat, angleUnit); } -Expression HyperbolicTrigonometricFunction::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression HyperbolicTrigonometricFunction::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } diff --git a/poincare/src/imaginary_part.cpp b/poincare/src/imaginary_part.cpp index 3f8e14e7d..7667e535b 100644 --- a/poincare/src/imaginary_part.cpp +++ b/poincare/src/imaginary_part.cpp @@ -20,13 +20,13 @@ int ImaginaryPartNode::serialize(char * buffer, int bufferSize, Preferences::Pri return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, ImaginaryPart::s_functionHelper.name()); } -Expression ImaginaryPartNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return ImaginaryPart(this).shallowReduce(context, angleUnit, target); +Expression ImaginaryPartNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return ImaginaryPart(this).shallowReduce(context, complexFormat, angleUnit, target); } -Expression ImaginaryPart::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression ImaginaryPart::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } @@ -46,7 +46,7 @@ Expression ImaginaryPart::shallowReduce(Context & context, Preferences::AngleUni ComplexCartesian complexChild = static_cast(c); Expression i = complexChild.imag(); replaceWithInPlace(i); - return i.shallowReduce(context, angleUnit, target); + return i.shallowReduce(context, complexFormat, angleUnit, target); } return *this; } diff --git a/poincare/src/infinity.cpp b/poincare/src/infinity.cpp index 9b11e2296..23bb83526 100644 --- a/poincare/src/infinity.cpp +++ b/poincare/src/infinity.cpp @@ -9,8 +9,8 @@ extern "C" { namespace Poincare { -Expression InfinityNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Infinity(this).setSign(s, context, angleUnit); +Expression InfinityNode::setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Infinity(this).setSign(s, context, complexFormat, angleUnit); } Layout InfinityNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -30,7 +30,7 @@ template Evaluation InfinityNode::templatedApproximate() const { return Complex(m_negative ? -INFINITY : INFINITY); } -Expression Infinity::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit) { +Expression Infinity::setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { Expression result = Infinity(s == ExpressionNode::Sign::Negative); replaceWithInPlace(result); return result; diff --git a/poincare/src/integral.cpp b/poincare/src/integral.cpp index 0c2c26fd5..7d17fe2d7 100644 --- a/poincare/src/integral.cpp +++ b/poincare/src/integral.cpp @@ -43,8 +43,8 @@ int IntegralNode::serialize(char * buffer, int bufferSize, Preferences::PrintFlo return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, Integral::s_functionHelper.name()); } -Expression IntegralNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Integral(this).shallowReduce(context, angleUnit); +Expression IntegralNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Integral(this).shallowReduce(context, complexFormat, angleUnit); } template @@ -195,9 +195,9 @@ T IntegralNode::adaptiveQuadrature(T a, T b, T eps, int numberOfIterations, Cont } #endif -Expression Integral::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression Integral::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } diff --git a/poincare/src/least_common_multiple.cpp b/poincare/src/least_common_multiple.cpp index e8092e698..aa20c0931 100644 --- a/poincare/src/least_common_multiple.cpp +++ b/poincare/src/least_common_multiple.cpp @@ -21,8 +21,8 @@ int LeastCommonMultipleNode::serialize(char * buffer, int bufferSize, Preference return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, LeastCommonMultiple::s_functionHelper.name()); } -Expression LeastCommonMultipleNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return LeastCommonMultiple(this).shallowReduce(context, angleUnit); +Expression LeastCommonMultipleNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return LeastCommonMultiple(this).shallowReduce(context, complexFormat, angleUnit); } template @@ -53,9 +53,9 @@ Evaluation LeastCommonMultipleNode::templatedApproximate(Context& context, Pr return Complex(product/a); } -Expression LeastCommonMultiple::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression LeastCommonMultiple::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 4295012eb..ccef5b82a 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -48,23 +48,23 @@ int LogarithmNode::serialize(char * buffer, int bufferSize, Preferences::Prin } template<> -Expression LogarithmNode<1>::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { - return CommonLogarithm(this).shallowReduce(context, angleUnit, target); +Expression LogarithmNode<1>::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + return CommonLogarithm(this).shallowReduce(context, complexFormat, angleUnit, target); } template<> -Expression LogarithmNode<2>::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { - return Logarithm(this).shallowReduce(context, angleUnit, target); +Expression LogarithmNode<2>::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + return Logarithm(this).shallowReduce(context, complexFormat, angleUnit, target); } template<> -Expression LogarithmNode<1>::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { +Expression LogarithmNode<1>::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { return CommonLogarithm(this); } template<> -Expression LogarithmNode<2>::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { - return Logarithm(this).shallowBeautify(context, angleUnit); +Expression LogarithmNode<2>::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { + return Logarithm(this).shallowBeautify(context, complexFormat, angleUnit); } template<> @@ -85,9 +85,9 @@ template Evaluation LogarithmNode<2>::templatedApproximate(Contex return Complex(result); } -Expression CommonLogarithm::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target){ +Expression CommonLogarithm::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target){ { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } @@ -102,12 +102,12 @@ Expression CommonLogarithm::shallowReduce(Context & context, Preferences::AngleU #endif Logarithm log = Logarithm::Builder(childAtIndex(0), Rational(10)); replaceWithInPlace(log); - return log.shallowReduce(context, angleUnit, target); + return log.shallowReduce(context, complexFormat, angleUnit, target); } -Expression Logarithm::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target){ +Expression Logarithm::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target){ { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } @@ -123,7 +123,7 @@ Expression Logarithm::shallowReduce(Context & context, Preferences::AngleUnit an if (c.sign(&context) == ExpressionNode::Sign::Negative || childAtIndex(1).sign(&context) == ExpressionNode::Sign::Negative) { return *this; } - Expression f = simpleShallowReduce(context, angleUnit); + Expression f = simpleShallowReduce(context, complexFormat, angleUnit); if (f.type() != ExpressionNode::Type::Logarithm) { return f; } @@ -144,8 +144,8 @@ Expression Logarithm::shallowReduce(Context & context, Preferences::AngleUnit an Multiplication mult(y); replaceWithInPlace(mult); mult.addChildAtIndexInPlace(*this, 1, 1); // --> y*log(x,b) - shallowReduce(context, angleUnit, target); // reduce log (ie log(e, e) = 1) - return mult.shallowReduce(context, angleUnit, target); + shallowReduce(context, complexFormat, angleUnit, target); // reduce log (ie log(e, e) = 1) + return mult.shallowReduce(context, complexFormat, angleUnit, target); } // log(x*y, b)->log(x,b)+log(y, b) if x,y>0 if (!letLogAtRoot && c.type() == ExpressionNode::Type::Multiplication) { @@ -157,15 +157,15 @@ Expression Logarithm::shallowReduce(Context & context, Preferences::AngleUnit an static_cast(c).removeChildInPlace(factor, factor.numberOfChildren()); newLog.replaceChildAtIndexInPlace(0, factor); a.addChildAtIndexInPlace(newLog, a.numberOfChildren(), a.numberOfChildren()); - newLog.shallowReduce(context, angleUnit, target); + newLog.shallowReduce(context, complexFormat, angleUnit, target); } } if (a.numberOfChildren() > 0) { - c.shallowReduce(context, angleUnit, target); - Expression reducedLastLog = shallowReduce(context, angleUnit, target); + c.shallowReduce(context, complexFormat, angleUnit, target); + Expression reducedLastLog = shallowReduce(context, complexFormat, angleUnit, target); reducedLastLog.replaceWithInPlace(a); a.addChildAtIndexInPlace(reducedLastLog, a.numberOfChildren(), a.numberOfChildren()); - return a.shallowReduce(context, angleUnit, target); + return a.shallowReduce(context, complexFormat, angleUnit, target); } } // log(r) with r Rational @@ -180,15 +180,15 @@ Expression Logarithm::shallowReduce(Context & context, Preferences::AngleUnit an r = Rational(newNumerator, newDenomitor); } // log(r) = a0log(p0)+a1log(p1)+... with r = p0^a0*p1^a1*... (Prime decomposition) - a.addChildAtIndexInPlace(splitLogarithmInteger(r.signedIntegerNumerator(), false, context, angleUnit, target), a.numberOfChildren(), a.numberOfChildren()); - a.addChildAtIndexInPlace(splitLogarithmInteger(r.integerDenominator(), true, context, angleUnit, target), a.numberOfChildren(), a.numberOfChildren()); + a.addChildAtIndexInPlace(splitLogarithmInteger(r.signedIntegerNumerator(), false, context, complexFormat, angleUnit, target), a.numberOfChildren(), a.numberOfChildren()); + a.addChildAtIndexInPlace(splitLogarithmInteger(r.integerDenominator(), true, context, complexFormat, angleUnit, target), a.numberOfChildren(), a.numberOfChildren()); replaceWithInPlace(a); - return a.shallowReduce(context, angleUnit, target); + return a.shallowReduce(context, complexFormat, angleUnit, target); } return *this; } -Expression Logarithm::simpleShallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression Logarithm::simpleShallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { Expression c = childAtIndex(0); // log(0,0)->Undefined if (c.type() == ExpressionNode::Type::Rational && childAtIndex(1).type() == ExpressionNode::Type::Rational && childAtIndex(1).convert().isZero() && static_cast(c).isZero()) { @@ -274,7 +274,7 @@ Integer Logarithm::simplifyLogarithmIntegerBaseInteger(Integer i, Integer & base return i; } -Expression Logarithm::splitLogarithmInteger(Integer i, bool isDenominator, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression Logarithm::splitLogarithmInteger(Integer i, bool isDenominator, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { assert(!i.isZero()); assert(!i.isNegative()); Integer factors[Arithmetic::k_maxNumberOfPrimeFactors]; @@ -302,14 +302,14 @@ Expression Logarithm::splitLogarithmInteger(Integer i, bool isDenominator, Conte Logarithm e = clone().convert(); e.replaceChildAtIndexInPlace(0, Rational(factors[index])); Multiplication m = Multiplication(Rational(coefficients[index]), e); - e.simpleShallowReduce(context, angleUnit); + e.simpleShallowReduce(context, complexFormat, angleUnit); a.addChildAtIndexInPlace(m, a.numberOfChildren(), a.numberOfChildren()); - m.shallowReduce(context, angleUnit, target); + m.shallowReduce(context, complexFormat, angleUnit, target); } return a; } -Expression Logarithm::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { +Expression Logarithm::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { assert(numberOfChildren() == 2); Constant e = Constant(Ion::Charset::Exponential); if (childAtIndex(1).isIdenticalTo(e)) { diff --git a/poincare/src/matrix.cpp b/poincare/src/matrix.cpp index 527830845..6d5bd5398 100644 --- a/poincare/src/matrix.cpp +++ b/poincare/src/matrix.cpp @@ -107,9 +107,9 @@ void Matrix::addChildrenAsRowInPlace(TreeHandle t, int i) { setDimensions(previousNumberOfRows + 1, previousNumberOfColumns == 0 ? t.numberOfChildren() : previousNumberOfColumns); } -int Matrix::rank(Context & context, Preferences::AngleUnit angleUnit, bool inPlace) { +int Matrix::rank(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, bool inPlace) { Matrix m = inPlace ? *this : clone().convert(); - m = m.rowCanonize(context, angleUnit); + m = m.rowCanonize(context, complexFormat, angleUnit); int rank = m.numberOfRows(); int i = rank-1; while (i >= 0) { @@ -159,10 +159,10 @@ int Matrix::ArrayInverse(T * array, int numberOfRows, int numberOfColumns) { return 0; } -Matrix Matrix::rowCanonize(Context & context, Preferences::AngleUnit angleUnit, Multiplication determinant) { +Matrix Matrix::rowCanonize(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, Multiplication determinant) { Expression::setInterruption(false); // The matrix children have to be reduced to be able to spot 0 - deepReduceChildren(context, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); + deepReduceChildren(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); int m = numberOfRows(); int n = numberOfColumns(); @@ -198,7 +198,7 @@ Matrix Matrix::rowCanonize(Context & context, Preferences::AngleUnit angleUnit, Expression opHJ = matrixChild(h, j); Expression newOpHJ = Division(opHJ, divisor.clone()); replaceChildAtIndexInPlace(h*n+j, newOpHJ); - newOpHJ = newOpHJ.shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); + newOpHJ = newOpHJ.shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); } replaceChildInPlace(divisor, Rational(1)); @@ -210,8 +210,8 @@ Matrix Matrix::rowCanonize(Context & context, Preferences::AngleUnit angleUnit, Expression opIJ = matrixChild(i, j); Expression newOpIJ = Subtraction(opIJ, Multiplication(matrixChild(h, j).clone(), factor.clone())); replaceChildAtIndexInPlace(i*n+j, newOpIJ); - newOpIJ.childAtIndex(1).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); - newOpIJ = newOpIJ.shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); + newOpIJ.childAtIndex(1).shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); + newOpIJ = newOpIJ.shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); } replaceChildAtIndexInPlace(i*n+k, Rational(0)); } @@ -299,7 +299,7 @@ Matrix Matrix::createIdentity(int dim) { return matrix; } -Expression Matrix::inverse(Context & context, Preferences::AngleUnit angleUnit) const { +Expression Matrix::inverse(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { if (m_numberOfRows != m_numberOfColumns) { return Undefined(); } @@ -315,7 +315,7 @@ Expression Matrix::inverse(Context & context, Preferences::AngleUnit angleUnit) } } AI.setDimensions(dim, 2*dim); - AI = AI.rowCanonize(context, angleUnit); + AI = AI.rowCanonize(context, complexFormat, angleUnit); // Check inversibility for (int i = 0; i < dim; i++) { if (AI.matrixChild(i, i)->type() != ExpressionNode::Type::Rational || !static_cast(AI.matrixChild(i, i)->node())->isOne()) { diff --git a/poincare/src/matrix_dimension.cpp b/poincare/src/matrix_dimension.cpp index e19409552..d1b12ed54 100644 --- a/poincare/src/matrix_dimension.cpp +++ b/poincare/src/matrix_dimension.cpp @@ -11,8 +11,8 @@ constexpr Expression::FunctionHelper MatrixDimension::s_functionHelper; int MatrixDimensionNode::numberOfChildren() const { return MatrixDimension::s_functionHelper.numberOfChildren(); } -Expression MatrixDimensionNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return MatrixDimension(this).shallowReduce(context, angleUnit); +Expression MatrixDimensionNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return MatrixDimension(this).shallowReduce(context, complexFormat, angleUnit); } Layout MatrixDimensionNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -37,9 +37,9 @@ Evaluation MatrixDimensionNode::templatedApproximate(Context& context, Prefer return MatrixComplex(operands, 1, 2); } -Expression MatrixDimension::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression MatrixDimension::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } diff --git a/poincare/src/matrix_inverse.cpp b/poincare/src/matrix_inverse.cpp index 43890f656..eca3f9a69 100644 --- a/poincare/src/matrix_inverse.cpp +++ b/poincare/src/matrix_inverse.cpp @@ -14,8 +14,8 @@ constexpr Expression::FunctionHelper MatrixInverse::s_functionHelper; int MatrixInverseNode::numberOfChildren() const { return MatrixInverse::s_functionHelper.numberOfChildren(); } -Expression MatrixInverseNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return MatrixInverse(this).shallowReduce(context, angleUnit, target); +Expression MatrixInverseNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return MatrixInverse(this).shallowReduce(context, complexFormat, angleUnit, target); } Layout MatrixInverseNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -42,9 +42,9 @@ Evaluation MatrixInverseNode::templatedApproximate(Context& context, Preferen return inverse; } -Expression MatrixInverse::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression MatrixInverse::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } @@ -53,7 +53,7 @@ Expression MatrixInverse::shallowReduce(Context & context, Preferences::AngleUni #if MATRIX_EXACT_REDUCING #if 0 if (!c.recursivelyMatches(Expression::IsMatrix)) { - return Power(c, Rational(-1).shallowReduce(context, angleUnit, target); + return Power(c, Rational(-1).shallowReduce(context, complexFormat, angleUnit, target); } if (c.type() == ExpressionNode::Type::Matrix) { Matrix mat = static_cast(c); @@ -67,7 +67,7 @@ Expression MatrixInverse::shallowReduce(Context & context, Preferences::AngleUni if (c.type() != ExpressionNode::Type::Matrix) { Expression result = Power(c, Rational(-1)); replaceWithInPlace(result); - result = result.shallowReduce(context, angleUnit, target); + result = result.shallowReduce(context, complexFormat, angleUnit, target); return result; } return *this; diff --git a/poincare/src/matrix_trace.cpp b/poincare/src/matrix_trace.cpp index aabe59807..ec7c9a866 100644 --- a/poincare/src/matrix_trace.cpp +++ b/poincare/src/matrix_trace.cpp @@ -13,8 +13,8 @@ constexpr Expression::FunctionHelper MatrixTrace::s_functionHelper; int MatrixTraceNode::numberOfChildren() const { return MatrixTrace::s_functionHelper.numberOfChildren(); } -Expression MatrixTraceNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return MatrixTrace(this).shallowReduce(context, angleUnit); +Expression MatrixTraceNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return MatrixTrace(this).shallowReduce(context, complexFormat, angleUnit); } Layout MatrixTraceNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -32,9 +32,9 @@ Evaluation MatrixTraceNode::templatedApproximate(Context& context, Preference return result; } -Expression MatrixTrace::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression MatrixTrace::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } @@ -52,7 +52,7 @@ Expression MatrixTrace::shallowReduce(Context & context, Preferences::AngleUnit for (int i = 0; i < n; i++) { a.addChildAtIndexInPlace(m.childAtIndex(i+n*i), i, a.numberOfChildren()); } - return a.shallowReduce(context, angleUnit); + return a.shallowReduce(context, complexFormat, angleUnit); } if (!c.recursivelyMatches(Expression::IsMatrix)) { return c; diff --git a/poincare/src/matrix_transpose.cpp b/poincare/src/matrix_transpose.cpp index 41ca47975..f19878254 100644 --- a/poincare/src/matrix_transpose.cpp +++ b/poincare/src/matrix_transpose.cpp @@ -12,8 +12,8 @@ constexpr Expression::FunctionHelper MatrixTranspose::s_functionHelper; int MatrixTransposeNode::numberOfChildren() const { return MatrixTranspose::s_functionHelper.numberOfChildren(); } -Expression MatrixTransposeNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return MatrixTranspose(this).shallowReduce(context, angleUnit); +Expression MatrixTransposeNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return MatrixTranspose(this).shallowReduce(context, complexFormat, angleUnit); } Layout MatrixTransposeNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -37,9 +37,9 @@ Evaluation MatrixTransposeNode::templatedApproximate(Context& context, Prefer return transpose; } -Expression MatrixTranspose::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression MatrixTranspose::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 2a51cf782..9e263b25b 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -66,8 +66,8 @@ MatrixComplex MultiplicationNode::computeOnMatrices(const MatrixComplex m, return result; } -Expression MultiplicationNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Multiplication(this).setSign(s, context, angleUnit, target); +Expression MultiplicationNode::setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Multiplication(this).setSign(s, context, complexFormat, angleUnit, target); } bool MultiplicationNode::childNeedsParenthesis(const TreeNode * child) const { @@ -93,16 +93,16 @@ int MultiplicationNode::serialize(char * buffer, int bufferSize, Preferences::Pr return SerializationHelper::Infix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, multiplicationString); } -Expression MultiplicationNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Multiplication(this).shallowReduce(context, angleUnit, target); +Expression MultiplicationNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Multiplication(this).shallowReduce(context, complexFormat, angleUnit, target); } -Expression MultiplicationNode::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { - return Multiplication(this).shallowBeautify(context, angleUnit); +Expression MultiplicationNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { + return Multiplication(this).shallowBeautify(context, complexFormat, angleUnit); } -Expression MultiplicationNode::denominator(Context & context, Preferences::AngleUnit angleUnit) const { - return Multiplication(this).denominator(context, angleUnit); +Expression MultiplicationNode::denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + return Multiplication(this).denominator(context, complexFormat, angleUnit); } /* Multiplication */ @@ -122,21 +122,21 @@ void Multiplication::computeOnArrays(T * m, T * n, T * result, int mNumberOfColu } } -Expression Multiplication::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression Multiplication::setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { assert(s == ExpressionNode::Sign::Positive); for (int i = 0; i < numberOfChildren(); i++) { if (childAtIndex(i).sign(context) == ExpressionNode::Sign::Negative) { - replaceChildAtIndexInPlace(i, childAtIndex(i).setSign(s, context, angleUnit, target)); + replaceChildAtIndexInPlace(i, childAtIndex(i).setSign(s, context, complexFormat, angleUnit, target)); } } - return shallowReduce(*context, angleUnit, target); + return shallowReduce(*context, complexFormat, angleUnit, target); } -Expression Multiplication::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { - return privateShallowReduce(context, angleUnit, target, true, true); +Expression Multiplication::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + return privateShallowReduce(context, complexFormat, angleUnit, target, true, true); } -Expression Multiplication::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { +Expression Multiplication::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { /* Beautifying a Multiplication consists in several possible operations: * - Add Opposite ((-3)*x -> -(3*x), useful when printing fractions) * - Adding parenthesis if needed (a*(b+c) is not a*b+c) @@ -144,7 +144,7 @@ Expression Multiplication::shallowBeautify(Context & context, Preferences::Angle * shall become a/b) or a non-integer rational term (3/2*a -> (3*a)/2). */ // Step 1: Turn -n*A into -(n*A) - Expression noNegativeNumeral = makePositiveAnyNegativeNumeralFactor(context, angleUnit, ExpressionNode::ReductionTarget::User); + Expression noNegativeNumeral = makePositiveAnyNegativeNumeralFactor(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); // If one negative numeral factor was made positive, we turn the expression in an Opposite if (!noNegativeNumeral.isUninitialized()) { Opposite o = Opposite(); @@ -155,9 +155,9 @@ Expression Multiplication::shallowBeautify(Context & context, Preferences::Angle /* Step 2: Merge negative powers: a*b^(-1)*c^(-pi)*d = a*(b*c^pi)^(-1) * This also turns 2/3*a into 2*a*3^(-1) */ - Expression thisExp = mergeNegativePower(context, angleUnit); + Expression thisExp = mergeNegativePower(context, complexFormat, angleUnit); if (thisExp.type() == ExpressionNode::Type::Power) { - return thisExp.shallowBeautify(context, angleUnit); + return thisExp.shallowBeautify(context, complexFormat, angleUnit); } assert(thisExp.type() == ExpressionNode::Type::Multiplication); @@ -181,7 +181,7 @@ Expression Multiplication::shallowBeautify(Context & context, Preferences::Angle Expression denominatorOperand = childI.childAtIndex(0); removeChildInPlace(childI, childI.numberOfChildren()); - Expression numeratorOperand = shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); + Expression numeratorOperand = shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); // Delete unnecessary parentheses on numerator if (numeratorOperand.type() == ExpressionNode::Type::Parenthesis) { Expression numeratorChild0 = numeratorOperand.childAtIndex(0); @@ -193,7 +193,7 @@ Expression Multiplication::shallowBeautify(Context & context, Preferences::Angle numeratorOperand.replaceWithInPlace(d); d.replaceChildAtIndexInPlace(0, numeratorOperand); d.replaceChildAtIndexInPlace(1, denominatorOperand); - return d.shallowBeautify(context, angleUnit); + return d.shallowBeautify(context, complexFormat, angleUnit); } return thisExp; } @@ -233,13 +233,13 @@ int Multiplication::getPolynomialCoefficients(Context & context, const char * sy return deg; } -Expression Multiplication::denominator(Context & context, Preferences::AngleUnit angleUnit) const { +Expression Multiplication::denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { // Merge negative power: a*b^-1*c^(-Pi)*d = a*(b*c^Pi)^-1 // WARNING: we do not want to change the expression but to create a new one. Multiplication thisClone = clone().convert(); - Expression e = thisClone.mergeNegativePower(context, angleUnit); + Expression e = thisClone.mergeNegativePower(context, complexFormat, angleUnit); if (e.type() == ExpressionNode::Type::Power) { - return e.denominator(context, angleUnit); + return e.denominator(context, complexFormat, angleUnit); } else { assert(e.type() == ExpressionNode::Type::Multiplication); for (int i = 0; i < e.numberOfChildren(); i++) { @@ -255,9 +255,9 @@ Expression Multiplication::denominator(Context & context, Preferences::AngleUnit return Expression(); } -Expression Multiplication::privateShallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target, bool shouldExpand, bool canBeInterrupted) { +Expression Multiplication::privateShallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target, bool shouldExpand, bool canBeInterrupted) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit);; + Expression e = Expression::defaultShallowReduce();; if (e.isUndefined()) { return e; } @@ -323,9 +323,9 @@ Expression Multiplication::privateShallowReduce(Context & context, Preferences:: for (int j = 0; j < n; j++) { Expression * mult = new Multiplication(currentMatrix->childAtIndex(j+om*i1), resultMatrix->childAtIndex(j*m+i2), true); static_cast(newMatrixOperands[e])->addOperand(mult); - mult->shallowReduce(context, angleUnit, target); + mult->shallowReduce(context, complexFormat, angleUnit, target); } - Reduce(&newMatrixOperands[e], context, angleUnit, false); + Reduce(&newMatrixOperands[e], context, complexFormat, angleUnit, false); } n = on; removeOperand(currentMatrix, true); @@ -339,9 +339,9 @@ Expression Multiplication::privateShallowReduce(Context & context, Preferences:: Expression * entryI = resultMatrix->childAtIndex(i); resultMatrix->replaceOperand(entryI, m, false); m->addOperand(entryI); - m->shallowReduce(context, angleUnit, target); + m->shallowReduce(context, complexFormat, angleUnit, target); } - return replaceWith(resultMatrix, true)->shallowReduce(context, angleUnit, target); + return replaceWith(resultMatrix, true)->shallowReduce(context, complexFormat, angleUnit, target); } #endif #endif @@ -363,11 +363,11 @@ Expression Multiplication::privateShallowReduce(Context & context, Preferences:: shouldFactorizeBase = oi.type() == ExpressionNode::Type::Power && oi1.type() == ExpressionNode::Type::Power; } if (shouldFactorizeBase) { - factorizeBase(i, i+1, context, angleUnit, target); + factorizeBase(i, i+1, context, complexFormat, angleUnit, target); continue; } } else if (TermHasNumeralBase(oi) && TermHasNumeralBase(oi1) && TermsHaveIdenticalExponent(oi, oi1)) { - factorizeExponent(i, i+1, context, angleUnit, target); + factorizeExponent(i, i+1, context, complexFormat, angleUnit, target); continue; } i++; @@ -387,7 +387,7 @@ Expression Multiplication::privateShallowReduce(Context & context, Preferences:: for (int j = i+1; j < numberOfChildren(); j++) { Expression o2 = childAtIndex(j); if (Base(o2).type() == ExpressionNode::Type::Cosine && TermHasNumeralExponent(o2) && Base(o2).childAtIndex(0).isIdenticalTo(x)) { - factorizeSineAndCosine(i, j, context, angleUnit); + factorizeSineAndCosine(i, j, context, complexFormat, angleUnit); break; } } @@ -456,7 +456,7 @@ Expression Multiplication::privateShallowReduce(Context & context, Preferences:: if (target != ExpressionNode::ReductionTarget::BottomUpComputation && shouldExpand && (p.isUninitialized() || p.type() != ExpressionNode::Type::Multiplication)) { for (int i = 0; i < numberOfChildren(); i++) { if (childAtIndex(i).type() == ExpressionNode::Type::Addition) { - return distributeOnOperandAtIndex(i, context, angleUnit, target); + return distributeOnOperandAtIndex(i, context, complexFormat, angleUnit, target); } } } @@ -490,7 +490,7 @@ Expression Multiplication::privateShallowReduce(Context & context, Preferences:: // the Multiplication is sorted so ComplexCartesian nodes are the last ones break; } - child = child.multiply(static_cast(e), context, angleUnit, target); + child = child.multiply(static_cast(e), context, complexFormat, angleUnit, target); removeChildAtIndexInPlace(i); i--; } @@ -503,9 +503,9 @@ Expression Multiplication::privateShallowReduce(Context & context, Preferences:: replaceWithInPlace(newComplexCartesian); newComplexCartesian.replaceChildAtIndexInPlace(0, real); newComplexCartesian.replaceChildAtIndexInPlace(1, imag); - real.shallowReduce(context, angleUnit, target); - imag.shallowReduce(context, angleUnit, target); - return newComplexCartesian.shallowReduce(context, angleUnit); + real.shallowReduce(context, complexFormat, angleUnit, target); + imag.shallowReduce(context, complexFormat, angleUnit, target); + return newComplexCartesian.shallowReduce(context, complexFormat, angleUnit); } return result; @@ -524,7 +524,7 @@ void Multiplication::mergeMultiplicationChildrenInPlace() { } } -void Multiplication::factorizeBase(int i, int j, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +void Multiplication::factorizeBase(int i, int j, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { /* This function factorizes two children which have a common base. For example * if this is Multiplication(pi^2, pi^3), then pi^2 and pi^3 could be merged * and this turned into Multiplication(pi^5). */ @@ -533,10 +533,10 @@ void Multiplication::factorizeBase(int i, int j, Context & context, Preferences: // Step 1: Get rid of the child j removeChildAtIndexInPlace(j); // Step 2: Merge child j in child i by factorizing base - mergeInChildByFactorizingBase(i, e, context, angleUnit, target); + mergeInChildByFactorizingBase(i, e, context, complexFormat, angleUnit, target); } -void Multiplication::mergeInChildByFactorizingBase(int i, Expression e, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +void Multiplication::mergeInChildByFactorizingBase(int i, Expression e, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { /* This function replace the child at index i by its factorization with e. e * and childAtIndex(i) are supposed to have a common base. */ @@ -544,10 +544,10 @@ void Multiplication::mergeInChildByFactorizingBase(int i, Expression e, Context Expression s = Addition(CreateExponent(childAtIndex(i)), CreateExponent(e)); // pi^2*pi^3 -> pi^(2+3) -> pi^5 // Step 2: Create the new Power Expression p = Power(Base(childAtIndex(i)), s); // pi^2*pi^-2 -> pi^0 -> 1 - s.shallowReduce(context, angleUnit, target); + s.shallowReduce(context, complexFormat, angleUnit, target); // Step 3: Replace one of the child replaceChildAtIndexInPlace(i, p); - p = p.shallowReduce(context, angleUnit, target); + p = p.shallowReduce(context, complexFormat, angleUnit, target); /* Step 4: Reducing the new power might have turned it into a multiplication, * ie: 12^(1/2) -> 2*3^(1/2). In that case, we need to merge the multiplication * node with this. */ @@ -556,7 +556,7 @@ void Multiplication::mergeInChildByFactorizingBase(int i, Expression e, Context } } -void Multiplication::factorizeExponent(int i, int j, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +void Multiplication::factorizeExponent(int i, int j, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { /* This function factorizes children which share a common exponent. For * example, it turns Multiplication(2^x,3^x) into Multiplication(6^x). */ @@ -567,8 +567,8 @@ void Multiplication::factorizeExponent(int i, int j, Context & context, Preferen // Step 3: Replace the other child childAtIndex(i).replaceChildAtIndexInPlace(0, m); // Step 4: Reduce expressions - m.shallowReduce(context, angleUnit, target); - Expression p = childAtIndex(i).shallowReduce(context, angleUnit, target); // 2^x*(1/2)^x -> (2*1/2)^x -> 1 + m.shallowReduce(context, complexFormat, angleUnit, target); + Expression p = childAtIndex(i).shallowReduce(context, complexFormat, angleUnit, target); // 2^x*(1/2)^x -> (2*1/2)^x -> 1 /* Step 5: Reducing the new power might have turned it into a multiplication, * ie: 12^(1/2) -> 2*3^(1/2). In that case, we need to merge the multiplication * node with this. */ @@ -577,7 +577,7 @@ void Multiplication::factorizeExponent(int i, int j, Context & context, Preferen } } -Expression Multiplication::distributeOnOperandAtIndex(int i, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression Multiplication::distributeOnOperandAtIndex(int i, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { /* This method creates a*...*b*y... + a*...*c*y... + ... from * a*...*(b+c+...)*y... */ assert(i >= 0 && i < numberOfChildren()); @@ -591,16 +591,16 @@ Expression Multiplication::distributeOnOperandAtIndex(int i, Context & context, m.replaceChildAtIndexInPlace(i, childI.childAtIndex(j)); // Reduce m: pi^(-1)*(pi + x) -> pi^(-1)*pi + pi^(-1)*x -> 1 + pi^(-1)*x a.addChildAtIndexInPlace(m, a.numberOfChildren(), a.numberOfChildren()); - m.shallowReduce(context, angleUnit, target); + m.shallowReduce(context, complexFormat, angleUnit, target); } replaceWithInPlace(a); - return a.shallowReduce(context, angleUnit, target); // Order terms, put under a common denominator if needed + return a.shallowReduce(context, complexFormat, angleUnit, target); // Order terms, put under a common denominator if needed } -void Multiplication::addMissingFactors(Expression factor, Context & context, Preferences::AngleUnit angleUnit) { +void Multiplication::addMissingFactors(Expression factor, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { if (factor.type() == ExpressionNode::Type::Multiplication) { for (int j = 0; j < factor.numberOfChildren(); j++) { - addMissingFactors(factor.childAtIndex(j), context, angleUnit); + addMissingFactors(factor.childAtIndex(j), context, complexFormat, angleUnit); } return; } @@ -623,7 +623,7 @@ void Multiplication::addMissingFactors(Expression factor, Context & context, Pre * base if any. Otherwise, we add it as an new child. */ for (int i = 0; i < numberOfChildren(); i++) { if (TermsHaveIdenticalBase(childAtIndex(i), factor)) { - Expression sub = Subtraction(CreateExponent(childAtIndex(i)), CreateExponent(factor)).deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); + Expression sub = Subtraction(CreateExponent(childAtIndex(i)), CreateExponent(factor)).deepReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); if (sub.sign(&context) == ExpressionNode::Sign::Negative) { // index[0] < index[1] sub = Opposite(sub); if (factor.type() == ExpressionNode::Type::Power) { @@ -631,10 +631,10 @@ void Multiplication::addMissingFactors(Expression factor, Context & context, Pre } else { factor = Power(factor, sub); } - sub.shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); - mergeInChildByFactorizingBase(i, factor, context, angleUnit, ExpressionNode::ReductionTarget::User); + sub.shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); + mergeInChildByFactorizingBase(i, factor, context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); } else if (sub.sign(&context) == ExpressionNode::Sign::Unknown) { - mergeInChildByFactorizingBase(i, factor, context, angleUnit, ExpressionNode::ReductionTarget::User); + mergeInChildByFactorizingBase(i, factor, context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); } return; } @@ -644,7 +644,7 @@ void Multiplication::addMissingFactors(Expression factor, Context & context, Pre sortChildrenInPlace(ExpressionNode::SimplificationOrder, false); } -void Multiplication::factorizeSineAndCosine(int i, int j, Context & context, Preferences::AngleUnit angleUnit) { +void Multiplication::factorizeSineAndCosine(int i, int j, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { /* This function turn sin(x)^p * cos(x)^q into either: * - tan(x)^p*cos(x)^(p+q) if |p|<|q| * - tan(x)^(-q)*sin(x)^(p+q) otherwise */ @@ -667,19 +667,19 @@ void Multiplication::factorizeSineAndCosine(int i, int j, Context & context, Pre } else { replaceChildAtIndexInPlace(i, Power(tan, p)); } - childAtIndex(i).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); + childAtIndex(i).shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); // Replace cos(x)^q by cos(x)^(p+q) replaceChildAtIndexInPlace(j, Power(Base(childAtIndex(j)), sumPQ)); - childAtIndex(j).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); + childAtIndex(j).shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); } else { // Replace cos(x)^q by tan(x)^(-q) Expression newPower = Power(tan, Number::Multiplication(q, Rational(-1))); - newPower.childAtIndex(1).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); + newPower.childAtIndex(1).shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); replaceChildAtIndexInPlace(j, newPower); - newPower.shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); + newPower.shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); // Replace sin(x)^p by sin(x)^(p+q) replaceChildAtIndexInPlace(i, Power(Base(childAtIndex(i)), sumPQ)); - childAtIndex(i).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); + childAtIndex(i).shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); } } @@ -730,7 +730,7 @@ bool Multiplication::TermHasNumeralExponent(const Expression & e) { return false; } -Expression Multiplication::mergeNegativePower(Context & context, Preferences::AngleUnit angleUnit) { +Expression Multiplication::mergeNegativePower(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { /* mergeNegativePower groups all factors that are power of form a^(-b) together * for instance, a^(-1)*b^(-c)*c = c*(a*b^c)^(-1) */ Multiplication m; @@ -749,7 +749,7 @@ Expression Multiplication::mergeNegativePower(Context & context, Preferences::An while (i < numberOfChildren()) { if (childAtIndex(i).type() == ExpressionNode::Type::Power) { Expression p = childAtIndex(i); - Expression positivePIndex = p.childAtIndex(1).makePositiveAnyNegativeNumeralFactor(context, angleUnit, ExpressionNode::ReductionTarget::User); + Expression positivePIndex = p.childAtIndex(1).makePositiveAnyNegativeNumeralFactor(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); if (!positivePIndex.isUninitialized()) { // Remove a^(-b) from the Multiplication removeChildAtIndexInPlace(i); diff --git a/poincare/src/naperian_logarithm.cpp b/poincare/src/naperian_logarithm.cpp index 852476d02..351c359b6 100644 --- a/poincare/src/naperian_logarithm.cpp +++ b/poincare/src/naperian_logarithm.cpp @@ -18,13 +18,13 @@ int NaperianLogarithmNode::serialize(char * buffer, int bufferSize, Preferences: return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, NaperianLogarithm::s_functionHelper.name()); } -Expression NaperianLogarithmNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return NaperianLogarithm(this).shallowReduce(context, angleUnit, target); +Expression NaperianLogarithmNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return NaperianLogarithm(this).shallowReduce(context, complexFormat, angleUnit, target); } -Expression NaperianLogarithm::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression NaperianLogarithm::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } @@ -36,7 +36,7 @@ Expression NaperianLogarithm::shallowReduce(Context & context, Preferences::Angl #endif Logarithm l = Logarithm::Builder(childAtIndex(0), Constant(Ion::Charset::Exponential)); replaceWithInPlace(l); - return l.shallowReduce(context, angleUnit, target); + return l.shallowReduce(context, complexFormat, angleUnit, target); } } diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index f4cdca87b..303dadd48 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -28,8 +28,8 @@ int NthRootNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloa return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, NthRoot::s_functionHelper.name()); } -Expression NthRootNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return NthRoot(this).shallowReduce(context, angleUnit, target); +Expression NthRootNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return NthRoot(this).shallowReduce(context, complexFormat, angleUnit, target); } template @@ -47,9 +47,9 @@ Evaluation NthRootNode::templatedApproximate(Context& context, Preferences::A return result; } -Expression NthRoot::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression NthRoot::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } @@ -61,9 +61,9 @@ Expression NthRoot::shallowReduce(Context & context, Preferences::AngleUnit angl #endif Expression invIndex = Power(childAtIndex(1), Rational(-1)); Power p = Power(childAtIndex(0), invIndex); - invIndex.shallowReduce(context, angleUnit, target); + invIndex.shallowReduce(context, complexFormat, angleUnit, target); replaceWithInPlace(p); - return p.shallowReduce(context, angleUnit, target); + return p.shallowReduce(context, complexFormat, angleUnit, target); } } diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index 5edd341fe..5b67ade67 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -62,16 +62,16 @@ int OppositeNode::serialize(char * buffer, int bufferSize, Preferences::PrintFlo return numberOfChar; } -Expression OppositeNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Opposite(this).shallowReduce(context, angleUnit, target); +Expression OppositeNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Opposite(this).shallowReduce(context, complexFormat, angleUnit, target); } /* Simplification */ Opposite::Opposite() : Expression(TreePool::sharedPool()->createTreeNode()) {} -Expression Opposite::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { - Expression result = Expression::defaultShallowReduce(context, angleUnit); +Expression Opposite::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + Expression result = Expression::defaultShallowReduce(); if (result.isUndefined()) { return result; } @@ -80,7 +80,7 @@ Expression Opposite::shallowReduce(Context & context, Preferences::AngleUnit ang #endif result = Multiplication(Rational(-1), child); replaceWithInPlace(result); - return result.shallowReduce(context, angleUnit, target); + return result.shallowReduce(context, complexFormat, angleUnit, target); } } diff --git a/poincare/src/parenthesis.cpp b/poincare/src/parenthesis.cpp index 32b5152b5..981879045 100644 --- a/poincare/src/parenthesis.cpp +++ b/poincare/src/parenthesis.cpp @@ -16,8 +16,8 @@ int ParenthesisNode::serialize(char * buffer, int bufferSize, Preferences::Print return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, ""); } -Expression ParenthesisNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Parenthesis(this).shallowReduce(context, angleUnit); +Expression ParenthesisNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Parenthesis(this).shallowReduce(context, complexFormat, angleUnit); } template @@ -25,8 +25,8 @@ Evaluation ParenthesisNode::templatedApproximate(Context& context, Preference return childAtIndex(0)->approximate(T(), context, angleUnit); } -Expression Parenthesis::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { - Expression e = Expression::defaultShallowReduce(context, angleUnit); +Expression Parenthesis::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } diff --git a/poincare/src/permute_coefficient.cpp b/poincare/src/permute_coefficient.cpp index 8970f23a0..4087c64cc 100644 --- a/poincare/src/permute_coefficient.cpp +++ b/poincare/src/permute_coefficient.cpp @@ -23,8 +23,8 @@ int PermuteCoefficientNode::serialize(char * buffer, int bufferSize, Preferences return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, PermuteCoefficient::s_functionHelper.name()); } -Expression PermuteCoefficientNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return PermuteCoefficient(this).shallowReduce(context, angleUnit); +Expression PermuteCoefficientNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return PermuteCoefficient(this).shallowReduce(context, complexFormat, angleUnit); } template @@ -49,9 +49,9 @@ Evaluation PermuteCoefficientNode::templatedApproximate(Context& context, Pre return Complex(std::round(result)); } -Expression PermuteCoefficient::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression PermuteCoefficient::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 1baf6d147..0d69de5bb 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -47,8 +47,8 @@ ExpressionNode::Sign PowerNode::sign(Context * context) const { return Sign::Unknown; } -Expression PowerNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Power(this).setSign(s, context, angleUnit, target); +Expression PowerNode::setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Power(this).setSign(s, context, complexFormat, angleUnit, target); } int PowerNode::polynomialDegree(Context & context, const char * symbolName) const { @@ -164,12 +164,12 @@ int PowerNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatM // Simplify -Expression PowerNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Power(this).shallowReduce(context, angleUnit, target); +Expression PowerNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Power(this).shallowReduce(context, complexFormat, angleUnit, target); } -Expression PowerNode::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { - return Power(this).shallowBeautify(context, angleUnit); +Expression PowerNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { + return Power(this).shallowBeautify(context, complexFormat, angleUnit); } int PowerNode::simplificationOrderGreaterType(const ExpressionNode * e, bool canBeInterrupted) const { @@ -191,8 +191,8 @@ int PowerNode::simplificationOrderSameType(const ExpressionNode * e, bool canBeI return SimplificationOrder(childAtIndex(1), e->childAtIndex(1), canBeInterrupted); } -Expression PowerNode::denominator(Context & context, Preferences::AngleUnit angleUnit) const { - return Power(this).denominator(context, angleUnit); +Expression PowerNode::denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + return Power(this).denominator(context, complexFormat, angleUnit); } // Evaluation @@ -238,12 +238,12 @@ Power::Power(Expression base, Expression exponent) : Expression(TreePool::shared replaceChildAtIndexInPlace(1, exponent); } -Expression Power::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression Power::setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { assert(s == ExpressionNode::Sign::Positive); if (childAtIndex(0).sign(context) == ExpressionNode::Sign::Negative) { - Expression result = Power(childAtIndex(0).setSign(ExpressionNode::Sign::Positive, context, angleUnit, target), childAtIndex(1)); + Expression result = Power(childAtIndex(0).setSign(ExpressionNode::Sign::Positive, context, complexFormat, angleUnit, target), childAtIndex(1)); replaceWithInPlace(result); - return result.shallowReduce(*context, angleUnit, target); + return result.shallowReduce(*context, complexFormat, angleUnit, target); } return *this; } @@ -279,10 +279,10 @@ int Power::getPolynomialCoefficients(Context & context, const char * symbolName, return -1; } -Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } @@ -304,8 +304,8 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU return replaceWith(new Undefined(), true); } if (exponent.isNegative()) { - childAtIndex(1)->setSign(Sign::Positive, context, angleUnit); - Expression * newMatrix = shallowReduce(context, angleUnit, target); + childAtIndex(1)->setSign(Sign::Positive, context, complexFormat, angleUnit); + Expression * newMatrix = shallowReduce(context, complexFormat, angleUnit, target); Expression * parent = newMatrix->parent(); MatrixInverse * inv = new MatrixInverse(newMatrix, false); parent->replaceOperand(newMatrix, inv, false); @@ -325,7 +325,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU result->addOperand(mat->clone()); } replaceWith(result, true); - return result->shallowReduce(context, angleUnit, target); + return result->shallowReduce(context, complexFormat, angleUnit, target); } #endif #endif @@ -420,25 +420,25 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU Rational r = static_cast(index); if (r.isMinusOne()) { // (x+iy)^(-1) - result = complexBase.inverse(context, angleUnit, target); + result = complexBase.inverse(context, complexFormat, angleUnit, target); } else if (r.isHalf()) { // (x+iy)^(1/2) - result = complexBase.squareRoot(context, angleUnit, target); + result = complexBase.squareRoot(context, complexFormat, angleUnit, target); } else if (r.isMinusHalf()) { // (x+iy)^(-1/2) - result = complexBase.squareRoot(context, angleUnit, target).inverse(context, angleUnit, target); + result = complexBase.squareRoot(context, complexFormat, angleUnit, target).inverse(context, complexFormat, angleUnit, target); } else if (r.integerDenominator().isOne() && r.unsignedIntegerNumerator().isLowerThan(ten)) { if (r.sign() == ExpressionNode::Sign::Positive) { // (x+iy)^n, n integer positive n < 10 - result = complexBase.powerInteger(r.unsignedIntegerNumerator().extractedInt(), context, angleUnit, target); + result = complexBase.powerInteger(r.unsignedIntegerNumerator().extractedInt(), context, complexFormat, angleUnit, target); } else { // (x+iy)^(-n), n integer positive n < 10 - result = complexBase.powerInteger(r.unsignedIntegerNumerator().extractedInt(), context, angleUnit, target).inverse(context, angleUnit, target); + result = complexBase.powerInteger(r.unsignedIntegerNumerator().extractedInt(), context, complexFormat, angleUnit, target).inverse(context, complexFormat, angleUnit, target); } } if (!result.isUninitialized()) { replaceWithInPlace(result); - return result.shallowReduce(context, angleUnit); + return result.shallowReduce(context, complexFormat, angleUnit); } } } @@ -448,15 +448,15 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU (!letPowerAtRoot && base.type() == ExpressionNode::Type::ComplexCartesian && index.type() == ExpressionNode::Type::ComplexCartesian)) { complexBase = base.type() == ExpressionNode::Type::ComplexCartesian ? static_cast(base) : ComplexCartesian::Builder(base, Rational(0)); complexIndex = index.type() == ExpressionNode::Type::ComplexCartesian ? static_cast(index) : ComplexCartesian::Builder(index, Rational(0)); - result = complexBase.power(complexIndex, context, angleUnit, target); + result = complexBase.power(complexIndex, context, complexFormat, angleUnit, target); replaceWithInPlace(result); - return result.shallowReduce(context, angleUnit); + return result.shallowReduce(context, complexFormat, angleUnit); } /* Step 3: We look for square root and sum of square roots (two terms maximum * so far) at the denominator and move them to the numerator. */ if (target == ExpressionNode::ReductionTarget::User) { - Expression r = removeSquareRootsFromDenominator(context, angleUnit); + Expression r = removeSquareRootsFromDenominator(context, complexFormat, angleUnit); if (!r.isUninitialized()) { return r; } @@ -468,9 +468,9 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU // i^(p/q) if (childAtIndex(0).type() == ExpressionNode::Type::Constant && childAtIndex(0).convert().isIComplex()) { Number r = Number::Multiplication(b, Rational(1, 2)); - Expression result = CreateComplexExponent(r, context, angleUnit, target); + Expression result = CreateComplexExponent(r, context, complexFormat, angleUnit, target); replaceWithInPlace(result); - return result.shallowReduce(context, angleUnit, target); + return result.shallowReduce(context, complexFormat, angleUnit, target); } } @@ -487,12 +487,12 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU // (-inf)^x --> (-1)^x*inf Power p(Rational(-1), childAtIndex(1)); result = Multiplication(p, result); - p.shallowReduce(context, angleUnit, target); + p.shallowReduce(context, complexFormat, angleUnit, target); } } if (!result.isUninitialized()) { replaceWithInPlace(result); - return result.shallowReduce(context, angleUnit, target); + return result.shallowReduce(context, complexFormat, angleUnit, target); } } @@ -506,7 +506,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU if (RationalExponentShouldNotBeReduced(a, exp)) { return *this; } - return simplifyRationalRationalPower(context, angleUnit, target); + return simplifyRationalRationalPower(context, complexFormat, angleUnit, target); } } // Step 7: (a)^(1/2) with a < 0 --> i*(-a)^(1/2) @@ -516,7 +516,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU && childAtIndex(1).type() == ExpressionNode::Type::Rational && childAtIndex(1).convert().isHalf()) { - Expression m0 = childAtIndex(0).makePositiveAnyNegativeNumeralFactor(context, angleUnit, target); + Expression m0 = childAtIndex(0).makePositiveAnyNegativeNumeralFactor(context, complexFormat, angleUnit, target); if (!m0.isUninitialized()) { replaceChildAtIndexInPlace(0, m0); // m0 doest not need to be shallowReduce as makePositiveAnyNegativeNumeralFactor returns a reduced expression @@ -525,10 +525,10 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU // Multiply m1 by i complex Constant i(Ion::Charset::IComplex); m1.addChildAtIndexInPlace(i, 0, 0); - i.shallowReduce(context, angleUnit, target); + i.shallowReduce(context, complexFormat, angleUnit, target); m1.addChildAtIndexInPlace(*this, 1, 1); - shallowReduce(context, angleUnit, target); - return m1.shallowReduce(context, angleUnit, target); + shallowReduce(context, complexFormat, angleUnit, target); + return m1.shallowReduce(context, complexFormat, angleUnit, target); } } // Step 8: e^(i*Pi*r) with r rational --> cos(pi*r) + i*sin(pi*r) @@ -540,15 +540,15 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU m.replaceChildAtIndexInPlace(m.numberOfChildren()-1, Rational(180)); } Expression cos = Cosine::Builder(m); - m = m.shallowReduce(context, angleUnit, target); + m = m.shallowReduce(context, complexFormat, angleUnit, target); Expression sin = Sine::Builder(m.clone()); Expression complexPart = Multiplication(sin, i); - sin.shallowReduce(context, angleUnit, target); + sin.shallowReduce(context, complexFormat, angleUnit, target); Expression a = Addition(cos, complexPart); - cos.shallowReduce(context, angleUnit, target); - complexPart.shallowReduce(context, angleUnit, target); + cos.shallowReduce(context, complexFormat, angleUnit, target); + complexPart.shallowReduce(context, complexFormat, angleUnit, target); replaceWithInPlace(a); - return a.shallowReduce(context, angleUnit, target); + return a.shallowReduce(context, complexFormat, angleUnit, target); } // Step 9: x^log(y,x)->y if y > 0 if (childAtIndex(1).type() == ExpressionNode::Type::Logarithm) { @@ -578,7 +578,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU || (childAtIndex(1).type() == ExpressionNode::Type::Rational && childAtIndex(1).convert().integerDenominator().isOne())) { - return simplifyPowerPower(context, angleUnit, target); + return simplifyPowerPower(context, complexFormat, angleUnit, target); } } // Step 11: (a*b*c*...)^r ? @@ -586,7 +586,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU Multiplication m = childAtIndex(0).convert(); // Case 1: (a*b*c*...)^n = a^n*b^n*c^n*... if n integer if (childAtIndex(1).type() == ExpressionNode::Type::Rational && childAtIndex(1).convert().integerDenominator().isOne()) { - return simplifyPowerMultiplication(context, angleUnit, target); + return simplifyPowerMultiplication(context, complexFormat, angleUnit, target); } // Case 2: (a*b*...)^r -> |a|^r*(sign(a)*b*...)^r if a not -1 for (int i = 0; i < m.numberOfChildren(); i++) { @@ -602,11 +602,11 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU // (sign(a)*b*...)^r if (factor.sign(&context) == ExpressionNode::Sign::Negative) { m.replaceChildAtIndexInPlace(i, Rational(-1)); - factor = factor.setSign(ExpressionNode::Sign::Positive, &context, angleUnit, target); + factor = factor.setSign(ExpressionNode::Sign::Positive, &context, complexFormat, angleUnit, target); } else { m.removeChildAtIndexInPlace(i); } - m.shallowReduce(context, angleUnit, target); + m.shallowReduce(context, complexFormat, angleUnit, target); // |a|^r Power p = Power(factor, rCopy); @@ -616,9 +616,9 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU Multiplication root = Multiplication(p); replaceWithInPlace(root); root.addChildAtIndexInPlace(thisRef, 1, 1); - p.shallowReduce(context, angleUnit, target); - thisRef.shallowReduce(context, angleUnit, target); - return root.shallowReduce(context, angleUnit, target); + p.shallowReduce(context, complexFormat, angleUnit, target); + thisRef.shallowReduce(context, complexFormat, angleUnit, target); + return root.shallowReduce(context, complexFormat, angleUnit, target); } } } @@ -644,8 +644,8 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU Multiplication m = Multiplication(p1); replaceWithInPlace(m); m.addChildAtIndexInPlace(thisRef, 1, 1); - p1.simplifyRationalRationalPower(context, angleUnit, target); - return m.shallowReduce(context, angleUnit, target); + p1.simplifyRationalRationalPower(context, complexFormat, angleUnit, target); + return m.shallowReduce(context, complexFormat, angleUnit, target); } } @@ -681,28 +681,28 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU // We need a 'double' distribution and newA will hold the new expanded form Expression newA = Addition(); for (int j = 0; j < a.numberOfChildren(); j++) { - Expression m = Multiplication(result.clone(), a.childAtIndex(j).clone()).distributeOnOperandAtIndex(0, context, angleUnit, target); + Expression m = Multiplication(result.clone(), a.childAtIndex(j).clone()).distributeOnOperandAtIndex(0, context, complexFormat, angleUnit, target); if (newA.type() == ExpressionNode::Type::Addition) { static_cast(newA).addChildAtIndexInPlace(m, newA.numberOfChildren(), newA.numberOfChildren()); } else { newA = Addition(newA, m); } - newA = newA.shallowReduce(context, angleUnit, target); + newA = newA.shallowReduce(context, complexFormat, angleUnit, target); } result.replaceWithInPlace(newA); result = newA; } else { // Just distribute result on a Multiplication m = Multiplication(a.clone(), result.clone()); - Expression distributedM = m.distributeOnOperandAtIndex(0, context, angleUnit, target); + Expression distributedM = m.distributeOnOperandAtIndex(0, context, complexFormat, angleUnit, target); result.replaceWithInPlace(distributedM); result = distributedM; - result = result.shallowReduce(context, angleUnit, target); + result = result.shallowReduce(context, complexFormat, angleUnit, target); } } if (nr.sign() == ExpressionNode::Sign::Negative) { nr.replaceWithInPlace(Rational(-1)); - return shallowReduce(context, angleUnit, target); + return shallowReduce(context, complexFormat, angleUnit, target); } else { replaceWithInPlace(result); return result; @@ -729,32 +729,32 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU Power * p1 = new Power(x1->clone(), new Rational(clippedN-i), false); const Expression * operands[3] = {r, p0, p1}; Multiplication * m = new Multiplication(operands, 3, false); - p0->shallowReduce(context, angleUnit, target); - p1->shallowReduce(context, angleUnit, target); + p0->shallowReduce(context, complexFormat, angleUnit, target); + p1->shallowReduce(context, complexFormat, angleUnit, target); a->addOperand(m); - m->shallowReduce(context, angleUnit, target); + m->shallowReduce(context, complexFormat, angleUnit, target); } if (nr->sign(&context) == Sign::Negative) { nr->replaceWith(new Rational(-1), true); - childAtIndex(0)->replaceWith(a, true)->shallowReduce(context, angleUnit, target); - return shallowReduce(context, angleUnit, target); + childAtIndex(0)->replaceWith(a, true)->shallowReduce(context, complexFormat, angleUnit, target); + return shallowReduce(context, complexFormat, angleUnit, target); } else { - return replaceWith(a, true)->shallowReduce(context, angleUnit, target); + return replaceWith(a, true)->shallowReduce(context, complexFormat, angleUnit, target); } } #endif return *this; } -Expression Power::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { +Expression Power::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { // Step 1: X^-y -> 1/(X->shallowBeautify)^y - Expression p = denominator(context, angleUnit); + Expression p = denominator(context, complexFormat, angleUnit); // If the denominator is initialized, the index of the power is of form -y if (!p.isUninitialized()) { Division d = Division(Rational(1), p); - p.shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); + p.shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); replaceWithInPlace(d); - return d.shallowBeautify(context, angleUnit); + return d.shallowBeautify(context, complexFormat, angleUnit); } // Step 2: Turn a^(1/n) into root(a, n) if (childAtIndex(1).type() == ExpressionNode::Type::Rational && childAtIndex(1).convert().signedIntegerNumerator().isOne()) { @@ -783,11 +783,11 @@ Expression Power::shallowBeautify(Context & context, Preferences::AngleUnit angl // Private // Simplification -Expression Power::denominator(Context & context, Preferences::AngleUnit angleUnit) const { +Expression Power::denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { // Clone the power Expression clone = Power(childAtIndex(0).clone(), childAtIndex(1).clone()); // If the power is of form x^(-y), denominator should be x^y - Expression positiveIndex = clone.childAtIndex(1).makePositiveAnyNegativeNumeralFactor(context, angleUnit, ExpressionNode::ReductionTarget::User); + Expression positiveIndex = clone.childAtIndex(1).makePositiveAnyNegativeNumeralFactor(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); if (!positiveIndex.isUninitialized()) { // if y was -1, clone is now x^1, denominator is then only x // we cannot shallowReduce the clone as it is not attached to its parent yet @@ -799,30 +799,30 @@ Expression Power::denominator(Context & context, Preferences::AngleUnit angleUni return Expression(); } -Expression Power::simplifyPowerPower(Context& context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression Power::simplifyPowerPower(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { // this is p^e = (a^b)^e, we want a^(b*e) Expression p = childAtIndex(0); Multiplication m(p.childAtIndex(1), childAtIndex(1)); replaceChildAtIndexInPlace(0, p.childAtIndex(0)); replaceChildAtIndexInPlace(1, m); - m.shallowReduce(context, angleUnit, target); - return shallowReduce(context, angleUnit, target); + m.shallowReduce(context, complexFormat, angleUnit, target); + return shallowReduce(context, complexFormat, angleUnit, target); } -Expression Power::simplifyPowerMultiplication(Context& context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression Power::simplifyPowerMultiplication(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { // this is m^r= (a*b*c*...)^r, we want a^r * b^r *c^r * ... Expression m = childAtIndex(0); Expression r = childAtIndex(1); for (int index = 0; index < m.numberOfChildren(); index++) { Power p = Power(m.childAtIndex(index).clone(), r.clone()); // We copy r and factor to avoid inheritance issues m.replaceChildAtIndexInPlace(index, p); - p.shallowReduce(context, angleUnit, target); + p.shallowReduce(context, complexFormat, angleUnit, target); } replaceWithInPlace(m); - return m.shallowReduce(context, angleUnit, target); + return m.shallowReduce(context, complexFormat, angleUnit, target); } -Expression Power::simplifyRationalRationalPower(Context& context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression Power::simplifyRationalRationalPower(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { // this is a^b with a, b rationals Rational a = childAtIndex(0).convert(); Rational b = childAtIndex(1).convert(); @@ -838,18 +838,18 @@ Expression Power::simplifyRationalRationalPower(Context& context, Preferences::A Expression d; if (b.sign() == ExpressionNode::Sign::Negative) { b.setSign(ExpressionNode::Sign::Positive); - n = CreateSimplifiedIntegerRationalPower(a.integerDenominator(), b, false, context, angleUnit, target); - d = CreateSimplifiedIntegerRationalPower(a.signedIntegerNumerator(), b, true, context, angleUnit, target); + n = CreateSimplifiedIntegerRationalPower(a.integerDenominator(), b, false, context, complexFormat, angleUnit, target); + d = CreateSimplifiedIntegerRationalPower(a.signedIntegerNumerator(), b, true, context, complexFormat, angleUnit, target); } else { - n = CreateSimplifiedIntegerRationalPower(a.signedIntegerNumerator(), b, false, context, angleUnit, target); - d = CreateSimplifiedIntegerRationalPower(a.integerDenominator(), b, true, context, angleUnit, target); + n = CreateSimplifiedIntegerRationalPower(a.signedIntegerNumerator(), b, false, context, complexFormat, angleUnit, target); + d = CreateSimplifiedIntegerRationalPower(a.integerDenominator(), b, true, context, complexFormat, angleUnit, target); } Multiplication m = Multiplication(n, d); replaceWithInPlace(m); - return m.shallowReduce(context, angleUnit, target); + return m.shallowReduce(context, complexFormat, angleUnit, target); } -Expression Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational r, bool isDenominator, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational r, bool isDenominator, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { assert(!i.isZero()); assert(r.sign() == ExpressionNode::Sign::Positive); if (i.isOne()) { @@ -861,7 +861,7 @@ Expression Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational r, bo if (numberOfPrimeFactors < 0) { /* We could not break i in prime factors (it might take either too many * factors or too much time). */ - Expression rClone = r.clone().setSign(isDenominator ? ExpressionNode::Sign::Negative : ExpressionNode::Sign::Positive, &context, angleUnit, target); + Expression rClone = r.clone().setSign(isDenominator ? ExpressionNode::Sign::Negative : ExpressionNode::Sign::Positive, &context, complexFormat, angleUnit, target); return Power(Rational(i), rClone); } @@ -893,15 +893,15 @@ Expression Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational r, bo m.addChildAtIndexInPlace(p, 1, 1); } if (i.isNegative()) { - Expression exp = CreateComplexExponent(r, context, angleUnit, target); + Expression exp = CreateComplexExponent(r, context, complexFormat, angleUnit, target); m.addChildAtIndexInPlace(exp, m.numberOfChildren(), m.numberOfChildren()); - exp.shallowReduce(context, angleUnit, target); + exp.shallowReduce(context, complexFormat, angleUnit, target); } m.sortChildrenInPlace(PowerNode::SimplificationOrder, false); return m; } -Expression Power::removeSquareRootsFromDenominator(Context & context, Preferences::AngleUnit angleUnit) { +Expression Power::removeSquareRootsFromDenominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { Expression result; if (childAtIndex(0).type() == ExpressionNode::Type::Rational && childAtIndex(1).type() == ExpressionNode::Type::Rational @@ -928,7 +928,7 @@ Expression Power::removeSquareRootsFromDenominator(Context & context, Preference } else { result = Multiplication(Rational(one, p), sqrt); // We use here the assertion that p != 0 } - sqrt.shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); + sqrt.shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); } } else if (childAtIndex(1).type() == ExpressionNode::Type::Rational && childAtIndex(1).convert().isMinusOne() @@ -996,14 +996,14 @@ Expression Power::removeSquareRootsFromDenominator(Context & context, Preference if (denominator.isInfinity() || factor1.isInfinity() || factor2.isInfinity() || pq1.isInfinity() || pq2.isInfinity()) { return result; // Escape } - numerator = numerator.deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); + numerator = numerator.deepReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); Integer one(1); result = Multiplication(numerator, Rational(one, denominator)); } if (!result.isUninitialized()) { replaceWithInPlace(result); - result = result.shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::User); + result = result.shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); } return result; } @@ -1079,22 +1079,22 @@ Expression Power::equivalentExpressionUsingStandardExpression() const { return Expression(); } -Expression Power::CreateComplexExponent(const Expression & r, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression Power::CreateComplexExponent(const Expression & r, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { // Returns e^(i*pi*r) const Constant exp = Constant(Ion::Charset::Exponential); Constant iComplex = Constant(Ion::Charset::IComplex); const Constant pi = Constant(Ion::Charset::SmallPi); Multiplication mExp = Multiplication(iComplex, pi, r.clone()); - iComplex.shallowReduce(context, angleUnit, target); + iComplex.shallowReduce(context, complexFormat, angleUnit, target); Power p(exp, mExp); - mExp.shallowReduce(context, angleUnit, target); + mExp.shallowReduce(context, complexFormat, angleUnit, target); return p; #if 0 const Constant iComplex = Constant(Ion::Charset::IComplex); const Constant pi = Constant(Ion::Charset::SmallPi); - Expression op = Multiplication(pi, r).shallowReduce(context, angleUnit, false); - Cosine cos = Cosine(op).shallowReduce(context, angleUnit, false);; - Sine sin = Sine(op).shallowReduce(context, angleUnit, false); + Expression op = Multiplication(pi, r).shallowReduce(context, complexFormat, angleUnit, false); + Cosine cos = Cosine(op).shallowReduce(context, complexFormat, angleUnit, false);; + Sine sin = Sine(op).shallowReduce(context, complexFormat, angleUnit, false); Expression m = Multiplication(iComplex, sin); Expression a = Addition(cos, m); const Expression * multExpOperands[3] = {pi, r->clone()}; diff --git a/poincare/src/prediction_interval.cpp b/poincare/src/prediction_interval.cpp index 8f0a659b3..a294a5640 100644 --- a/poincare/src/prediction_interval.cpp +++ b/poincare/src/prediction_interval.cpp @@ -27,8 +27,8 @@ int PredictionIntervalNode::serialize(char * buffer, int bufferSize, Preferences } -Expression PredictionIntervalNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return PredictionInterval(this).shallowReduce(context, angleUnit, target); +Expression PredictionIntervalNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return PredictionInterval(this).shallowReduce(context, complexFormat, angleUnit, target); } template @@ -46,9 +46,9 @@ Evaluation PredictionIntervalNode::templatedApproximate(Context& context, Pre return MatrixComplex(operands, 1, 2); } -Expression PredictionInterval::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression PredictionInterval::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } @@ -102,7 +102,7 @@ Expression PredictionInterval::shallowReduce(Context & context, Preferences::Ang matrix.addChildAtIndexInPlace(Addition(r0.clone(), m), 1, 1); matrix.setDimensions(1, 2); replaceWithInPlace(matrix); - matrix.deepReduceChildren(context, angleUnit, target); + matrix.deepReduceChildren(context, complexFormat, angleUnit, target); return matrix; } diff --git a/poincare/src/random.cpp b/poincare/src/random.cpp index 11a959e01..737082864 100644 --- a/poincare/src/random.cpp +++ b/poincare/src/random.cpp @@ -12,8 +12,8 @@ constexpr Expression::FunctionHelper Random::s_functionHelper; int RandomNode::numberOfChildren() const { return Random::s_functionHelper.numberOfChildren(); } -Expression RandomNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Random(this).setSign(s, context, angleUnit); +Expression RandomNode::setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Random(this).setSign(s, context, complexFormat, angleUnit); } Layout RandomNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -28,7 +28,7 @@ template Evaluation RandomNode::templateApproximate() const { return Complex(Random::random()); } -Expression Random::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit) { +Expression Random::setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { assert(s == ExpressionNode::Sign::Positive); return *this; } diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index 48fb40659..ae11ffcaf 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -98,7 +98,7 @@ int RationalNode::serialize(char * buffer, int bufferSize, Preferences::PrintFlo // Expression subclassing -Expression RationalNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) { +Expression RationalNode::setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { return Rational(this).setSign(s); } @@ -143,16 +143,16 @@ int RationalNode::simplificationOrderSameType(const ExpressionNode * e, bool can // Simplification -Expression RationalNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Rational(this).shallowReduce(context, angleUnit); +Expression RationalNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Rational(this).shallowReduce(context, complexFormat, angleUnit); } -Expression RationalNode::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { - return Rational(this).shallowBeautify(context, angleUnit); +Expression RationalNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { + return Rational(this).shallowBeautify(context, complexFormat, angleUnit); } -Expression RationalNode::denominator(Context & context, Preferences::AngleUnit angleUnit) const { - return Rational(this).denominator(context, angleUnit); +Expression RationalNode::denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + return Rational(this).denominator(context, complexFormat, angleUnit); } /* Rational */ @@ -233,7 +233,7 @@ Rational::Rational(const native_uint_t * i, uint8_t numeratorSize, const native_ static_cast(node())->setDigits(i, numeratorSize, j, denominatorSize, negative); } -Expression Rational::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression Rational::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { // FIXME: /* Infinite Rational should not exist as they aren't parsed and are supposed * to be turn in Float if they should appear. We assert(false) so far, but @@ -259,7 +259,7 @@ Expression Rational::shallowReduce(Context & context, Preferences::AngleUnit ang return *this; } -Expression Rational::shallowBeautify(Context & context, Preferences::AngleUnit angleUnit) { +Expression Rational::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { if (sign() == ExpressionNode::Sign::Negative) { Expression abs = setSign(ExpressionNode::Sign::Positive); Opposite o; @@ -270,7 +270,7 @@ Expression Rational::shallowBeautify(Context & context, Preferences::AngleUnit a return *this; } -Expression Rational::denominator(Context & context, Preferences::AngleUnit angleUnit) const { +Expression Rational::denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { Integer d = integerDenominator(); if (d.isOne()) { return Expression(); diff --git a/poincare/src/real_part.cpp b/poincare/src/real_part.cpp index 0458f0038..4d5e58c7e 100644 --- a/poincare/src/real_part.cpp +++ b/poincare/src/real_part.cpp @@ -20,13 +20,13 @@ int RealPartNode::serialize(char * buffer, int bufferSize, Preferences::PrintFlo return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, RealPart::s_functionHelper.name()); } -Expression RealPartNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return RealPart(this).shallowReduce(context, angleUnit, target); +Expression RealPartNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return RealPart(this).shallowReduce(context, complexFormat, angleUnit, target); } -Expression RealPart::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression RealPart::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } @@ -45,7 +45,7 @@ Expression RealPart::shallowReduce(Context & context, Preferences::AngleUnit ang ComplexCartesian complexChild = static_cast(c); Expression r = complexChild.real(); replaceWithInPlace(r); - return r.shallowReduce(context, angleUnit, target); + return r.shallowReduce(context, complexFormat, angleUnit, target); } return *this; } diff --git a/poincare/src/round.cpp b/poincare/src/round.cpp index eea75450a..d6f105ae6 100644 --- a/poincare/src/round.cpp +++ b/poincare/src/round.cpp @@ -21,8 +21,8 @@ int RoundNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatM return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, Round::s_functionHelper.name()); } -Expression RoundNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Round(this).shallowReduce(context, angleUnit); +Expression RoundNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Round(this).shallowReduce(context, complexFormat, angleUnit); } template @@ -38,9 +38,9 @@ Evaluation RoundNode::templatedApproximate(Context& context, Preferences::Ang return Complex(std::round(f1*err)/err); } -Expression Round::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression Round::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } diff --git a/poincare/src/sign_function.cpp b/poincare/src/sign_function.cpp index 88867021c..ce7bd9868 100644 --- a/poincare/src/sign_function.cpp +++ b/poincare/src/sign_function.cpp @@ -17,7 +17,7 @@ ExpressionNode::Sign SignFunctionNode::sign(Context * context) const { return childAtIndex(0)->sign(context); } -Expression SignFunctionNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) { +Expression SignFunctionNode::setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { SignFunction sign(this); Rational r(s == ExpressionNode::Sign::Positive ? 1 : -1); sign.replaceWithInPlace(r); @@ -32,8 +32,8 @@ int SignFunctionNode::serialize(char * buffer, int bufferSize, Preferences::Prin return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, SignFunction::s_functionHelper.name()); } -Expression SignFunctionNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return SignFunction(this).shallowReduce(context, angleUnit, target); +Expression SignFunctionNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return SignFunction(this).shallowReduce(context, complexFormat, angleUnit, target); } template @@ -47,9 +47,9 @@ Complex SignFunctionNode::computeOnComplex(const std::complex c, Preferenc return Complex(1.0); } -Expression SignFunction::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression SignFunction::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } @@ -73,7 +73,7 @@ Expression SignFunction::shallowReduce(Context & context, Preferences::AngleUnit // c has no sign (c is complex or NAN) if (std::isnan(c.imag()) || std::isnan(c.real()) || c.imag() != 0) { // sign(-x) = -sign(x) - Expression oppChild = child.makePositiveAnyNegativeNumeralFactor(context, angleUnit, target); + Expression oppChild = child.makePositiveAnyNegativeNumeralFactor(context, complexFormat, angleUnit, target); if (oppChild.isUninitialized()) { return *this; } else { diff --git a/poincare/src/simplification_helper.cpp b/poincare/src/simplification_helper.cpp index 3afadd465..ce828c6a4 100644 --- a/poincare/src/simplification_helper.cpp +++ b/poincare/src/simplification_helper.cpp @@ -4,17 +4,17 @@ namespace Poincare { // TODO Use clones -Expression SimplificationHelper::Map(const Expression & e, Context & context, Preferences::AngleUnit angleUnit) { +Expression SimplificationHelper::Map(const Expression & e, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { assert(e->numberOfChildren() == 1 && e->childAtIndex(0)->type() == ExpressionNode::Type::Matrix); Expression c = e.childAtIndex(0); Matrix matrix; for (int i = 0; i < c->numberOfChildren(); i++) { Expression f = e.replaceChildAtIndexInPlace(0, e.childAtIndex(0).childAtIndex(i)); matrix.addChildAtIndexInPlace(f, i, i); - f.shallowReduce(context, angleUnit); + f.shallowReduce(context, complexFormat, angleUnit); } replaceWithInPlace(matrix); - return matrix.shallowReduce(context, angleUnit); + return matrix.shallowReduce(context, complexFormat, angleUnit); } } diff --git a/poincare/src/sine.cpp b/poincare/src/sine.cpp index e34607158..a04bd527f 100644 --- a/poincare/src/sine.cpp +++ b/poincare/src/sine.cpp @@ -30,13 +30,13 @@ int SineNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMo return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, Sine::s_functionHelper.name()); } -Expression SineNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Sine(this).shallowReduce(context, angleUnit, target); +Expression SineNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Sine(this).shallowReduce(context, complexFormat, angleUnit, target); } -Expression Sine::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression Sine::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } @@ -47,7 +47,7 @@ Expression Sine::shallowReduce(Context & context, Preferences::AngleUnit angleUn return SimplificationHelper::Map(*this, context, angleUnit); } #endif - return Trigonometry::shallowReduceDirectFunction(*this, context, angleUnit, target); + return Trigonometry::shallowReduceDirectFunction(*this, context, complexFormat, angleUnit, target); } } diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index 53f7379fd..253f473b4 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -38,13 +38,13 @@ Complex SquareRootNode::computeOnComplex(const std::complex c, Preferences return Complex(ApproximationHelper::TruncateRealOrImaginaryPartAccordingToArgument(result)); } -Expression SquareRootNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return SquareRoot(this).shallowReduce(context, angleUnit, target); +Expression SquareRootNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return SquareRoot(this).shallowReduce(context, complexFormat, angleUnit, target); } -Expression SquareRoot::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression SquareRoot::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } @@ -56,7 +56,7 @@ Expression SquareRoot::shallowReduce(Context & context, Preferences::AngleUnit a #endif Power p = Power(childAtIndex(0), Rational(1, 2)); replaceWithInPlace(p); - return p.shallowReduce(context, angleUnit, target); + return p.shallowReduce(context, complexFormat, angleUnit, target); } } diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index 3aa3f341d..afac6fd1f 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -15,12 +15,12 @@ extern "C" { namespace Poincare { -void StoreNode::deepReduceChildren(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +void StoreNode::deepReduceChildren(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { return; } -Expression StoreNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Store(this).shallowReduce(context, angleUnit); +Expression StoreNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Store(this).shallowReduce(context, complexFormat, angleUnit); } int StoreNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -50,7 +50,7 @@ Evaluation StoreNode::templatedApproximate(Context& context, Preferences::Ang return e.approximateToEvaluation(context, angleUnit); } -Expression Store::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression Store::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { Expression finalValue; if (symbol().type() == ExpressionNode::Type::Function) { // In tata + 2 ->f(tata), replace tata with xUnknown symbol diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index f6ce7a4f6..3e410f31d 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -52,22 +52,22 @@ template MatrixComplex SubtractionNode::computeOnComplexAndMatrix return result; } -Expression SubtractionNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Subtraction(this).shallowReduce(context, angleUnit, target); +Expression SubtractionNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Subtraction(this).shallowReduce(context, complexFormat, angleUnit, target); } Subtraction::Subtraction() : Expression(TreePool::sharedPool()->createTreeNode()) {} -Expression Subtraction::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { - Expression e = Expression::defaultShallowReduce(context, angleUnit); +Expression Subtraction::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } Expression m = Multiplication(Rational(-1), childAtIndex(1)); Addition a(childAtIndex(0), m); - m = m.shallowReduce(context, angleUnit, target); + m = m.shallowReduce(context, complexFormat, angleUnit, target); replaceWithInPlace(a); - return a.shallowReduce(context, angleUnit, target); + return a.shallowReduce(context, complexFormat, angleUnit, target); } } diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 7fe6e3e06..8a83647a1 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -117,8 +117,8 @@ int SymbolNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloat return strlcpy(buffer, m_name, bufferSize); } -Expression SymbolNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Symbol(this).shallowReduce(context, angleUnit, target); +Expression SymbolNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Symbol(this).shallowReduce(context, complexFormat, angleUnit, target); } Expression SymbolNode::shallowReplaceReplaceableSymbols(Context & context) { @@ -157,7 +157,7 @@ bool Symbol::isRegressionSymbol(const char * c) { return false; } -Expression Symbol::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression Symbol::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { Symbol s = *this; Expression result = SymbolAbstract::Expand(s, context, true); if (result.isUninitialized()) { @@ -165,7 +165,7 @@ Expression Symbol::shallowReduce(Context & context, Preferences::AngleUnit angle } replaceWithInPlace(result); // The stored expression is as entered by the user, so we need to call reduce - return result.deepReduce(context, angleUnit, target); + return result.deepReduce(context, complexFormat, angleUnit, target); } Expression Symbol::replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression) { diff --git a/poincare/src/symbol_abstract.cpp b/poincare/src/symbol_abstract.cpp index 91eedcf46..2fd65125b 100644 --- a/poincare/src/symbol_abstract.cpp +++ b/poincare/src/symbol_abstract.cpp @@ -37,12 +37,12 @@ ExpressionNode::Sign SymbolAbstractNode::sign(Context * context) const { return e.sign(context); } -Expression SymbolAbstractNode::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit, ReductionTarget target) { +Expression SymbolAbstractNode::setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { SymbolAbstract sa(this); Expression e = SymbolAbstract::Expand(sa, *context, true); assert(!e.isUninitialized()); sa.replaceWithInPlace(e); - return e.setSign(s, context, angleUnit, target); + return e.setSign(s, context, complexFormat, angleUnit, target); } int SymbolAbstractNode::simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const { diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp index dceb282df..01e342b50 100644 --- a/poincare/src/tangent.cpp +++ b/poincare/src/tangent.cpp @@ -33,13 +33,13 @@ Complex TangentNode::computeOnComplex(const std::complex c, Preferences::A return Complex(Trigonometry::RoundToMeaningfulDigits(res, angleInput)); } -Expression TangentNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Tangent(this).shallowReduce(context, angleUnit, target); +Expression TangentNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Tangent(this).shallowReduce(context, complexFormat, angleUnit, target); } -Expression Tangent::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression Tangent::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { - Expression e = Expression::defaultShallowReduce(context, angleUnit); + Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } @@ -50,15 +50,15 @@ Expression Tangent::shallowReduce(Context & context, Preferences::AngleUnit angl return SimplificationHelper::Map(*this, context, angleUnit); } #endif - Expression newExpression = Trigonometry::shallowReduceDirectFunction(*this, context, angleUnit, target); + Expression newExpression = Trigonometry::shallowReduceDirectFunction(*this, context, complexFormat, angleUnit, target); if (newExpression.type() == ExpressionNode::Type::Tangent) { Sine s = Sine::Builder(newExpression.childAtIndex(0).clone()); Cosine c = Cosine::Builder(newExpression.childAtIndex(0)); Division d = Division(s, c); - s.shallowReduce(context, angleUnit, target); - c.shallowReduce(context, angleUnit, target); + s.shallowReduce(context, complexFormat, angleUnit, target); + c.shallowReduce(context, complexFormat, angleUnit, target); newExpression.replaceWithInPlace(d); - return d.shallowReduce(context, angleUnit, target); + return d.shallowReduce(context, complexFormat, angleUnit, target); } return newExpression; } diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 06c14476f..92622c91c 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -83,11 +83,11 @@ bool Trigonometry::ExpressionIsEquivalentToTangent(const Expression & e) { return false; } -Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { assert(isDirectTrigonometryFunction(e)); // Step 1. Try finding an easy standard calculation reduction - Expression lookup = Trigonometry::table(e.childAtIndex(0), e.type(), context, angleUnit, target); + Expression lookup = Trigonometry::table(e.childAtIndex(0), e.type(), context, complexFormat, angleUnit, target); if (!lookup.isUninitialized()) { e.replaceWithInPlace(lookup); return lookup; @@ -115,14 +115,14 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& co Rational(1,2) ); // reduce x^2 - sqrt.childAtIndex(0).childAtIndex(1).childAtIndex(1).shallowReduce(context, angleUnit, target); + sqrt.childAtIndex(0).childAtIndex(1).childAtIndex(1).shallowReduce(context, complexFormat, angleUnit, target); // reduce -1*x^2 - sqrt.childAtIndex(0).childAtIndex(1).shallowReduce(context, angleUnit, target); + sqrt.childAtIndex(0).childAtIndex(1).shallowReduce(context, complexFormat, angleUnit, target); // reduce 1-1*x^2 - sqrt.childAtIndex(0).shallowReduce(context, angleUnit, target); + sqrt.childAtIndex(0).shallowReduce(context, complexFormat, angleUnit, target); e.replaceWithInPlace(sqrt); // reduce sqrt(1+(-1)*x^2) - return sqrt.shallowReduce(context, angleUnit, target); + return sqrt.shallowReduce(context, complexFormat, angleUnit, target); } // Step 4. Look for an expression of type "cos(arctan(x))" or "sin(arctan(x))" @@ -144,33 +144,33 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& co ); // reduce x^2 - res.childAtIndex(0).childAtIndex(1).shallowReduce(context, angleUnit, target); + res.childAtIndex(0).childAtIndex(1).shallowReduce(context, complexFormat, angleUnit, target); // reduce 1+*x^2 - res.childAtIndex(0).shallowReduce(context, angleUnit, target); + res.childAtIndex(0).shallowReduce(context, complexFormat, angleUnit, target); if (e.type() == ExpressionNode::Type::Sine) { res = Multiplication(x, res); // reduce (1+x^2)^(-1/2) - res.childAtIndex(0).shallowReduce(context, angleUnit, target); + res.childAtIndex(0).shallowReduce(context, complexFormat, angleUnit, target); } e.replaceWithInPlace(res); // reduce (1+x^2)^(-1/2) or x*(1+x^2)^(-1/2) - return res.shallowReduce(context, angleUnit, target); + return res.shallowReduce(context, complexFormat, angleUnit, target); } // Step 5. Look for an expression of type "cos(-a)", return "+/-cos(a)" - Expression positiveArg = e.childAtIndex(0).makePositiveAnyNegativeNumeralFactor(context, angleUnit, target); + Expression positiveArg = e.childAtIndex(0).makePositiveAnyNegativeNumeralFactor(context, complexFormat, angleUnit, target); if (!positiveArg.isUninitialized()) { // The argument was of form cos(-a) if (e.type() == ExpressionNode::Type::Cosine) { // cos(-a) = cos(a) - return e.shallowReduce(context, angleUnit, target); + return e.shallowReduce(context, complexFormat, angleUnit, target); } else { // sin(-a) = -sin(a) or tan(-a) = -tan(a) Multiplication m(Rational(-1)); e.replaceWithInPlace(m); m.addChildAtIndexInPlace(e, 1, 1); - e.shallowReduce(context, angleUnit, target); - return m.shallowReduce(context, angleUnit, target); + e.shallowReduce(context, complexFormat, angleUnit, target); + return m.shallowReduce(context, complexFormat, angleUnit, target); } } @@ -222,27 +222,27 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& co Expression newR = Rational(div.remainder, rDenominator); Expression rationalParent = angleUnit == Preferences::AngleUnit::Radian ? e.childAtIndex(0) : e; rationalParent.replaceChildAtIndexInPlace(0, newR); - newR.shallowReduce(context, angleUnit, target); + newR.shallowReduce(context, complexFormat, angleUnit, target); if (angleUnit == Preferences::AngleUnit::Radian) { - e.childAtIndex(0).shallowReduce(context, angleUnit, target); + e.childAtIndex(0).shallowReduce(context, complexFormat, angleUnit, target); } if (Integer::Division(div.quotient, Integer(2)).remainder.isOne() && e.type() != ExpressionNode::Type::Tangent) { /* Step 4.6. If we subtracted an odd number of Pi in 4.2, we need to * multiply the result by -1 (because cos((2k+1)Pi + x) = -cos(x) */ unaryCoefficient *= -1; } - Expression simplifiedCosine = e.shallowReduce(context, angleUnit, target); // recursive + Expression simplifiedCosine = e.shallowReduce(context, complexFormat, angleUnit, target); // recursive Multiplication m = Multiplication(Rational(unaryCoefficient)); simplifiedCosine.replaceWithInPlace(m); m.addChildAtIndexInPlace(simplifiedCosine, 1, 1); - return m.shallowReduce(context, angleUnit, target); + return m.shallowReduce(context, complexFormat, angleUnit, target); } assert(r.sign() == ExpressionNode::Sign::Positive); } return e; } -Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { assert(isInverseTrigonometryFunction(e)); float pi = angleUnit == Preferences::AngleUnit::Radian ? M_PI : 180; @@ -278,19 +278,19 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& c if (target == ExpressionNode::ReductionTarget::User || x.isNumber()) { Expression sign = SignFunction::Builder(x.clone()); Multiplication m0(Rational(1,2), sign, Constant(Ion::Charset::SmallPi)); - sign.shallowReduce(context, angleUnit, target); + sign.shallowReduce(context, complexFormat, angleUnit, target); e.replaceChildAtIndexInPlace(0, x); Addition a(m0); e.replaceWithInPlace(a); Multiplication m1(Rational(-1), e); - e.shallowReduce(context, angleUnit, target); + e.shallowReduce(context, complexFormat, angleUnit, target); a.addChildAtIndexInPlace(m1, 1, 1); - return a.shallowReduce(context, angleUnit, target); + return a.shallowReduce(context, complexFormat, angleUnit, target); } } // Step 4. Try finding an easy standard calculation reduction - Expression lookup = Trigonometry::table(e.childAtIndex(0), e.type(), context, angleUnit, target); + Expression lookup = Trigonometry::table(e.childAtIndex(0), e.type(), context, complexFormat, angleUnit, target); if (!lookup.isUninitialized()) { e.replaceWithInPlace(lookup); return lookup; @@ -308,7 +308,7 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& c * arcsin(-x) = -arcsin(x), arctan(-x)= -arctan(x) * */ if (!letArcFunctionAtRoot) { - Expression positiveArg = e.childAtIndex(0).makePositiveAnyNegativeNumeralFactor(context, angleUnit, target); + Expression positiveArg = e.childAtIndex(0).makePositiveAnyNegativeNumeralFactor(context, complexFormat, angleUnit, target); if (!positiveArg.isUninitialized()) { // The argument was made positive // acos(-x) = pi-acos(x) @@ -318,15 +318,15 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& c e.replaceWithInPlace(s); s.replaceChildAtIndexInPlace(0, pi); s.replaceChildAtIndexInPlace(1, e); - e.shallowReduce(context, angleUnit, target); - return s.shallowReduce(context, angleUnit, target); + e.shallowReduce(context, complexFormat, angleUnit, target); + return s.shallowReduce(context, complexFormat, angleUnit, target); } else { // asin(-x) = -asin(x) or atan(-x) = -atan(x) Multiplication m(Rational(-1)); e.replaceWithInPlace(m); m.addChildAtIndexInPlace(e, 1, 1); - e.shallowReduce(context, angleUnit, target); - return m.shallowReduce(context, angleUnit, target); + e.shallowReduce(context, complexFormat, angleUnit, target); + return m.shallowReduce(context, complexFormat, angleUnit, target); } } } @@ -425,7 +425,7 @@ constexpr Pair cheatTable[Trigonometry::k_numberOfEntries][5] = {Pair("180",180.0f), Pair("\x8A",3.141592653589793f), Pair("-1",-1.0f), Pair("0",0.0f), Pair("0",0.0f)}}; -Expression Trigonometry::table(const Expression e, ExpressionNode::Type type, Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression Trigonometry::table(const Expression e, ExpressionNode::Type type, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { assert(type == ExpressionNode::Type::Sine || type == ExpressionNode::Type::Cosine || type == ExpressionNode::Type::Tangent @@ -461,14 +461,14 @@ Expression Trigonometry::table(const Expression e, ExpressionNode::Type type, Co // Our given expression approximation matches a table entry, we check that both expressions are identical Expression input = Expression::Parse(cheatTable[i][inputIndex].expression); assert(!input.isUninitialized()); - input = input.deepReduce(context, angleUnit, target); + input = input.deepReduce(context, complexFormat, angleUnit, target); bool rightInput = input.isIdenticalTo(e); if (rightInput) { Expression output = Expression::Parse(cheatTable[i][outputIndex].expression); if (output.isUninitialized()) { return Expression(); } - return output.deepReduce(context, angleUnit, target); + return output.deepReduce(context, complexFormat, angleUnit, target); } break; } diff --git a/poincare/src/undefined.cpp b/poincare/src/undefined.cpp index 2928c987a..4c821ffa6 100644 --- a/poincare/src/undefined.cpp +++ b/poincare/src/undefined.cpp @@ -13,7 +13,7 @@ int UndefinedNode::polynomialDegree(Context & context, const char * symbolName) return -1; } -Expression UndefinedNode::setSign(Sign s, Context * context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { +Expression UndefinedNode::setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { return Undefined(this); } diff --git a/poincare/test/float.cpp b/poincare/test/float.cpp index fbd9d6b69..d605cf819 100644 --- a/poincare/test/float.cpp +++ b/poincare/test/float.cpp @@ -16,7 +16,7 @@ void assert_float_evaluates_to(Float f, const char * result) { Shared::GlobalContext globalContext; int numberOfDigits = sizeof(T) == sizeof(double) ? PrintFloat::k_numberOfStoredSignificantDigits : PrintFloat::k_numberOfPrintedSignificantDigits; char buffer[500]; - f.template approximate(globalContext, Radian, Cartesian).serialize(buffer, sizeof(buffer), DecimalMode, numberOfDigits); + f.template approximate(globalContext, Cartesian, Radian).serialize(buffer, sizeof(buffer), DecimalMode, numberOfDigits); translate_in_ASCII_chars(buffer); quiz_assert(strcmp(buffer, result) == 0); } diff --git a/poincare/test/helper.cpp b/poincare/test/helper.cpp index 936c518e8..f35ebadd0 100644 --- a/poincare/test/helper.cpp +++ b/poincare/test/helper.cpp @@ -103,10 +103,10 @@ void assert_parsed_expression_is(const char * expression, Poincare::Expression r quiz_assert(expressions_are_equal(r, e)); } -void assert_parsed_expression_polynomial_degree(const char * expression, int degree, const char * symbolName) { +void assert_parsed_expression_polynomial_degree(const char * expression, int degree, const char * symbolName, Preferences::ComplexFormat complexFormat) { Shared::GlobalContext globalContext; Expression e = parse_expression(expression); - Expression result = e.clone().reduce(globalContext, Radian); + Expression result = e.clone().reduce(globalContext, complexFormat, Radian); if (result.isUninitialized()) { result = e; } @@ -117,13 +117,13 @@ void assert_simplify(const char * expression) { Shared::GlobalContext globalContext; Expression e = parse_expression(expression); quiz_assert(!e.isUninitialized()); - e = e.simplify(globalContext, Radian); + e = e.simplify(globalContext, Cartesian, Radian); quiz_assert(!e.isUninitialized()); } -typedef Expression (*ProcessExpression)(Expression, Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat); +typedef Expression (*ProcessExpression)(Expression, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); -void assert_parsed_expression_process_to(const char * expression, const char * result, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat, ProcessExpression process, int numberOfSignifiantDigits = PrintFloat::k_numberOfStoredSignificantDigits) { +void assert_parsed_expression_process_to(const char * expression, const char * result, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ProcessExpression process, int numberOfSignifiantDigits = PrintFloat::k_numberOfStoredSignificantDigits) { Shared::GlobalContext globalContext; Expression e = parse_expression(expression); @@ -131,7 +131,7 @@ void assert_parsed_expression_process_to(const char * expression, const char * r cout << " Entry expression: " << expression << "----" << endl; print_expression(e, 0); #endif - Expression m = process(e, globalContext, angleUnit, complexFormat); + Expression m = process(e, globalContext, complexFormat, angleUnit); char buffer[500]; m.serialize(buffer, sizeof(buffer), DecimalMode, numberOfSignifiantDigits); translate_in_ASCII_chars(buffer); @@ -149,12 +149,12 @@ void assert_parsed_expression_evaluates_to(const char * expression, const char * #endif int numberOfDigits = sizeof(T) == sizeof(double) ? PrintFloat::k_numberOfStoredSignificantDigits : PrintFloat::k_numberOfPrintedSignificantDigits; numberOfDigits = numberOfSignificantDigits > 0 ? numberOfSignificantDigits : numberOfDigits; - assert_parsed_expression_process_to(expression, approximation, angleUnit, complexFormat, [](Expression e, Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) { - Expression result = e.clone().simplify(context, angleUnit); + assert_parsed_expression_process_to(expression, approximation, complexFormat, angleUnit, [](Expression e, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { + Expression result = e.clone().simplify(context, complexFormat, angleUnit); if (result.isUninitialized()) { result = e; } - return result.approximate(context, angleUnit, complexFormat); + return result.approximate(context, complexFormat, angleUnit); }, numberOfDigits); } @@ -169,9 +169,9 @@ void assert_parsed_expression_simplify_to(const char * expression, const char * #if POINCARE_TESTS_PRINT_EXPRESSIONS cout << "--------- Simplification ---------" << endl; #endif - assert_parsed_expression_process_to(expression, simplifiedExpression, angleUnit, complexFormat, [](Expression e, Context & context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) { + assert_parsed_expression_process_to(expression, simplifiedExpression, complexFormat, angleUnit, [](Expression e, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { Expression copy = e.clone(); - copy.simplifyAndApproximate(©, nullptr, context, angleUnit, complexFormat); + copy.simplifyAndApproximate(©, nullptr, context, complexFormat, angleUnit); if (copy.isUninitialized()) { return e; } @@ -218,6 +218,6 @@ void assert_expression_layout_serialize_to(Poincare::Layout layout, const char * } template void assert_parsed_expression_evaluates_to(char const*, char const *, Poincare::Preferences::AngleUnit, Poincare::Preferences::ComplexFormat, int); -template void assert_parsed_expression_evaluates_to(char const*, char const *, Poincare::Preferences::AngleUnit, Poincare::Preferences::ComplexFormat, int); +template void assert_parsed_expression_evaluates_to(char const*, char const *, Poincare::Preferences::AngleUnit, Poincare::Preferences::ComplexFormat, int); template void assert_parsed_expression_approximates_with_value_for_symbol(Poincare::Expression, const char *, float, float, Poincare::Preferences::AngleUnit); template void assert_parsed_expression_approximates_with_value_for_symbol(Poincare::Expression, const char *, double, double, Poincare::Preferences::AngleUnit); diff --git a/poincare/test/helper.h b/poincare/test/helper.h index 00a0e8f20..e445f5488 100644 --- a/poincare/test/helper.h +++ b/poincare/test/helper.h @@ -12,6 +12,7 @@ constexpr Poincare::Preferences::AngleUnit Degree = Poincare::Preferences::Angle constexpr Poincare::Preferences::AngleUnit Radian = Poincare::Preferences::AngleUnit::Radian; constexpr Poincare::Preferences::ComplexFormat Cartesian = Poincare::Preferences::ComplexFormat::Cartesian; constexpr Poincare::Preferences::ComplexFormat Polar = Poincare::Preferences::ComplexFormat::Polar; +constexpr Poincare::Preferences::ComplexFormat Real = Poincare::Preferences::ComplexFormat::Real; constexpr Poincare::Preferences::PrintFloatMode DecimalMode = Poincare::Preferences::PrintFloatMode::Decimal; constexpr Poincare::Preferences::PrintFloatMode ScientificMode = Poincare::Preferences::PrintFloatMode::Scientific; @@ -22,7 +23,7 @@ Poincare::Expression parse_expression(const char * expression, bool canBeUnparsa void assert_expression_not_parsable(const char * expression); void assert_parsed_expression_type(const char * expression, Poincare::ExpressionNode::Type type); void assert_parsed_expression_is(const char * expression, Poincare::Expression r); -void assert_parsed_expression_polynomial_degree(const char * expression, int degree, const char * symbolName = "x"); +void assert_parsed_expression_polynomial_degree(const char * expression, int degree, const char * symbolName = "x", Poincare::Preferences::ComplexFormat complexFormat = Cartesian); void assert_simplify(const char * expression); template diff --git a/poincare/test/layouts.cpp b/poincare/test/layouts.cpp index 59133fb96..dff41720e 100644 --- a/poincare/test/layouts.cpp +++ b/poincare/test/layouts.cpp @@ -15,14 +15,14 @@ void assert_parsed_layout_is(Layout l, Poincare::Expression r) { l.serializeForParsing(buffer, bufferSize); Expression e = parse_expression(buffer); Expression eSimplified; - e.clone().simplifyAndApproximate(&eSimplified, nullptr, context, Degree, Cartesian); + e.clone().simplifyAndApproximate(&eSimplified, nullptr, context, Cartesian, Degree); if (eSimplified.isUninitialized()) { /* In case the simplification is impossible (if there are matrices for * instance), use the non simplified expression */ eSimplified = e; } Expression rSimplified; - r.clone().simplifyAndApproximate(&rSimplified, nullptr, context, Degree, Cartesian); + r.clone().simplifyAndApproximate(&rSimplified, nullptr, context, Cartesian, Degree); if (rSimplified.isUninitialized()) { /* In case the simplification is impossible (if there are matrices for * instance), use the non simplified expression */ diff --git a/poincare/test/properties.cpp b/poincare/test/properties.cpp index b5ac572d8..031a3f043 100644 --- a/poincare/test/properties.cpp +++ b/poincare/test/properties.cpp @@ -11,11 +11,11 @@ constexpr Poincare::ExpressionNode::Sign Positive = Poincare::ExpressionNode::Si constexpr Poincare::ExpressionNode::Sign Negative = Poincare::ExpressionNode::Sign::Negative; constexpr Poincare::ExpressionNode::Sign Unknown = Poincare::ExpressionNode::Sign::Unknown; -void assert_parsed_expression_sign(const char * expression, Poincare::ExpressionNode::Sign sign) { +void assert_parsed_expression_sign(const char * expression, Poincare::ExpressionNode::Sign sign, Poincare::Preferences::ComplexFormat complexFormat = Cartesian) { Shared::GlobalContext globalContext; Expression e = parse_expression(expression); quiz_assert(!e.isUninitialized()); - e = e.reduce(globalContext, Degree); + e = e.reduce(globalContext, complexFormat, Degree); quiz_assert(e.sign(&globalContext) == sign); } @@ -34,6 +34,8 @@ QUIZ_CASE(poincare_sign) { assert_parsed_expression_sign("-23/32", Negative); assert_parsed_expression_sign("P", Positive); assert_parsed_expression_sign("X", Positive); + assert_parsed_expression_sign("R(-1)", Unknown); + assert_parsed_expression_sign("R(-1)", Unknown, Real); } QUIZ_CASE(poincare_polynomial_degree) { @@ -62,7 +64,7 @@ QUIZ_CASE(poincare_polynomial_degree) { void assert_expression_has_characteristic_range(Expression e, float range, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Degree) { Shared::GlobalContext globalContext; quiz_assert(!e.isUninitialized()); - e = e.reduce(globalContext, angleUnit); + e = e.reduce(globalContext, Preferences::ComplexFormat::Cartesian, angleUnit); if (std::isnan(range)) { quiz_assert(std::isnan(e.characteristicXRange(globalContext, angleUnit))); } else { @@ -124,18 +126,18 @@ QUIZ_CASE(poincare_get_variables) { assert_parsed_expression_has_variables("f(tata)", variableBuffer7, 2); } -void assert_parsed_expression_has_polynomial_coefficient(const char * expression, const char * symbolName, const char ** coefficients, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Degree) { +void assert_parsed_expression_has_polynomial_coefficient(const char * expression, const char * symbolName, const char ** coefficients, Preferences::ComplexFormat complexFormat = Preferences::ComplexFormat::Cartesian, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Degree) { Shared::GlobalContext globalContext; Expression e = parse_expression(expression); quiz_assert(!e.isUninitialized()); - e = e.reduce(globalContext, angleUnit); + e = e.reduce(globalContext, complexFormat, angleUnit); Expression coefficientBuffer[Poincare::Expression::k_maxNumberOfPolynomialCoefficients]; - int d = e.getPolynomialReducedCoefficients(symbolName, coefficientBuffer, globalContext, Radian); + int d = e.getPolynomialReducedCoefficients(symbolName, coefficientBuffer, globalContext, complexFormat, Radian); for (int i = 0; i <= d; i++) { Expression f = parse_expression(coefficients[i]); quiz_assert(!f.isUninitialized()); - coefficientBuffer[i] = coefficientBuffer[i].reduce(globalContext, angleUnit); - f = f.reduce(globalContext, angleUnit); + coefficientBuffer[i] = coefficientBuffer[i].reduce(globalContext, complexFormat, angleUnit); + f = f.reduce(globalContext, complexFormat, angleUnit); quiz_assert(coefficientBuffer[i].isIdenticalTo(f)); } quiz_assert(coefficients[d+1] == 0); From 5e434a4c332f94b18863fac34770d8a4d01eb80c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 21 Dec 2018 16:24:24 +0100 Subject: [PATCH 139/373] [poincare] Get rid of useless arguments in shallowReduce --- poincare/include/poincare/binomial_coefficient.h | 2 +- poincare/include/poincare/ceiling.h | 2 +- poincare/include/poincare/complex_cartesian.h | 2 +- poincare/include/poincare/decimal.h | 2 +- poincare/include/poincare/derivative.h | 2 +- poincare/include/poincare/determinant.h | 2 +- poincare/include/poincare/division_quotient.h | 2 +- poincare/include/poincare/division_remainder.h | 2 +- poincare/include/poincare/equal.h | 2 +- poincare/include/poincare/factorial.h | 2 +- poincare/include/poincare/floor.h | 2 +- poincare/include/poincare/frac_part.h | 2 +- poincare/include/poincare/great_common_divisor.h | 2 +- .../include/poincare/hyperbolic_trigonometric_function.h | 2 +- poincare/include/poincare/integral.h | 2 +- poincare/include/poincare/least_common_multiple.h | 2 +- poincare/include/poincare/matrix_dimension.h | 2 +- poincare/include/poincare/matrix_trace.h | 2 +- poincare/include/poincare/matrix_transpose.h | 2 +- poincare/include/poincare/parenthesis.h | 2 +- poincare/include/poincare/permute_coefficient.h | 2 +- poincare/include/poincare/rational.h | 2 +- poincare/include/poincare/round.h | 2 +- poincare/include/poincare/store.h | 2 +- poincare/src/addition.cpp | 2 +- poincare/src/binomial_coefficient.cpp | 4 ++-- poincare/src/ceiling.cpp | 4 ++-- poincare/src/complex_cartesian.cpp | 6 +++--- poincare/src/decimal.cpp | 4 ++-- poincare/src/derivative.cpp | 4 ++-- poincare/src/determinant.cpp | 4 ++-- poincare/src/division_quotient.cpp | 4 ++-- poincare/src/division_remainder.cpp | 4 ++-- poincare/src/equal.cpp | 4 ++-- poincare/src/factorial.cpp | 4 ++-- poincare/src/floor.cpp | 4 ++-- poincare/src/frac_part.cpp | 4 ++-- poincare/src/great_common_divisor.cpp | 4 ++-- poincare/src/hyperbolic_trigonometric_function.cpp | 4 ++-- poincare/src/integral.cpp | 4 ++-- poincare/src/least_common_multiple.cpp | 4 ++-- poincare/src/matrix_dimension.cpp | 4 ++-- poincare/src/matrix_trace.cpp | 4 ++-- poincare/src/matrix_transpose.cpp | 4 ++-- poincare/src/multiplication.cpp | 2 +- poincare/src/parenthesis.cpp | 4 ++-- poincare/src/permute_coefficient.cpp | 4 ++-- poincare/src/power.cpp | 4 ++-- poincare/src/rational.cpp | 4 ++-- poincare/src/round.cpp | 4 ++-- poincare/src/store.cpp | 4 ++-- 51 files changed, 77 insertions(+), 77 deletions(-) diff --git a/poincare/include/poincare/binomial_coefficient.h b/poincare/include/poincare/binomial_coefficient.h index 0587257cf..0a890a921 100644 --- a/poincare/include/poincare/binomial_coefficient.h +++ b/poincare/include/poincare/binomial_coefficient.h @@ -44,7 +44,7 @@ public: static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("binomial", 2, &UntypedBuilder); // Expression - Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowReduce(); private: BinomialCoefficient(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child0); diff --git a/poincare/include/poincare/ceiling.h b/poincare/include/poincare/ceiling.h index 44dafdbdf..07fa9c7fd 100644 --- a/poincare/include/poincare/ceiling.h +++ b/poincare/include/poincare/ceiling.h @@ -46,7 +46,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("ceil", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowReduce(); private: explicit Ceiling(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/complex_cartesian.h b/poincare/include/poincare/complex_cartesian.h index 324dcf303..c254083d5 100644 --- a/poincare/include/poincare/complex_cartesian.h +++ b/poincare/include/poincare/complex_cartesian.h @@ -46,7 +46,7 @@ public: Expression imag() { return childAtIndex(1); } // Simplification - Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowReduce(); Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); // Common operations (done in-place) diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index f86bde4a7..e78118224 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -104,7 +104,7 @@ private: Decimal(size_t size, const Integer & m, int e); Expression setSign(ExpressionNode::Sign s); // Simplification - Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowReduce(); Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); }; diff --git a/poincare/include/poincare/derivative.h b/poincare/include/poincare/derivative.h index f22b9b66e..5eb690fac 100644 --- a/poincare/include/poincare/derivative.h +++ b/poincare/include/poincare/derivative.h @@ -61,7 +61,7 @@ public: } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("diff", 3, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowReduce(); private: Derivative(Expression child0, Expression child1, Expression child2) : Expression(TreePool::sharedPool()->createTreeNode()) { assert(child1.type() == ExpressionNode::Type::Symbol); diff --git a/poincare/include/poincare/determinant.h b/poincare/include/poincare/determinant.h index 62a36a7bd..2f8b4b0a4 100644 --- a/poincare/include/poincare/determinant.h +++ b/poincare/include/poincare/determinant.h @@ -39,7 +39,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("det", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context); private: explicit Determinant(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/division_quotient.h b/poincare/include/poincare/division_quotient.h index 3849503d5..2d98fec41 100644 --- a/poincare/include/poincare/division_quotient.h +++ b/poincare/include/poincare/division_quotient.h @@ -43,7 +43,7 @@ public: static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("quo", 2, &UntypedBuilder); // Expression - Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowReduce(); private: DivisionQuotient(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child0); diff --git a/poincare/include/poincare/division_remainder.h b/poincare/include/poincare/division_remainder.h index 1710553bf..25c5ecc08 100644 --- a/poincare/include/poincare/division_remainder.h +++ b/poincare/include/poincare/division_remainder.h @@ -44,7 +44,7 @@ public: static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("rem", 2, &UntypedBuilder); // Expression - Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowReduce(); private: DivisionRemainder(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child0); diff --git a/poincare/include/poincare/equal.h b/poincare/include/poincare/equal.h index 0056082ba..17b863c10 100644 --- a/poincare/include/poincare/equal.h +++ b/poincare/include/poincare/equal.h @@ -43,7 +43,7 @@ public: // For the equation A = B, create the reduced expression A-B Expression standardEquation(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; // Expression - Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowReduce(); }; } diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index 52955b808..ec0c1aa35 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -57,7 +57,7 @@ public: replaceChildAtIndexInPlace(0, child); } - Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowReduce(); Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); private: constexpr static int k_maxOperandValue = 100; diff --git a/poincare/include/poincare/floor.h b/poincare/include/poincare/floor.h index 47606158b..eb658e0ad 100644 --- a/poincare/include/poincare/floor.h +++ b/poincare/include/poincare/floor.h @@ -48,7 +48,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("floor", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowReduce(); private: explicit Floor(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/frac_part.h b/poincare/include/poincare/frac_part.h index 7df4b717b..83d0d30c4 100644 --- a/poincare/include/poincare/frac_part.h +++ b/poincare/include/poincare/frac_part.h @@ -48,7 +48,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("frac", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowReduce(); private: explicit FracPart(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/great_common_divisor.h b/poincare/include/poincare/great_common_divisor.h index 3bdc5b8fb..a6db18e15 100644 --- a/poincare/include/poincare/great_common_divisor.h +++ b/poincare/include/poincare/great_common_divisor.h @@ -42,7 +42,7 @@ public: static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("gcd", 2, &UntypedBuilder); // Expression - Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowReduce(); private: GreatCommonDivisor(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child0); diff --git a/poincare/include/poincare/hyperbolic_trigonometric_function.h b/poincare/include/poincare/hyperbolic_trigonometric_function.h index 18eaf7d54..98b4a8d7a 100644 --- a/poincare/include/poincare/hyperbolic_trigonometric_function.h +++ b/poincare/include/poincare/hyperbolic_trigonometric_function.h @@ -18,7 +18,7 @@ private: class HyperbolicTrigonometricFunction : public Expression { public: HyperbolicTrigonometricFunction(const HyperbolicTrigonometricFunctionNode * n) : Expression(n) {} - Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowReduce(); }; } diff --git a/poincare/include/poincare/integral.h b/poincare/include/poincare/integral.h index 4860f80ad..d278ff366 100644 --- a/poincare/include/poincare/integral.h +++ b/poincare/include/poincare/integral.h @@ -66,7 +66,7 @@ public: static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("int", 4, &UntypedBuilder); // Expression - Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowReduce(); private: Integral(Expression child0, Expression child1, Expression child2, Expression child3) : Expression(TreePool::sharedPool()->createTreeNode()) { assert(child1.type() == ExpressionNode::Type::Symbol); diff --git a/poincare/include/poincare/least_common_multiple.h b/poincare/include/poincare/least_common_multiple.h index f501b5ebc..3bb103900 100644 --- a/poincare/include/poincare/least_common_multiple.h +++ b/poincare/include/poincare/least_common_multiple.h @@ -42,7 +42,7 @@ public: static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("lcm", 2, &UntypedBuilder); // Expression - Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowReduce(); private: LeastCommonMultiple(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child0); diff --git a/poincare/include/poincare/matrix_dimension.h b/poincare/include/poincare/matrix_dimension.h index ce5b3a796..f1eb57a8d 100644 --- a/poincare/include/poincare/matrix_dimension.h +++ b/poincare/include/poincare/matrix_dimension.h @@ -39,7 +39,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("dim", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowReduce(); private: explicit MatrixDimension(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/matrix_trace.h b/poincare/include/poincare/matrix_trace.h index 27bc2234d..446022de7 100644 --- a/poincare/include/poincare/matrix_trace.h +++ b/poincare/include/poincare/matrix_trace.h @@ -38,7 +38,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("trace", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowReduce(); private: explicit MatrixTrace(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/matrix_transpose.h b/poincare/include/poincare/matrix_transpose.h index 97abb0234..e6b8a4711 100644 --- a/poincare/include/poincare/matrix_transpose.h +++ b/poincare/include/poincare/matrix_transpose.h @@ -38,7 +38,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("transpose", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowReduce(); private: explicit MatrixTranspose(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index 1e594500d..8974aab03 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -42,7 +42,7 @@ public: replaceChildAtIndexInPlace(0, exp); } // Expression - Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowReduce(); }; } diff --git a/poincare/include/poincare/permute_coefficient.h b/poincare/include/poincare/permute_coefficient.h index 2c3f1a093..f954da449 100644 --- a/poincare/include/poincare/permute_coefficient.h +++ b/poincare/include/poincare/permute_coefficient.h @@ -46,7 +46,7 @@ public: static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("permute", 2, &UntypedBuilder); // Expression - Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowReduce(); private: PermuteCoefficient(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child0); diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index 6b98ec1f0..6293dc28a 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -108,7 +108,7 @@ public: static int NaturalOrder(const Rational & i, const Rational & j) { return RationalNode::NaturalOrder(i.node(), j.node()); } // Simplification - Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowReduce(); private: Rational(const native_uint_t * i, uint8_t numeratorSize, const native_uint_t * j, uint8_t denominatorSize, bool negative); diff --git a/poincare/include/poincare/round.h b/poincare/include/poincare/round.h index 7876622d6..b3e2ba47c 100644 --- a/poincare/include/poincare/round.h +++ b/poincare/include/poincare/round.h @@ -42,7 +42,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("round", 2, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowReduce(); private: Round(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child0); diff --git a/poincare/include/poincare/store.h b/poincare/include/poincare/store.h index 223973bbd..3b2c21769 100644 --- a/poincare/include/poincare/store.h +++ b/poincare/include/poincare/store.h @@ -55,7 +55,7 @@ public: } // Expression - Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context); }; } diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 179e4425b..279c6c9a4 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -277,7 +277,7 @@ Expression Addition::shallowReduce(Context & context, Preferences::ComplexFormat newComplexCartesian.replaceChildAtIndexInPlace(1, imag); real.shallowReduce(context, complexFormat, angleUnit, target); imag.shallowReduce(context, complexFormat, angleUnit, target); - return newComplexCartesian.shallowReduce(context, complexFormat, angleUnit); + return newComplexCartesian.shallowReduce(); } /* Step 7: Let's put everything under a common denominator. diff --git a/poincare/src/binomial_coefficient.cpp b/poincare/src/binomial_coefficient.cpp index 398aa24cd..cf9f9b3ac 100644 --- a/poincare/src/binomial_coefficient.cpp +++ b/poincare/src/binomial_coefficient.cpp @@ -15,7 +15,7 @@ constexpr Expression::FunctionHelper BinomialCoefficient::s_functionHelper; int BinomialCoefficientNode::numberOfChildren() const { return BinomialCoefficient::s_functionHelper.numberOfChildren(); } Expression BinomialCoefficientNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return BinomialCoefficient(this).shallowReduce(context, complexFormat, angleUnit); + return BinomialCoefficient(this).shallowReduce(); } Layout BinomialCoefficientNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -53,7 +53,7 @@ T BinomialCoefficientNode::compute(T k, T n) { return std::round(result); } -Expression BinomialCoefficient::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression BinomialCoefficient::shallowReduce() { { Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { diff --git a/poincare/src/ceiling.cpp b/poincare/src/ceiling.cpp index 1afb83571..8d8139a25 100644 --- a/poincare/src/ceiling.cpp +++ b/poincare/src/ceiling.cpp @@ -32,10 +32,10 @@ Complex CeilingNode::computeOnComplex(const std::complex c, Preferences::A } Expression CeilingNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Ceiling(this).shallowReduce(context, complexFormat, angleUnit); + return Ceiling(this).shallowReduce(); } -Expression Ceiling::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression Ceiling::shallowReduce() { { Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { diff --git a/poincare/src/complex_cartesian.cpp b/poincare/src/complex_cartesian.cpp index e0a9b2331..74916e7a8 100644 --- a/poincare/src/complex_cartesian.cpp +++ b/poincare/src/complex_cartesian.cpp @@ -20,7 +20,7 @@ namespace Poincare { Expression ComplexCartesianNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return ComplexCartesian(this).shallowReduce(context, complexFormat, angleUnit); + return ComplexCartesian(this).shallowReduce(); } Expression ComplexCartesianNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { @@ -40,7 +40,7 @@ Complex ComplexCartesianNode::templatedApproximate(Context& context, Preferen return Complex(a.real(), b.real()); } -Expression ComplexCartesian::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression ComplexCartesian::shallowReduce() { if (imag().isRationalZero()) { Expression r = real(); replaceWithInPlace(r); @@ -253,7 +253,7 @@ ComplexCartesian ComplexCartesian::powerInteger(int n, Context & context, Prefer Power apow(aclone, Rational(n-i)); Power bpow(bclone, Rational(i)); Multiplication m(binom, apow, bpow); - binom.shallowReduce(context, complexFormat, angleUnit); + binom.shallowReduce(); apow.shallowReduce(context, complexFormat, angleUnit, target); bpow.shallowReduce(context, complexFormat, angleUnit, target); if (i/2%2 == 1) { diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index 94adda80e..5203266c8 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -86,7 +86,7 @@ int DecimalNode::simplificationOrderSameType(const ExpressionNode * e, bool canB } Expression DecimalNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Decimal(this).shallowReduce(context, complexFormat, angleUnit); + return Decimal(this).shallowReduce(); } Expression DecimalNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { @@ -342,7 +342,7 @@ Expression Decimal::setSign(ExpressionNode::Sign s) { return result; } -Expression Decimal::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression Decimal::shallowReduce() { Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; diff --git a/poincare/src/derivative.cpp b/poincare/src/derivative.cpp index 4163b59ae..2fde528f2 100644 --- a/poincare/src/derivative.cpp +++ b/poincare/src/derivative.cpp @@ -40,7 +40,7 @@ int DerivativeNode::serialize(char * buffer, int bufferSize, Preferences::PrintF } Expression DerivativeNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Derivative(this).shallowReduce(context, complexFormat, angleUnit); + return Derivative(this).shallowReduce(); } template @@ -137,7 +137,7 @@ T DerivativeNode::riddersApproximation(Context & context, Preferences::AngleUnit return ans; } -Expression Derivative::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression Derivative::shallowReduce() { { Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { diff --git a/poincare/src/determinant.cpp b/poincare/src/determinant.cpp index d73746c53..2a01a7073 100644 --- a/poincare/src/determinant.cpp +++ b/poincare/src/determinant.cpp @@ -29,10 +29,10 @@ Evaluation DeterminantNode::templatedApproximate(Context& context, Preference } Expression DeterminantNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Determinant(this).shallowReduce(context, complexFormat, angleUnit); + return Determinant(this).shallowReduce(context); } -Expression Determinant::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression Determinant::shallowReduce(Context & context) { { Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { diff --git a/poincare/src/division_quotient.cpp b/poincare/src/division_quotient.cpp index acd244c53..51dae949d 100644 --- a/poincare/src/division_quotient.cpp +++ b/poincare/src/division_quotient.cpp @@ -13,7 +13,7 @@ constexpr Expression::FunctionHelper DivisionQuotient::s_functionHelper; int DivisionQuotientNode::numberOfChildren() const { return DivisionQuotient::s_functionHelper.numberOfChildren(); } Expression DivisionQuotientNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return DivisionQuotient(this).shallowReduce(context, complexFormat, angleUnit); + return DivisionQuotient(this).shallowReduce(); } Layout DivisionQuotientNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -35,7 +35,7 @@ Evaluation DivisionQuotientNode::templatedApproximate(Context& context, Prefe return Complex(std::floor(f1/f2)); } -Expression DivisionQuotient::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression DivisionQuotient::shallowReduce() { { Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { diff --git a/poincare/src/division_remainder.cpp b/poincare/src/division_remainder.cpp index 4ed9a1bc5..095a5ee32 100644 --- a/poincare/src/division_remainder.cpp +++ b/poincare/src/division_remainder.cpp @@ -21,7 +21,7 @@ int DivisionRemainderNode::serialize(char * buffer, int bufferSize, Preferences: } Expression DivisionRemainderNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return DivisionRemainder(this).shallowReduce(context, complexFormat, angleUnit); + return DivisionRemainder(this).shallowReduce(); } template @@ -36,7 +36,7 @@ Evaluation DivisionRemainderNode::templatedApproximate(Context& context, Pref return Complex(std::round(f1-f2*std::floor(f1/f2))); } -Expression DivisionRemainder::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression DivisionRemainder::shallowReduce() { { Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { diff --git a/poincare/src/equal.cpp b/poincare/src/equal.cpp index 1c44a35b2..0f3461bb9 100644 --- a/poincare/src/equal.cpp +++ b/poincare/src/equal.cpp @@ -21,7 +21,7 @@ extern "C" { namespace Poincare { Expression EqualNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Equal(this).shallowReduce(context, complexFormat, angleUnit); + return Equal(this).shallowReduce(); } Layout EqualNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -46,7 +46,7 @@ Expression Equal::standardEquation(Context & context, Preferences::ComplexFormat return sub.reduce(context, complexFormat, angleUnit); } -Expression Equal::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression Equal::shallowReduce() { { Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index 3e4d8d60d..84354a0ba 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -35,7 +35,7 @@ bool FactorialNode::childNeedsParenthesis(const TreeNode * child) const { // Simplification Expression FactorialNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Factorial(this).shallowReduce(context, complexFormat, angleUnit); + return Factorial(this).shallowReduce(); } Expression FactorialNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { @@ -91,7 +91,7 @@ int FactorialNode::serialize(char * buffer, int bufferSize, Preferences::PrintFl Factorial::Factorial() : Expression(TreePool::sharedPool()->createTreeNode()) {} -Expression Factorial::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression Factorial::shallowReduce() { { Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { diff --git a/poincare/src/floor.cpp b/poincare/src/floor.cpp index 97236d5f0..6e1e3538c 100644 --- a/poincare/src/floor.cpp +++ b/poincare/src/floor.cpp @@ -32,10 +32,10 @@ Complex FloorNode::computeOnComplex(const std::complex c, Preferences::Ang } Expression FloorNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Floor(this).shallowReduce(context, complexFormat, angleUnit); + return Floor(this).shallowReduce(); } -Expression Floor::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression Floor::shallowReduce() { { Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { diff --git a/poincare/src/frac_part.cpp b/poincare/src/frac_part.cpp index beae8c161..ccd91ce0a 100644 --- a/poincare/src/frac_part.cpp +++ b/poincare/src/frac_part.cpp @@ -20,7 +20,7 @@ int FracPartNode::serialize(char * buffer, int bufferSize, Preferences::PrintFlo } Expression FracPartNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return FracPart(this).shallowReduce(context, complexFormat, angleUnit); + return FracPart(this).shallowReduce(); } template @@ -31,7 +31,7 @@ Complex FracPartNode::computeOnComplex(const std::complex c, Preferences:: return Complex(c.real()-std::floor(c.real())); } -Expression FracPart::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression FracPart::shallowReduce() { { Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { diff --git a/poincare/src/great_common_divisor.cpp b/poincare/src/great_common_divisor.cpp index 0dda60aa5..6e1bf3216 100644 --- a/poincare/src/great_common_divisor.cpp +++ b/poincare/src/great_common_divisor.cpp @@ -21,7 +21,7 @@ int GreatCommonDivisorNode::serialize(char * buffer, int bufferSize, Preferences } Expression GreatCommonDivisorNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return GreatCommonDivisor(this).shallowReduce(context, complexFormat, angleUnit); + return GreatCommonDivisor(this).shallowReduce(); } template @@ -48,7 +48,7 @@ Evaluation GreatCommonDivisorNode::templatedApproximate(Context& context, Pre return Complex(std::round((T)a)); } -Expression GreatCommonDivisor::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression GreatCommonDivisor::shallowReduce() { { Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { diff --git a/poincare/src/hyperbolic_trigonometric_function.cpp b/poincare/src/hyperbolic_trigonometric_function.cpp index d8f27740b..4d48654dc 100644 --- a/poincare/src/hyperbolic_trigonometric_function.cpp +++ b/poincare/src/hyperbolic_trigonometric_function.cpp @@ -3,10 +3,10 @@ namespace Poincare { Expression HyperbolicTrigonometricFunctionNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return HyperbolicTrigonometricFunction(this).shallowReduce(context, complexFormat, angleUnit); + return HyperbolicTrigonometricFunction(this).shallowReduce(); } -Expression HyperbolicTrigonometricFunction::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression HyperbolicTrigonometricFunction::shallowReduce() { { Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { diff --git a/poincare/src/integral.cpp b/poincare/src/integral.cpp index 7d17fe2d7..93f159d9a 100644 --- a/poincare/src/integral.cpp +++ b/poincare/src/integral.cpp @@ -44,7 +44,7 @@ int IntegralNode::serialize(char * buffer, int bufferSize, Preferences::PrintFlo } Expression IntegralNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Integral(this).shallowReduce(context, complexFormat, angleUnit); + return Integral(this).shallowReduce(); } template @@ -195,7 +195,7 @@ T IntegralNode::adaptiveQuadrature(T a, T b, T eps, int numberOfIterations, Cont } #endif -Expression Integral::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression Integral::shallowReduce() { { Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { diff --git a/poincare/src/least_common_multiple.cpp b/poincare/src/least_common_multiple.cpp index aa20c0931..81aa319c2 100644 --- a/poincare/src/least_common_multiple.cpp +++ b/poincare/src/least_common_multiple.cpp @@ -22,7 +22,7 @@ int LeastCommonMultipleNode::serialize(char * buffer, int bufferSize, Preference } Expression LeastCommonMultipleNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return LeastCommonMultiple(this).shallowReduce(context, complexFormat, angleUnit); + return LeastCommonMultiple(this).shallowReduce(); } template @@ -53,7 +53,7 @@ Evaluation LeastCommonMultipleNode::templatedApproximate(Context& context, Pr return Complex(product/a); } -Expression LeastCommonMultiple::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression LeastCommonMultiple::shallowReduce() { { Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { diff --git a/poincare/src/matrix_dimension.cpp b/poincare/src/matrix_dimension.cpp index d1b12ed54..cab61c470 100644 --- a/poincare/src/matrix_dimension.cpp +++ b/poincare/src/matrix_dimension.cpp @@ -12,7 +12,7 @@ constexpr Expression::FunctionHelper MatrixDimension::s_functionHelper; int MatrixDimensionNode::numberOfChildren() const { return MatrixDimension::s_functionHelper.numberOfChildren(); } Expression MatrixDimensionNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return MatrixDimension(this).shallowReduce(context, complexFormat, angleUnit); + return MatrixDimension(this).shallowReduce(); } Layout MatrixDimensionNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -37,7 +37,7 @@ Evaluation MatrixDimensionNode::templatedApproximate(Context& context, Prefer return MatrixComplex(operands, 1, 2); } -Expression MatrixDimension::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression MatrixDimension::shallowReduce() { { Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { diff --git a/poincare/src/matrix_trace.cpp b/poincare/src/matrix_trace.cpp index ec7c9a866..83acc54f2 100644 --- a/poincare/src/matrix_trace.cpp +++ b/poincare/src/matrix_trace.cpp @@ -14,7 +14,7 @@ constexpr Expression::FunctionHelper MatrixTrace::s_functionHelper; int MatrixTraceNode::numberOfChildren() const { return MatrixTrace::s_functionHelper.numberOfChildren(); } Expression MatrixTraceNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return MatrixTrace(this).shallowReduce(context, complexFormat, angleUnit); + return MatrixTrace(this).shallowReduce(); } Layout MatrixTraceNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -32,7 +32,7 @@ Evaluation MatrixTraceNode::templatedApproximate(Context& context, Preference return result; } -Expression MatrixTrace::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression MatrixTrace::shallowReduce() { { Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { diff --git a/poincare/src/matrix_transpose.cpp b/poincare/src/matrix_transpose.cpp index f19878254..2f1c6ec29 100644 --- a/poincare/src/matrix_transpose.cpp +++ b/poincare/src/matrix_transpose.cpp @@ -13,7 +13,7 @@ constexpr Expression::FunctionHelper MatrixTranspose::s_functionHelper; int MatrixTransposeNode::numberOfChildren() const { return MatrixTranspose::s_functionHelper.numberOfChildren(); } Expression MatrixTransposeNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return MatrixTranspose(this).shallowReduce(context, complexFormat, angleUnit); + return MatrixTranspose(this).shallowReduce(); } Layout MatrixTransposeNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -37,7 +37,7 @@ Evaluation MatrixTransposeNode::templatedApproximate(Context& context, Prefer return transpose; } -Expression MatrixTranspose::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression MatrixTranspose::shallowReduce() { { Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 9e263b25b..08eb0028b 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -505,7 +505,7 @@ Expression Multiplication::privateShallowReduce(Context & context, Preferences:: newComplexCartesian.replaceChildAtIndexInPlace(1, imag); real.shallowReduce(context, complexFormat, angleUnit, target); imag.shallowReduce(context, complexFormat, angleUnit, target); - return newComplexCartesian.shallowReduce(context, complexFormat, angleUnit); + return newComplexCartesian.shallowReduce(); } return result; diff --git a/poincare/src/parenthesis.cpp b/poincare/src/parenthesis.cpp index 981879045..437b7fc78 100644 --- a/poincare/src/parenthesis.cpp +++ b/poincare/src/parenthesis.cpp @@ -17,7 +17,7 @@ int ParenthesisNode::serialize(char * buffer, int bufferSize, Preferences::Print } Expression ParenthesisNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Parenthesis(this).shallowReduce(context, complexFormat, angleUnit); + return Parenthesis(this).shallowReduce(); } template @@ -25,7 +25,7 @@ Evaluation ParenthesisNode::templatedApproximate(Context& context, Preference return childAtIndex(0)->approximate(T(), context, angleUnit); } -Expression Parenthesis::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression Parenthesis::shallowReduce() { Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; diff --git a/poincare/src/permute_coefficient.cpp b/poincare/src/permute_coefficient.cpp index 4087c64cc..5a330d708 100644 --- a/poincare/src/permute_coefficient.cpp +++ b/poincare/src/permute_coefficient.cpp @@ -24,7 +24,7 @@ int PermuteCoefficientNode::serialize(char * buffer, int bufferSize, Preferences } Expression PermuteCoefficientNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return PermuteCoefficient(this).shallowReduce(context, complexFormat, angleUnit); + return PermuteCoefficient(this).shallowReduce(); } template @@ -49,7 +49,7 @@ Evaluation PermuteCoefficientNode::templatedApproximate(Context& context, Pre return Complex(std::round(result)); } -Expression PermuteCoefficient::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression PermuteCoefficient::shallowReduce() { { Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 0d69de5bb..cb61da904 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -438,7 +438,7 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co } if (!result.isUninitialized()) { replaceWithInPlace(result); - return result.shallowReduce(context, complexFormat, angleUnit); + return result.shallowReduce(); } } } @@ -450,7 +450,7 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co complexIndex = index.type() == ExpressionNode::Type::ComplexCartesian ? static_cast(index) : ComplexCartesian::Builder(index, Rational(0)); result = complexBase.power(complexIndex, context, complexFormat, angleUnit, target); replaceWithInPlace(result); - return result.shallowReduce(context, complexFormat, angleUnit); + return result.shallowReduce(); } /* Step 3: We look for square root and sum of square roots (two terms maximum diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index ae11ffcaf..9df0d44c4 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -144,7 +144,7 @@ int RationalNode::simplificationOrderSameType(const ExpressionNode * e, bool can // Simplification Expression RationalNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Rational(this).shallowReduce(context, complexFormat, angleUnit); + return Rational(this).shallowReduce(); } Expression RationalNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { @@ -233,7 +233,7 @@ Rational::Rational(const native_uint_t * i, uint8_t numeratorSize, const native_ static_cast(node())->setDigits(i, numeratorSize, j, denominatorSize, negative); } -Expression Rational::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression Rational::shallowReduce() { // FIXME: /* Infinite Rational should not exist as they aren't parsed and are supposed * to be turn in Float if they should appear. We assert(false) so far, but diff --git a/poincare/src/round.cpp b/poincare/src/round.cpp index d6f105ae6..2ddf81cb4 100644 --- a/poincare/src/round.cpp +++ b/poincare/src/round.cpp @@ -22,7 +22,7 @@ int RoundNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatM } Expression RoundNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Round(this).shallowReduce(context, complexFormat, angleUnit); + return Round(this).shallowReduce(); } template @@ -38,7 +38,7 @@ Evaluation RoundNode::templatedApproximate(Context& context, Preferences::Ang return Complex(std::round(f1*err)/err); } -Expression Round::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression Round::shallowReduce() { { Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index afac6fd1f..c9cc6b31f 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -20,7 +20,7 @@ void StoreNode::deepReduceChildren(Context & context, Preferences::ComplexFormat } Expression StoreNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Store(this).shallowReduce(context, complexFormat, angleUnit); + return Store(this).shallowReduce(context); } int StoreNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -50,7 +50,7 @@ Evaluation StoreNode::templatedApproximate(Context& context, Preferences::Ang return e.approximateToEvaluation(context, angleUnit); } -Expression Store::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression Store::shallowReduce(Context & context) { Expression finalValue; if (symbol().type() == ExpressionNode::Type::Function) { // In tata + 2 ->f(tata), replace tata with xUnknown symbol From c3ad0e027c189c29f33a373f4da864e7b88f6618 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 21 Dec 2018 17:55:34 +0100 Subject: [PATCH 140/373] [poincare] Create class Unreal --- poincare/Makefile | 1 + poincare/include/poincare/expression.h | 2 +- poincare/include/poincare/expression_node.h | 1 + poincare/include/poincare/undefined.h | 2 +- poincare/include/poincare/unreal.h | 41 +++++++++++++++++++++ poincare/include/poincare_nodes.h | 1 + poincare/src/parsing/parser.cpp | 3 ++ poincare/src/tree_pool.cpp | 1 + poincare/src/unreal.cpp | 24 ++++++++++++ 9 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 poincare/include/poincare/unreal.h create mode 100644 poincare/src/unreal.cpp diff --git a/poincare/Makefile b/poincare/Makefile index 816a3a53f..e8bef072d 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -128,6 +128,7 @@ objs += $(addprefix poincare/src/,\ tree_pool.o\ trigonometry.o\ undefined.o\ + unreal.o\ variable_context.o\ ) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 4f8bddee7..1576a71a7 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -120,7 +120,7 @@ public: /* Properties */ ExpressionNode::Type type() const { return node()->type(); } ExpressionNode::Sign sign(Context * context) const { return node()->sign(context); } - bool isUndefined() const { return node()->type() == ExpressionNode::Type::Undefined; } + bool isUndefined() const { return node()->type() == ExpressionNode::Type::Undefined || node()->type() == ExpressionNode::Type::Unreal; } bool isNumber() const { return node()->isNumber(); } bool isRationalZero() const; bool isRationalOne() const; diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index c5baa792a..b5a8581dd 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -27,6 +27,7 @@ public: enum class Type : uint8_t { Uninitialized = 0, Undefined = 1, + Unreal, Rational, Decimal, Float, diff --git a/poincare/include/poincare/undefined.h b/poincare/include/poincare/undefined.h index f31e02096..8a8ed7a10 100644 --- a/poincare/include/poincare/undefined.h +++ b/poincare/include/poincare/undefined.h @@ -5,7 +5,7 @@ namespace Poincare { -class UndefinedNode final : public NumberNode { +class UndefinedNode : public NumberNode { public: // TreeNode diff --git a/poincare/include/poincare/unreal.h b/poincare/include/poincare/unreal.h new file mode 100644 index 000000000..7b5e657e7 --- /dev/null +++ b/poincare/include/poincare/unreal.h @@ -0,0 +1,41 @@ +#ifndef POINCARE_UNREAL_H +#define POINCARE_UNREAL_H + +#include + +namespace Poincare { + +class UnrealNode final : public UndefinedNode { +public: + + // TreeNode + size_t size() const override { return sizeof(UnrealNode); } +#if POINCARE_TREE_LOG + virtual void logNodeName(std::ostream & stream) const override { + stream << "Unreal"; + } +#endif + + // Properties + Type type() const override { return Type::Unreal; } + + // Layout + Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; + int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = 0) const override; +private: +}; + +class Unreal final : public Number { +public: + Unreal() : Number(TreePool::sharedPool()->createTreeNode()) {} + static const char * Name() { + return "unreal"; + } + static int NameSize() { + return 7; + } +}; + +} + +#endif diff --git a/poincare/include/poincare_nodes.h b/poincare/include/poincare_nodes.h index 0315fd467..63d1eea25 100644 --- a/poincare/include/poincare_nodes.h +++ b/poincare/include/poincare_nodes.h @@ -76,6 +76,7 @@ #include #include #include +#include #include #endif diff --git a/poincare/src/parsing/parser.cpp b/poincare/src/parsing/parser.cpp index 5274fec93..01a02b5a5 100644 --- a/poincare/src/parsing/parser.cpp +++ b/poincare/src/parsing/parser.cpp @@ -40,6 +40,7 @@ bool Parser::IsSpecialIdentifierName(const char * name, size_t nameLength) { Token::CompareNonNullTerminatedName(name, nameLength, Symbol::k_ans) == 0 || Token::CompareNonNullTerminatedName(name, nameLength, Infinity::Name()) == 0 || Token::CompareNonNullTerminatedName(name, nameLength, Undefined::Name()) == 0 || + Token::CompareNonNullTerminatedName(name, nameLength, Unreal::Name()) == 0 || Token::CompareNonNullTerminatedName(name, nameLength, "u_") == 0 || Token::CompareNonNullTerminatedName(name, nameLength, "v_") == 0 || Token::CompareNonNullTerminatedName(name, nameLength, "u") == 0 || @@ -376,6 +377,8 @@ void Parser::parseSpecialIdentifier(Expression & leftHandSide) { leftHandSide = Infinity(false); } else if (m_currentToken.compareTo(Undefined::Name()) == 0) { leftHandSide = Undefined(); + } else if (m_currentToken.compareTo(Unreal::Name()) == 0) { + leftHandSide = Unreal(); } else if (m_currentToken.compareTo("u_") == 0 || m_currentToken.compareTo("v_") == 0) { // Special case for sequences (e.g. "u_{n}") parseSequence(leftHandSide, m_currentToken.text()[0], Token::LeftBrace, Token::RightBrace); } else if (m_currentToken.compareTo("u") == 0 || m_currentToken.compareTo("v") == 0) { // Special case for sequences (e.g. "u(n)") diff --git a/poincare/src/tree_pool.cpp b/poincare/src/tree_pool.cpp index 70d095737..346768071 100644 --- a/poincare/src/tree_pool.cpp +++ b/poincare/src/tree_pool.cpp @@ -216,6 +216,7 @@ template ArcCosineNode * Poincare::TreePool::createTreeNode(size_ template ArcSineNode * Poincare::TreePool::createTreeNode(size_t size); template ArcTangentNode * Poincare::TreePool::createTreeNode(size_t size); template UndefinedNode * Poincare::TreePool::createTreeNode(size_t size); +template UnrealNode * Poincare::TreePool::createTreeNode(size_t size); template BinomialCoefficientNode * Poincare::TreePool::createTreeNode(size_t size); template CeilingNode * Poincare::TreePool::createTreeNode(size_t size); template OppositeNode * Poincare::TreePool::createTreeNode(size_t size); diff --git a/poincare/src/unreal.cpp b/poincare/src/unreal.cpp new file mode 100644 index 000000000..6180455ac --- /dev/null +++ b/poincare/src/unreal.cpp @@ -0,0 +1,24 @@ +#include +#include + +extern "C" { +#include +#include +} + +namespace Poincare { + +Layout UnrealNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::String(Unreal::Name(), Unreal::NameSize()-1); +} + +int UnrealNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + if (bufferSize == 0) { + return -1; + } + strlcpy(buffer, Unreal::Name(), bufferSize); + return min(Unreal::NameSize(), bufferSize) - 1; +} + +} + From ecf3f2ea0fa31c618302c58e94de0727c816b983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 21 Dec 2018 17:55:58 +0100 Subject: [PATCH 141/373] [poincare] Create a a flag on Expression that is set when the approximation encouters a complex value All approximation methods take the complex format into account. --- apps/regression/model/model.cpp | 3 +- apps/sequence/sequence.cpp | 7 +- apps/shared/function.cpp | 3 +- apps/shared/poincare_helpers.h | 32 +++-- apps/shared/storage_cartesian_function.cpp | 12 +- apps/shared/storage_function.cpp | 3 +- apps/solver/equation_store.cpp | 6 +- poincare/include/poincare/expression.h | 30 ++-- poincare/src/absolute_value.cpp | 2 +- poincare/src/complex.cpp | 3 + poincare/src/complex_argument.cpp | 2 +- poincare/src/derivative.cpp | 5 +- poincare/src/expression.cpp | 153 ++++++++++++--------- poincare/src/function.cpp | 2 +- poincare/src/integral.cpp | 7 +- poincare/src/store.cpp | 2 +- poincare/src/symbol.cpp | 2 +- poincare/src/trigonometry.cpp | 8 +- poincare/test/addition.cpp | 2 +- poincare/test/function.cpp | 2 +- poincare/test/helper.cpp | 10 +- poincare/test/helper.h | 2 +- poincare/test/user_variable.cpp | 11 ++ 23 files changed, 187 insertions(+), 122 deletions(-) diff --git a/apps/regression/model/model.cpp b/apps/regression/model/model.cpp index 2df92feff..fb62cd1b0 100644 --- a/apps/regression/model/model.cpp +++ b/apps/regression/model/model.cpp @@ -19,7 +19,8 @@ double Model::levelSet(double * modelCoefficients, double xMin, double step, dou Expression yExpression = Number::DecimalNumber(y); PoincareHelpers::Simplify(&yExpression, *context); Expression modelExpression = simplifiedExpression(modelCoefficients, context); - double result = modelExpression.nextIntersection("x", xMin, step, xMax, *context, Preferences::sharedPreferences()->angleUnit(), yExpression).abscissa; + Preferences * preferences = Preferences::sharedPreferences(); + double result = modelExpression.nextIntersection("x", xMin, step, xMax, *context, preferences->complexFormat(), preferences->angleUnit(), yExpression).abscissa; return result; } diff --git a/apps/sequence/sequence.cpp b/apps/sequence/sequence.cpp index e0fb7f8ab..04f3e652a 100644 --- a/apps/sequence/sequence.cpp +++ b/apps/sequence/sequence.cpp @@ -251,13 +251,12 @@ T Sequence::approximateToNextRank(int n, SequenceContext * sqctx) const { Poincare::Symbol vn1Symbol("v(n+1)", 6); Poincare::Symbol unSymbol("u(n)", 4); Poincare::Symbol un1Symbol("u(n+1)", 6); - Preferences * preferences = Poincare::Preferences::sharedPreferences(); switch (m_type) { case Type::Explicit: { ctx.setValueForSymbol(un, unSymbol); ctx.setValueForSymbol(vn, vnSymbol); - return expression(sqctx).approximateWithValueForSymbol(symbol(), (T)n, ctx, preferences->angleUnit()); + return PoincareHelpers::ApproximateWithValueForSymbol(expression(sqctx), symbol(), (T)n, ctx); } case Type::SingleRecurrence: { @@ -268,7 +267,7 @@ T Sequence::approximateToNextRank(int n, SequenceContext * sqctx) const { ctx.setValueForSymbol(unm1, unSymbol); ctx.setValueForSymbol(vn, vn1Symbol); ctx.setValueForSymbol(vnm1, vnSymbol); - return expression(sqctx).approximateWithValueForSymbol(symbol(), (T)(n-1), ctx, preferences->angleUnit()); + return PoincareHelpers::ApproximateWithValueForSymbol(expression(sqctx), symbol(), (T)(n-1), ctx); } default: { @@ -282,7 +281,7 @@ T Sequence::approximateToNextRank(int n, SequenceContext * sqctx) const { ctx.setValueForSymbol(unm2, unSymbol); ctx.setValueForSymbol(vnm1, vn1Symbol); ctx.setValueForSymbol(vnm2, vnSymbol); - return expression(sqctx).approximateWithValueForSymbol(symbol(), (T)(n-2), ctx, preferences->angleUnit()); + return PoincareHelpers::ApproximateWithValueForSymbol(expression(sqctx), symbol(), (T)(n-2), ctx); } } } diff --git a/apps/shared/function.cpp b/apps/shared/function.cpp index efa4cc6e5..3fff69cd8 100644 --- a/apps/shared/function.cpp +++ b/apps/shared/function.cpp @@ -1,4 +1,5 @@ #include "function.h" +#include "poincare_helpers.h" #include #include #include @@ -41,7 +42,7 @@ void Function::setActive(bool active) { template T Function::templatedApproximateAtAbscissa(T x, Poincare::Context * context) const { - return expression(context).approximateWithValueForSymbol(symbol(), x, *context, Preferences::sharedPreferences()->angleUnit()); + return PoincareHelpers::ApproximateWithValueForSymbol(expression(context), symbol(), x, *context); } } diff --git a/apps/shared/poincare_helpers.h b/apps/shared/poincare_helpers.h index eb4162dcb..589d536a4 100644 --- a/apps/shared/poincare_helpers.h +++ b/apps/shared/poincare_helpers.h @@ -10,7 +10,8 @@ namespace Shared { namespace PoincareHelpers { inline Poincare::Layout CreateLayout(const Poincare::Expression e) { - return e.createLayout(Poincare::Preferences::sharedPreferences()->displayMode(), Poincare::Preferences::sharedPreferences()->numberOfSignificantDigits()); + Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); + return e.createLayout(preferences->displayMode(), preferences->numberOfSignificantDigits()); } template @@ -24,25 +25,39 @@ inline int Serialize(const Poincare::Expression e, char * buffer, int bufferSize template inline Poincare::Expression Approximate(const Poincare::Expression e, Poincare::Context & context) { - Poincare::Preferences::ComplexFormat complexFormat = Poincare::Preferences::sharedPreferences()->complexFormat(); + Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); + Poincare::Preferences::ComplexFormat complexFormat = preferences->complexFormat(); complexFormat = Poincare::Expression::UpdatedComplexFormatWithExpressionInput(complexFormat, e, context); - return e.approximate(context, complexFormat, Poincare::Preferences::sharedPreferences()->angleUnit()); + return e.approximate(context, complexFormat, preferences->angleUnit()); } template inline T ApproximateToScalar(const Poincare::Expression e, Poincare::Context & context) { - return e.approximateToScalar(context, Poincare::Preferences::sharedPreferences()->angleUnit()); + Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); + Poincare::Preferences::ComplexFormat complexFormat = preferences->complexFormat(); + complexFormat = Poincare::Expression::UpdatedComplexFormatWithExpressionInput(complexFormat, e, context); + return e.approximateToScalar(context, complexFormat, preferences->angleUnit()); +} + +template +inline T ApproximateWithValueForSymbol(const Poincare::Expression e, const char * symbol, T x, Poincare::Context & context) { + Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); + Poincare::Preferences::ComplexFormat complexFormat = preferences->complexFormat(); + complexFormat = Poincare::Expression::UpdatedComplexFormatWithExpressionInput(complexFormat, e, context); + return e.approximateWithValueForSymbol(symbol, x, context, complexFormat, preferences->angleUnit()); } template inline T ApproximateToScalar(const char * text, Poincare::Context & context) { - Poincare::Preferences::ComplexFormat complexFormat = Poincare::Preferences::sharedPreferences()->complexFormat(); + Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); + Poincare::Preferences::ComplexFormat complexFormat = preferences->complexFormat(); complexFormat = Poincare::Expression::UpdatedComplexFormatWithTextInput(complexFormat, text); - return Poincare::Expression::approximateToScalar(text, context, complexFormat, Poincare::Preferences::sharedPreferences()->angleUnit()); + return Poincare::Expression::approximateToScalar(text, context, complexFormat, preferences->angleUnit()); } inline Poincare::Expression ParseAndSimplify(const char * text, Poincare::Context & context) { - return Poincare::Expression::ParseAndSimplify(text, context, Poincare::Preferences::sharedPreferences()->complexFormat(), Poincare::Preferences::sharedPreferences()->angleUnit()); + Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); + return Poincare::Expression::ParseAndSimplify(text, context, preferences->complexFormat(), preferences->angleUnit()); } inline void Simplify(Poincare::Expression * e, Poincare::Context & context, Poincare::Preferences::ComplexFormat complexFormat = Poincare::Preferences::sharedPreferences()->complexFormat()) { @@ -51,7 +66,8 @@ inline void Simplify(Poincare::Expression * e, Poincare::Context & context, Poin } inline void ParseAndSimplifyAndApproximate(const char * text, Poincare::Expression * simplifiedExpression, Poincare::Expression * approximateExpression, Poincare::Context & context) { - Poincare::Expression::ParseAndSimplifyAndApproximate(text, simplifiedExpression, approximateExpression, context, Poincare::Preferences::sharedPreferences()->complexFormat(), Poincare::Preferences::sharedPreferences()->angleUnit()); + Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); + Poincare::Expression::ParseAndSimplifyAndApproximate(text, simplifiedExpression, approximateExpression, context, preferences->complexFormat(), preferences->angleUnit()); } inline void SimplifyAndApproximate(Poincare::Expression * e, Poincare::Expression * approximate, Poincare::Context & context, Poincare::Preferences::ComplexFormat complexFormat = Poincare::Preferences::sharedPreferences()->complexFormat()) { diff --git a/apps/shared/storage_cartesian_function.cpp b/apps/shared/storage_cartesian_function.cpp index 33a785ca3..1dc520041 100644 --- a/apps/shared/storage_cartesian_function.cpp +++ b/apps/shared/storage_cartesian_function.cpp @@ -103,22 +103,26 @@ double StorageCartesianFunction::sumBetweenBounds(double start, double end, Poin Expression::Coordinate2D StorageCartesianFunction::nextMinimumFrom(double start, double step, double max, Context * context) const { const char unknownX[2] = {Poincare::Symbol::UnknownX, 0}; - return expressionReduced(context).nextMinimum(unknownX, start, step, max, *context, Preferences::sharedPreferences()->angleUnit()); + Preferences * preferences = Preferences::sharedPreferences(); + return expressionReduced(context).nextMinimum(unknownX, start, step, max, *context, preferences->complexFormat(), preferences->angleUnit()); } Expression::Coordinate2D StorageCartesianFunction::nextMaximumFrom(double start, double step, double max, Context * context) const { const char unknownX[2] = {Poincare::Symbol::UnknownX, 0}; - return expressionReduced(context).nextMaximum(unknownX, start, step, max, *context, Preferences::sharedPreferences()->angleUnit()); + Preferences * preferences = Preferences::sharedPreferences(); + return expressionReduced(context).nextMaximum(unknownX, start, step, max, *context, preferences->complexFormat(), preferences->angleUnit()); } double StorageCartesianFunction::nextRootFrom(double start, double step, double max, Context * context) const { const char unknownX[2] = {Poincare::Symbol::UnknownX, 0}; - return expressionReduced(context).nextRoot(unknownX, start, step, max, *context, Preferences::sharedPreferences()->angleUnit()); + Preferences * preferences = Preferences::sharedPreferences(); + return expressionReduced(context).nextRoot(unknownX, start, step, max, *context, preferences->complexFormat(), preferences->angleUnit()); } Expression::Coordinate2D StorageCartesianFunction::nextIntersectionFrom(double start, double step, double max, Poincare::Context * context, Expression e) const { const char unknownX[2] = {Poincare::Symbol::UnknownX, 0}; - return expressionReduced(context).nextIntersection(unknownX, start, step, max, *context, Preferences::sharedPreferences()->angleUnit(), e); + Preferences * preferences = Preferences::sharedPreferences(); + return expressionReduced(context).nextIntersection(unknownX, start, step, max, *context, preferences->complexFormat(), preferences->angleUnit(), e); } StorageCartesianFunction::CartesianFunctionRecordData * StorageCartesianFunction::recordData() const { diff --git a/apps/shared/storage_function.cpp b/apps/shared/storage_function.cpp index afb572634..02fa70fd4 100644 --- a/apps/shared/storage_function.cpp +++ b/apps/shared/storage_function.cpp @@ -1,4 +1,5 @@ #include "storage_function.h" +#include "poincare_helpers.h" #include #include "poincare/src/parsing/parser.h" #include @@ -76,7 +77,7 @@ T StorageFunction::templatedApproximateAtAbscissa(T x, Poincare::Context * conte return NAN; } const char unknownX[2] = {Poincare::Symbol::UnknownX, 0}; - return expressionReduced(context).approximateWithValueForSymbol(unknownX, x, *context, Preferences::sharedPreferences()->angleUnit()); + return PoincareHelpers::ApproximateWithValueForSymbol(expressionReduced(context), unknownX, x, *context); } StorageFunction::FunctionRecordData * StorageFunction::recordData() const { diff --git a/apps/solver/equation_store.cpp b/apps/solver/equation_store.cpp index 708837b4d..b7b444985 100644 --- a/apps/solver/equation_store.cpp +++ b/apps/solver/equation_store.cpp @@ -78,7 +78,8 @@ bool EquationStore::haveMoreApproximationSolutions(Context * context) { return false; } double step = (m_intervalApproximateSolutions[1]-m_intervalApproximateSolutions[0])*k_precision; - return !std::isnan(definedModelAtIndex(0)->standardForm(context).nextRoot(m_variables[0], m_approximateSolutions[m_numberOfSolutions-1], step, m_intervalApproximateSolutions[1], *context, Preferences::sharedPreferences()->angleUnit())); + Preferences * preferences = Preferences::sharedPreferences(); + return !std::isnan(definedModelAtIndex(0)->standardForm(context).nextRoot(m_variables[0], m_approximateSolutions[m_numberOfSolutions-1], step, m_intervalApproximateSolutions[1], *context, preferences->complexFormat(), preferences->angleUnit())); } void EquationStore::approximateSolve(Poincare::Context * context) { @@ -87,8 +88,9 @@ void EquationStore::approximateSolve(Poincare::Context * context) { m_numberOfSolutions = 0; double start = m_intervalApproximateSolutions[0]; double step = (m_intervalApproximateSolutions[1]-m_intervalApproximateSolutions[0])*k_precision; + Preferences * preferences = Preferences::sharedPreferences(); for (int i = 0; i < k_maxNumberOfApproximateSolutions; i++) { - m_approximateSolutions[i] = definedModelAtIndex(0)->standardForm(context).nextRoot(m_variables[0], start, step, m_intervalApproximateSolutions[1], *context, Preferences::sharedPreferences()->angleUnit()); + m_approximateSolutions[i] = definedModelAtIndex(0)->standardForm(context).nextRoot(m_variables[0], start, step, m_intervalApproximateSolutions[1], *context, preferences->complexFormat(), preferences->angleUnit()); if (std::isnan(m_approximateSolutions[i])) { break; } else { diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 1576a71a7..ae6d8dde2 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -167,6 +167,7 @@ public: Expression defaultReplaceUnknown(const Symbol & symbol); /* Complex */ + static void SetEncounterComplex(bool encounterComplex); static Preferences::ComplexFormat UpdatedComplexFormatWithTextInput(Preferences::ComplexFormat complexFormat, const char * textInput); static Preferences::ComplexFormat UpdatedComplexFormatWithExpressionInput(Preferences::ComplexFormat complexFormat, const Expression & e, Context & context); bool isReal(Context & context) const { return node()->isReal(context); } @@ -193,20 +194,21 @@ public: Expression degreeToRadian(); /* Approximation Helper */ + // These methods reset the sApproximationEncounterComplex flag. They should not be use to implement node approximation template static U epsilon(); template Expression approximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; - template U approximateToScalar(Context& context, Preferences::AngleUnit angleUnit) const; + template U approximateToScalar(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; template static U approximateToScalar(const char * text, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); - template U approximateWithValueForSymbol(const char * symbol, U x, Context & context, Preferences::AngleUnit angleUnit) const; + template U approximateWithValueForSymbol(const char * symbol, U x, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; /* Expression roots/extrema solver */ struct Coordinate2D { double abscissa; double value; }; - Coordinate2D nextMinimum(const char * symbol, double start, double step, double max, Context & context, Preferences::AngleUnit angleUnit) const; - Coordinate2D nextMaximum(const char * symbol, double start, double step, double max, Context & context, Preferences::AngleUnit angleUnit) const; - double nextRoot(const char * symbol, double start, double step, double max, Context & context, Preferences::AngleUnit angleUnit) const; - Coordinate2D nextIntersection(const char * symbol, double start, double step, double max, Context & context, Preferences::AngleUnit angleUnit, const Expression expression) const; + Coordinate2D nextMinimum(const char * symbol, double start, double step, double max, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; + Coordinate2D nextMaximum(const char * symbol, double start, double step, double max, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; + double nextRoot(const char * symbol, double start, double step, double max, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; + Coordinate2D nextIntersection(const char * symbol, double start, double step, double max, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression) const; /* This class is meant to contain data about named functions (e.g. sin, tan...) * in one place: their name, their number of children and a pointer to a builder. @@ -298,7 +300,7 @@ private: Expression defaultShallowBeautify() { return *this; } /* Approximation */ - template Evaluation approximateToEvaluation(Context& context, Preferences::AngleUnit angleUnit) const; + template Evaluation approximateToEvaluation(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; /* Properties */ Expression defaultReplaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression expression); @@ -315,13 +317,13 @@ private: constexpr static double k_sqrtEps = 1.4901161193847656E-8; // sqrt(DBL_EPSILON) constexpr static double k_goldenRatio = 0.381966011250105151795413165634361882279690820194237137864; // (3-sqrt(5))/2 constexpr static double k_maxFloat = 1e100; - typedef double (*EvaluationAtAbscissa)(const char * symbol, double abscissa, Context & context, Preferences::AngleUnit angleUnit, const Expression expression0, const Expression expression1); - Coordinate2D nextMinimumOfExpression(const char * symbol, double start, double step, double max, EvaluationAtAbscissa evaluation, Context & context, Preferences::AngleUnit angleUnit, const Expression expression = Expression(), bool lookForRootMinimum = false) const; - void bracketMinimum(const char * symbol, double start, double step, double max, double result[3], EvaluationAtAbscissa evaluation, Context & context, Preferences::AngleUnit angleUnit, const Expression expression = Expression()) const; - Coordinate2D brentMinimum(const char * symbol, double ax, double bx, EvaluationAtAbscissa evaluation, Context & context, Preferences::AngleUnit angleUnit, const Expression expression = Expression()) const; - double nextIntersectionWithExpression(const char * symbol, double start, double step, double max, EvaluationAtAbscissa evaluation, Context & context, Preferences::AngleUnit angleUnit, const Expression expression) const; - void bracketRoot(const char * symbol, double start, double step, double max, double result[2], EvaluationAtAbscissa evaluation, Context & context, Preferences::AngleUnit angleUnit, const Expression expression) const; - double brentRoot(const char * symbol, double ax, double bx, double precision, EvaluationAtAbscissa evaluation, Context & context, Preferences::AngleUnit angleUnit, const Expression expression) const; + typedef double (*EvaluationAtAbscissa)(const char * symbol, double abscissa, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression0, const Expression expression1); + Coordinate2D nextMinimumOfExpression(const char * symbol, double start, double step, double max, EvaluationAtAbscissa evaluation, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression = Expression(), bool lookForRootMinimum = false) const; + void bracketMinimum(const char * symbol, double start, double step, double max, double result[3], EvaluationAtAbscissa evaluation, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression = Expression()) const; + Coordinate2D brentMinimum(const char * symbol, double ax, double bx, EvaluationAtAbscissa evaluation, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression = Expression()) const; + double nextIntersectionWithExpression(const char * symbol, double start, double step, double max, EvaluationAtAbscissa evaluation, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression) const; + void bracketRoot(const char * symbol, double start, double step, double max, double result[2], EvaluationAtAbscissa evaluation, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression) const; + double brentRoot(const char * symbol, double ax, double bx, double precision, EvaluationAtAbscissa evaluation, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression) const; }; } diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 8a053454b..e3b97bf27 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -49,7 +49,7 @@ Expression AbsoluteValue::shallowReduce(Context & context, Preferences::ComplexF #endif Expression c = childAtIndex(0); if (c.isReal(context)) { - float app = c.approximateToScalar(context, angleUnit); + float app = c.node()->approximate(float(), context, angleUnit).toScalar(); if (!std::isnan(app) && app >= Expression::epsilon()) { // abs(a) = a with a > 0 replaceWithInPlace(c); diff --git a/poincare/src/complex.cpp b/poincare/src/complex.cpp index 4237baf1b..6f735d972 100644 --- a/poincare/src/complex.cpp +++ b/poincare/src/complex.cpp @@ -22,6 +22,9 @@ namespace Poincare { template void ComplexNode::setComplex(std::complex c) { + if (c.imag() != 0.0) { + Expression::SetEncounterComplex(true); + } this->real(c.real()); this->imag(c.imag()); if (this->real() == -0) { diff --git a/poincare/src/complex_argument.cpp b/poincare/src/complex_argument.cpp index c0aec6212..c4c6d9b0d 100644 --- a/poincare/src/complex_argument.cpp +++ b/poincare/src/complex_argument.cpp @@ -48,7 +48,7 @@ Expression ComplexArgument::shallowReduce(Context & context, Preferences::Comple #endif bool real = c.isReal(context); if (real) { - float app = c.approximateToScalar(context, angleUnit); + float app = c.node()->approximate(float(), context, angleUnit).toScalar(); if (!std::isnan(app) && app >= Expression::epsilon()) { // arg(x) = 0 if x > 0 Expression result = Rational(0); diff --git a/poincare/src/derivative.cpp b/poincare/src/derivative.cpp index 2fde528f2..b59f02091 100644 --- a/poincare/src/derivative.cpp +++ b/poincare/src/derivative.cpp @@ -76,7 +76,10 @@ Evaluation DerivativeNode::templatedApproximate(Context& context, Preferences template T DerivativeNode::approximateWithArgument(T x, Context & context, Preferences::AngleUnit angleUnit) const { assert(childAtIndex(1)->type() == Type::Symbol); - return Expression(childAtIndex(0)).approximateWithValueForSymbol(static_cast(childAtIndex(1))->name(), x, context, angleUnit); + VariableContext variableContext = VariableContext(static_cast(childAtIndex(1))->name(), &context); + variableContext.setApproximationForVariable(x); + // Here we cannot use Expression::approximateWithValueForSymbol which would reset the sApproximationEncounterComplex flag + return childAtIndex(0)->approximate(T(), variableContext, angleUnit).toScalar(); } template diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 63606669c..efb8737fa 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -14,6 +14,7 @@ namespace Poincare { bool Expression::sSymbolReplacementsCountLock = false; +static bool sApproximationEncounterComplex = false; /* Constructor & Destructor */ @@ -269,10 +270,15 @@ Expression Expression::makePositiveAnyNegativeNumeralFactor(Context & context, P } template -Evaluation Expression::approximateToEvaluation(Context& context, Preferences::AngleUnit angleUnit) const { +Evaluation Expression::approximateToEvaluation(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + sApproximationEncounterComplex = false; // Reset interrupting flag because some evaluation methods use it sSimplificationHasBeenInterrupted = false; - return node()->approximate(U(), context, angleUnit); + Evaluation e = node()->approximate(U(), context, angleUnit); + if (complexFormat == Preferences::ComplexFormat::Real && sApproximationEncounterComplex) { + e = Complex::Undefined(); + } + return e; } Expression Expression::defaultReplaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression expression) { @@ -314,6 +320,10 @@ Expression Expression::defaultReplaceUnknown(const Symbol & symbol) { /* Complex */ +void Expression::SetEncounterComplex(bool encounterComplex) { + sApproximationEncounterComplex = encounterComplex; +} + Preferences::ComplexFormat Expression::UpdatedComplexFormatWithTextInput(Preferences::ComplexFormat complexFormat, const char * textInput) { if (complexFormat == Preferences::ComplexFormat::Real && strchr(textInput, Ion::Charset::IComplex) != nullptr) { return Preferences::ComplexFormat::Cartesian; @@ -538,27 +548,27 @@ Expression Expression::setSign(ExpressionNode::Sign s, Context * context, Prefer template Expression Expression::approximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { - return isUninitialized() ? Undefined() : approximateToEvaluation(context, angleUnit).complexToExpression(complexFormat); + return isUninitialized() ? Undefined() : approximateToEvaluation(context, complexFormat, angleUnit).complexToExpression(complexFormat); } template -U Expression::approximateToScalar(Context& context, Preferences::AngleUnit angleUnit) const { - return approximateToEvaluation(context, angleUnit).toScalar(); +U Expression::approximateToScalar(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + return approximateToEvaluation(context, complexFormat, angleUnit).toScalar(); } template U Expression::approximateToScalar(const char * text, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { Expression exp = ParseAndSimplify(text, context, UpdatedComplexFormatWithTextInput(complexFormat, text), angleUnit); assert(!exp.isUninitialized()); - return exp.approximateToScalar(context, angleUnit); + return exp.approximateToScalar(context, complexFormat, angleUnit); } template -U Expression::approximateWithValueForSymbol(const char * symbol, U x, Context & context, Preferences::AngleUnit angleUnit) const { +U Expression::approximateWithValueForSymbol(const char * symbol, U x, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { VariableContext variableContext = VariableContext(symbol, &context); variableContext.setApproximationForVariable(x); - return approximateToScalar(variableContext, angleUnit); + return approximateToScalar(variableContext, complexFormat, angleUnit); } template @@ -580,7 +590,9 @@ bool Expression::isMinusOne(const Expression e) { } Expression Expression::CreateComplexExpression(Expression ra, Expression tb, Preferences::ComplexFormat complexFormat, bool undefined, bool isZeroRa, bool isOneRa, bool isZeroTb, bool isOneTb, bool isNegativeRa, bool isNegativeTb) { - if (undefined) { + if (complexFormat == Preferences::ComplexFormat::Real && sApproximationEncounterComplex) { + return Unreal(); + } else if (undefined) { return Undefined(); } switch (complexFormat) { @@ -651,37 +663,42 @@ Expression Expression::CreateComplexExpression(Expression ra, Expression tb, Pre /* Expression roots/extrema solver*/ -typename Expression::Coordinate2D Expression::nextMinimum(const char * symbol, double start, double step, double max, Context & context, Preferences::AngleUnit angleUnit) const { - return nextMinimumOfExpression(symbol, start, step, max, [](const char * symbol, double x, Context & context, Preferences::AngleUnit angleUnit, const Expression expression0, const Expression expression1 = Expression()) { - return expression0.approximateWithValueForSymbol(symbol, x, context, angleUnit); - }, context, angleUnit); +typename Expression::Coordinate2D Expression::nextMinimum(const char * symbol, double start, double step, double max, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + complexFormat = UpdatedComplexFormatWithExpressionInput(complexFormat, *this, context); + return nextMinimumOfExpression(symbol, start, step, max, [](const char * symbol, double x, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression0, const Expression expression1 = Expression()) { + return expression0.approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit); + }, context, complexFormat, angleUnit); } -typename Expression::Coordinate2D Expression::nextMaximum(const char * symbol, double start, double step, double max, Context & context, Preferences::AngleUnit angleUnit) const { - Coordinate2D minimumOfOpposite = nextMinimumOfExpression(symbol, start, step, max, [](const char * symbol, double x, Context & context, Preferences::AngleUnit angleUnit, const Expression expression0, const Expression expression1 = Expression()) { - return -expression0.approximateWithValueForSymbol(symbol, x, context, angleUnit); - }, context, angleUnit); +typename Expression::Coordinate2D Expression::nextMaximum(const char * symbol, double start, double step, double max, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + complexFormat = UpdatedComplexFormatWithExpressionInput(complexFormat, *this, context); + Coordinate2D minimumOfOpposite = nextMinimumOfExpression(symbol, start, step, max, [](const char * symbol, double x, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression0, const Expression expression1 = Expression()) { + return -expression0.approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit); + }, context, complexFormat, angleUnit); return {.abscissa = minimumOfOpposite.abscissa, .value = -minimumOfOpposite.value}; } -double Expression::nextRoot(const char * symbol, double start, double step, double max, Context & context, Preferences::AngleUnit angleUnit) const { - return nextIntersectionWithExpression(symbol, start, step, max, [](const char * symbol, double x, Context & context, Preferences::AngleUnit angleUnit, const Expression expression0, const Expression expression1 = Expression()) { - return expression0.approximateWithValueForSymbol(symbol, x, context, angleUnit); - }, context, angleUnit, nullptr); +double Expression::nextRoot(const char * symbol, double start, double step, double max, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + complexFormat = UpdatedComplexFormatWithExpressionInput(complexFormat, *this, context); + return nextIntersectionWithExpression(symbol, start, step, max, [](const char * symbol, double x, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression0, const Expression expression1 = Expression()) { + return expression0.approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit); + }, context, complexFormat, angleUnit, nullptr); } -typename Expression::Coordinate2D Expression::nextIntersection(const char * symbol, double start, double step, double max, Poincare::Context & context, Preferences::AngleUnit angleUnit, const Expression expression) const { - double resultAbscissa = nextIntersectionWithExpression(symbol, start, step, max, [](const char * symbol, double x, Context & context, Preferences::AngleUnit angleUnit, const Expression expression0, const Expression expression1) { - return expression0.approximateWithValueForSymbol(symbol, x, context, angleUnit)-expression1.approximateWithValueForSymbol(symbol, x, context, angleUnit); - }, context, angleUnit, expression); - typename Expression::Coordinate2D result = {.abscissa = resultAbscissa, .value = approximateWithValueForSymbol(symbol, resultAbscissa, context, angleUnit)}; +typename Expression::Coordinate2D Expression::nextIntersection(const char * symbol, double start, double step, double max, Poincare::Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression) const { + complexFormat = UpdatedComplexFormatWithExpressionInput(complexFormat, *this, context); + complexFormat = UpdatedComplexFormatWithExpressionInput(complexFormat, expression, context); + double resultAbscissa = nextIntersectionWithExpression(symbol, start, step, max, [](const char * symbol, double x, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression0, const Expression expression1) { + return expression0.approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit)-expression1.approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit); + }, context, complexFormat, angleUnit, expression); + typename Expression::Coordinate2D result = {.abscissa = resultAbscissa, .value = approximateWithValueForSymbol(symbol, resultAbscissa, context, complexFormat, angleUnit)}; if (std::fabs(result.value) < step*k_solverPrecision) { result.value = 0.0; } return result; } -typename Expression::Coordinate2D Expression::nextMinimumOfExpression(const char * symbol, double start, double step, double max, EvaluationAtAbscissa evaluate, Context & context, Preferences::AngleUnit angleUnit, const Expression expression, bool lookForRootMinimum) const { +typename Expression::Coordinate2D Expression::nextMinimumOfExpression(const char * symbol, double start, double step, double max, EvaluationAtAbscissa evaluate, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression, bool lookForRootMinimum) const { Coordinate2D result = {.abscissa = NAN, .value = NAN}; if (start == max || step == 0.0) { return result; @@ -690,13 +707,13 @@ typename Expression::Coordinate2D Expression::nextMinimumOfExpression(const char double x = start; bool endCondition = false; do { - bracketMinimum(symbol, x, step, max, bracket, evaluate, context, angleUnit, expression); - result = brentMinimum(symbol, bracket[0], bracket[2], evaluate, context, angleUnit, expression); + bracketMinimum(symbol, x, step, max, bracket, evaluate, context, complexFormat, angleUnit, expression); + result = brentMinimum(symbol, bracket[0], bracket[2], evaluate, context, complexFormat, angleUnit, expression); x = bracket[1]; // Because of float approximation, exact zero is never reached if (std::fabs(result.abscissa) < std::fabs(step)*k_solverPrecision) { result.abscissa = 0; - result.value = evaluate(symbol, 0, context, angleUnit, *this, expression); + result.value = evaluate(symbol, 0, context, complexFormat, angleUnit, *this, expression); } /* Ignore extremum whose value is undefined or too big because they are * really unlikely to be local extremum. */ @@ -718,13 +735,13 @@ typename Expression::Coordinate2D Expression::nextMinimumOfExpression(const char return result; } -void Expression::bracketMinimum(const char * symbol, double start, double step, double max, double result[3], EvaluationAtAbscissa evaluate, Context & context, Preferences::AngleUnit angleUnit, const Expression expression) const { +void Expression::bracketMinimum(const char * symbol, double start, double step, double max, double result[3], EvaluationAtAbscissa evaluate, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression) const { Coordinate2D p[3]; - p[0] = {.abscissa = start, .value = evaluate(symbol, start, context, angleUnit, *this, expression)}; - p[1] = {.abscissa = start+step, .value = evaluate(symbol, start+step, context, angleUnit, *this, expression)}; + p[0] = {.abscissa = start, .value = evaluate(symbol, start, context, complexFormat, angleUnit, *this, expression)}; + p[1] = {.abscissa = start+step, .value = evaluate(symbol, start+step, context, complexFormat, angleUnit, *this, expression)}; double x = start+2.0*step; while (step > 0.0 ? x <= max : x >= max) { - p[2] = {.abscissa = x, .value = evaluate(symbol, x, context, angleUnit, *this, expression)}; + p[2] = {.abscissa = x, .value = evaluate(symbol, x, context, complexFormat, angleUnit, *this, expression)}; if ((p[0].value > p[1].value || std::isnan(p[0].value)) && (p[2].value > p[1].value || std::isnan(p[2].value)) && (!std::isnan(p[0].value) || !std::isnan(p[2].value))) { result[0] = p[0].abscissa; result[1] = p[1].abscissa; @@ -743,11 +760,11 @@ void Expression::bracketMinimum(const char * symbol, double start, double step, result[2] = NAN; } -typename Expression::Coordinate2D Expression::brentMinimum(const char * symbol, double ax, double bx, EvaluationAtAbscissa evaluate, Context & context, Preferences::AngleUnit angleUnit, const Expression expression) const { +typename Expression::Coordinate2D Expression::brentMinimum(const char * symbol, double ax, double bx, EvaluationAtAbscissa evaluate, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression) const { /* Bibliography: R. P. Brent, Algorithms for finding zeros and extrema of * functions without calculating derivatives */ if (ax > bx) { - return brentMinimum(symbol, bx, ax, evaluate, context, angleUnit, expression); + return brentMinimum(symbol, bx, ax, evaluate, context, complexFormat, angleUnit, expression); } double e = 0.0; double a = ax; @@ -755,7 +772,7 @@ typename Expression::Coordinate2D Expression::brentMinimum(const char * symbol, double x = a+k_goldenRatio*(b-a); double v = x; double w = x; - double fx = evaluate(symbol, x, context, angleUnit, *this, expression); + double fx = evaluate(symbol, x, context, complexFormat, angleUnit, *this, expression); double fw = fx; double fv = fw; @@ -767,10 +784,10 @@ typename Expression::Coordinate2D Expression::brentMinimum(const char * symbol, double tol1 = k_sqrtEps*std::fabs(x)+1E-10; double tol2 = 2.0*tol1; if (std::fabs(x-m) <= tol2-0.5*(b-a)) { - double middleFax = evaluate(symbol, (x+a)/2.0, context, angleUnit, *this, expression); - double middleFbx = evaluate(symbol, (x+b)/2.0, context, angleUnit, *this, expression); - double fa = evaluate(symbol, a, context, angleUnit, *this, expression); - double fb = evaluate(symbol, b, context, angleUnit, *this, expression); + double middleFax = evaluate(symbol, (x+a)/2.0, context, complexFormat, angleUnit, *this, expression); + double middleFbx = evaluate(symbol, (x+b)/2.0, context, complexFormat, angleUnit, *this, expression); + double fa = evaluate(symbol, a, context, complexFormat, angleUnit, *this, expression); + double fb = evaluate(symbol, b, context, complexFormat, angleUnit, *this, expression); if (middleFax-fa <= k_sqrtEps && fx-middleFax <= k_sqrtEps && fx-middleFbx <= k_sqrtEps && middleFbx-fb <= k_sqrtEps) { Coordinate2D result = {.abscissa = x, .value = fx}; return result; @@ -803,7 +820,7 @@ typename Expression::Coordinate2D Expression::brentMinimum(const char * symbol, d = k_goldenRatio*e; } u = x + (std::fabs(d) >= tol1 ? d : (d>0 ? tol1 : -tol1)); - fu = evaluate(symbol, u, context, angleUnit, *this, expression); + fu = evaluate(symbol, u, context, complexFormat, angleUnit, *this, expression); if (fu <= fx) { if (u 0.0 ? x <= max : x >= max)); double extremumMax = std::isnan(result) ? max : result; Coordinate2D resultExtremum[2] = { - nextMinimumOfExpression(symbol, start, step, extremumMax, [](const char * symbol, double x, Context & context, Preferences::AngleUnit angleUnit, const Expression expression0, const Expression expression1) { + nextMinimumOfExpression(symbol, start, step, extremumMax, [](const char * symbol, double x, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression0, const Expression expression1) { if (expression1.isUninitialized()) { - return expression0.approximateWithValueForSymbol(symbol, x, context, angleUnit); + return expression0.approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit); } else { - return expression0.approximateWithValueForSymbol(symbol, x, context, angleUnit)-expression1.approximateWithValueForSymbol(symbol, x, context, angleUnit); + return expression0.approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit)-expression1.approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit); } - }, context, angleUnit, expression, true), - nextMinimumOfExpression(symbol, start, step, extremumMax, [](const char * symbol, double x, Context & context, Preferences::AngleUnit angleUnit, const Expression expression0, const Expression expression1) { + }, context, complexFormat, angleUnit, expression, true), + nextMinimumOfExpression(symbol, start, step, extremumMax, [](const char * symbol, double x, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression0, const Expression expression1) { if (expression1.isUninitialized()) { - return -expression0.approximateWithValueForSymbol(symbol, x, context, angleUnit); + return -expression0.approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit); } else { - return expression1.approximateWithValueForSymbol(symbol, x, context, angleUnit)-expression0.approximateWithValueForSymbol(symbol, x, context, angleUnit); + return expression1.approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit)-expression0.approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit); } - }, context, angleUnit, expression, true)}; + }, context, complexFormat, angleUnit, expression, true)}; for (int i = 0; i < 2; i++) { if (!std::isnan(resultExtremum[i].abscissa) && (std::isnan(result) || std::fabs(result - start) > std::fabs(resultExtremum[i].abscissa - start))) { result = resultExtremum[i].abscissa; @@ -878,12 +895,12 @@ double Expression::nextIntersectionWithExpression(const char * symbol, double st return result; } -void Expression::bracketRoot(const char * symbol, double start, double step, double max, double result[2], EvaluationAtAbscissa evaluation, Context & context, Preferences::AngleUnit angleUnit, const Expression expression) const { +void Expression::bracketRoot(const char * symbol, double start, double step, double max, double result[2], EvaluationAtAbscissa evaluation, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression) const { double a = start; double b = start+step; while (step > 0.0 ? b <= max : b >= max) { - double fa = evaluation(symbol, a, context, angleUnit, *this, expression); - double fb = evaluation(symbol, b, context, angleUnit,* this, expression); + double fa = evaluation(symbol, a, context, complexFormat, angleUnit, *this, expression); + double fb = evaluation(symbol, b, context, complexFormat, angleUnit,* this, expression); if (fa*fb <= 0) { result[0] = a; result[1] = b; @@ -896,17 +913,17 @@ void Expression::bracketRoot(const char * symbol, double start, double step, dou result[1] = NAN; } -double Expression::brentRoot(const char * symbol, double ax, double bx, double precision, EvaluationAtAbscissa evaluation, Context & context, Preferences::AngleUnit angleUnit, const Expression expression) const { +double Expression::brentRoot(const char * symbol, double ax, double bx, double precision, EvaluationAtAbscissa evaluation, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression) const { if (ax > bx) { - return brentRoot(symbol, bx, ax, precision, evaluation, context, angleUnit, expression); + return brentRoot(symbol, bx, ax, precision, evaluation, context, complexFormat, angleUnit, expression); } double a = ax; double b = bx; double c = bx; double d = b-a; double e = b-a; - double fa = evaluation(symbol, a, context, angleUnit, *this, expression); - double fb = evaluation(symbol, b, context, angleUnit, *this, expression); + double fa = evaluation(symbol, a, context, complexFormat, angleUnit, *this, expression); + double fb = evaluation(symbol, b, context, complexFormat, angleUnit, *this, expression); double fc = fb; for (int i = 0; i < 100; i++) { if ((fb > 0.0 && fc > 0.0) || (fb < 0.0 && fc < 0.0)) { @@ -926,7 +943,7 @@ double Expression::brentRoot(const char * symbol, double ax, double bx, double p double tol1 = 2.0*DBL_EPSILON*std::fabs(b)+0.5*precision; double xm = 0.5*(c-b); if (std::fabs(xm) <= tol1 || fb == 0.0) { - double fbcMiddle = evaluation(symbol, 0.5*(b+c), context, angleUnit, *this, expression); + double fbcMiddle = evaluation(symbol, 0.5*(b+c), context, complexFormat, angleUnit, *this, expression); double isContinuous = (fb <= fbcMiddle && fbcMiddle <= fc) || (fc <= fbcMiddle && fbcMiddle <= fb); if (isContinuous) { return b; @@ -964,7 +981,7 @@ double Expression::brentRoot(const char * symbol, double ax, double bx, double p } else { b += xm > 0.0 ? tol1 : tol1; } - fb = evaluation(symbol, b, context, angleUnit, *this, expression); + fb = evaluation(symbol, b, context, complexFormat, angleUnit, *this, expression); } return NAN; } @@ -975,16 +992,16 @@ template double Expression::epsilon(); template Expression Expression::approximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; template Expression Expression::approximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; -template float Expression::approximateToScalar(Context& context, Preferences::AngleUnit angleUnit) const; -template double Expression::approximateToScalar(Context& context, Preferences::AngleUnit angleUnit) const; +template float Expression::approximateToScalar(Context& context, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) const; +template double Expression::approximateToScalar(Context& context, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) const; template float Expression::approximateToScalar(const char * text, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); template double Expression::approximateToScalar(const char * text, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); -template Evaluation Expression::approximateToEvaluation(Context& context, Preferences::AngleUnit angleUnit) const; -template Evaluation Expression::approximateToEvaluation(Context& context, Preferences::AngleUnit angleUnit) const; +template Evaluation Expression::approximateToEvaluation(Context& context, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) const; +template Evaluation Expression::approximateToEvaluation(Context& context, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) const; -template float Expression::approximateWithValueForSymbol(const char * symbol, float x, Context & context, Preferences::AngleUnit angleUnit) const; -template double Expression::approximateWithValueForSymbol(const char * symbol, double x, Context & context, Preferences::AngleUnit angleUnit) const; +template float Expression::approximateWithValueForSymbol(const char * symbol, float x, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; +template double Expression::approximateWithValueForSymbol(const char * symbol, double x, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; } diff --git a/poincare/src/function.cpp b/poincare/src/function.cpp index f21d0066e..89d0a11a8 100644 --- a/poincare/src/function.cpp +++ b/poincare/src/function.cpp @@ -85,7 +85,7 @@ Evaluation FunctionNode::templatedApproximate(Context& context, Preferences:: if (e.isUninitialized()) { return Complex::Undefined(); } - return e.approximateToEvaluation(context, angleUnit); + return e.node()->approximate(T(), context, angleUnit); } Function::Function(const char * name, size_t length) : diff --git a/poincare/src/integral.cpp b/poincare/src/integral.cpp index 93f159d9a..8d4383147 100644 --- a/poincare/src/integral.cpp +++ b/poincare/src/integral.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -66,7 +67,11 @@ Evaluation IntegralNode::templatedApproximate(Context & context, Preferences: template T IntegralNode::functionValueAtAbscissa(T x, Context & context, Preferences::AngleUnit angleUnit) const { - return Expression(childAtIndex(0)).approximateWithValueForSymbol(static_cast(childAtIndex(1))->name(), x, context, angleUnit); + // Here we cannot use Expression::approximateWithValueForSymbol which would reset the sApproximationEncounterComplex flag + assert(childAtIndex(1)->type() == Type::Symbol); + VariableContext variableContext = VariableContext(static_cast(childAtIndex(1))->name(), &context); + variableContext.setApproximationForVariable(x); + return childAtIndex(0)->approximate(T(), variableContext, angleUnit).toScalar(); } #ifdef LAGRANGE_METHOD diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index c9cc6b31f..19226410f 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -47,7 +47,7 @@ Evaluation StoreNode::templatedApproximate(Context& context, Preferences::Ang if (e.isUninitialized()) { return Complex::Undefined(); } - return e.approximateToEvaluation(context, angleUnit); + return e.node()->approximate(T(), context, angleUnit); } Expression Store::shallowReduce(Context & context) { diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 8a83647a1..5ccccc661 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -132,7 +132,7 @@ Evaluation SymbolNode::templatedApproximate(Context& context, Preferences::An if (e.isUninitialized()) { return Complex::Undefined(); } - return e.approximateToEvaluation(context, angleUnit); + return e.node()->approximate(T(), context, angleUnit); } Symbol::Symbol(const char * name, int length) : SymbolAbstract(TreePool::sharedPool()->createTreeNode(SymbolAbstract::AlignedNodeSize(length, sizeof(SymbolNode)))) { diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 92622c91c..07c761684 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -36,7 +36,7 @@ float Trigonometry::characteristicXRange(const Expression & e, Context & context /* To compute a, the slope of the expression child(0), we compute the * derivative of child(0) for any x value. */ Poincare::Derivative derivative = Poincare::Derivative::Builder(e.childAtIndex(0).clone(), Symbol(x, 1), Float(1.0f)); - float a = derivative.approximateToScalar(context, angleUnit); + float a = derivative.node()->approximate(float(), context, angleUnit).toScalar(); float pi = angleUnit == Preferences::AngleUnit::Radian ? M_PI : 180.0f; return 2.0f*pi/std::fabs(a); } @@ -248,7 +248,7 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& c // Step 1. Look for an expression of type "arccos(cos(x))", return x if (AreInverseFunctions(e.childAtIndex(0), e)) { - float trigoOp = e.childAtIndex(0).childAtIndex(0).approximateToScalar(context, angleUnit); + float trigoOp = e.childAtIndex(0).childAtIndex(0).node()->approximate(float(), context, angleUnit).toScalar(); if ((e.type() == ExpressionNode::Type::ArcCosine && trigoOp >= 0.0f && trigoOp <= pi) || (e.type() == ExpressionNode::Type::ArcSine && trigoOp >= -pi/2.0f && trigoOp <= pi/2.0f) || (e.type() == ExpressionNode::Type::ArcTangent && trigoOp >= -pi/2.0f && trigoOp <= pi/2.0f)) { @@ -260,7 +260,7 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& c // Step 2. Special case for arctan(sin(x)/cos(x)) if (e.type() == ExpressionNode::Type::ArcTangent && ExpressionIsEquivalentToTangent(e.childAtIndex(0))) { - float trigoOp = e.childAtIndex(0).childAtIndex(1).childAtIndex(0).approximateToScalar(context, angleUnit); + float trigoOp = e.childAtIndex(0).childAtIndex(1).childAtIndex(0).node()->approximate(float(), context, angleUnit).toScalar(); if (trigoOp >= -pi/2.0f && trigoOp <= pi/2.0f) { Expression result = e.childAtIndex(0).childAtIndex(1).childAtIndex(0); e.replaceWithInPlace(result); @@ -449,7 +449,7 @@ Expression Trigonometry::table(const Expression e, ExpressionNode::Type type, Co return Expression(); } // We approximate the given expression to quickly compare it to the cheat table entries. - float eValue = e.approximateToScalar(context, angleUnit); + float eValue = e.node()->approximate(float(), context, angleUnit).toScalar(); if (std::isnan(eValue) || std::isinf(eValue)) { return Expression(); } diff --git a/poincare/test/addition.cpp b/poincare/test/addition.cpp index 5adf26374..42c2c4af1 100644 --- a/poincare/test/addition.cpp +++ b/poincare/test/addition.cpp @@ -12,7 +12,7 @@ using namespace Poincare; static inline void assert_approximation_equals(const Expression i, float f) { Shared::GlobalContext c; - quiz_assert(i.approximateToScalar(c, Preferences::AngleUnit::Degree) == f); + quiz_assert(i.approximateToScalar(c, Cartesian, Degree) == f); } static inline void assert_parsed_expression_is_equal_to(const char * exp, Expression e) { diff --git a/poincare/test/function.cpp b/poincare/test/function.cpp index d8d9d654a..32c272f4f 100644 --- a/poincare/test/function.cpp +++ b/poincare/test/function.cpp @@ -11,7 +11,7 @@ using namespace Poincare; template void assert_exp_is_bounded(Expression exp, T lowBound, T upBound, bool upBoundIncluded = false) { Shared::GlobalContext globalContext; - T result = exp.approximateToScalar(globalContext, Radian); + T result = exp.approximateToScalar(globalContext, Cartesian, Radian); quiz_assert(result >= lowBound); quiz_assert(result < upBound || (result == upBound && upBoundIncluded)); } diff --git a/poincare/test/helper.cpp b/poincare/test/helper.cpp index f35ebadd0..b72b72352 100644 --- a/poincare/test/helper.cpp +++ b/poincare/test/helper.cpp @@ -159,10 +159,10 @@ void assert_parsed_expression_evaluates_to(const char * expression, const char * } template -void assert_parsed_expression_approximates_with_value_for_symbol(Expression expression, const char * symbol, T value, T approximation, Poincare::Preferences::AngleUnit angleUnit) { +void assert_parsed_expression_approximates_with_value_for_symbol(Expression expression, const char * symbol, T value, T approximation, Poincare::Preferences::ComplexFormat complexFormat, Poincare::Preferences::AngleUnit angleUnit) { Shared::GlobalContext globalContext; - T result = expression.approximateWithValueForSymbol(symbol, value, globalContext, angleUnit); - quiz_assert(std::fabs(result - approximation) < 10.0*Expression::epsilon()); + T result = expression.approximateWithValueForSymbol(symbol, value, globalContext, complexFormat, angleUnit); + quiz_assert((std::isnan(result) && std::isnan(approximation)) || std::fabs(result - approximation) < 10.0*Expression::epsilon()); } void assert_parsed_expression_simplify_to(const char * expression, const char * simplifiedExpression, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) { @@ -219,5 +219,5 @@ void assert_expression_layout_serialize_to(Poincare::Layout layout, const char * template void assert_parsed_expression_evaluates_to(char const*, char const *, Poincare::Preferences::AngleUnit, Poincare::Preferences::ComplexFormat, int); template void assert_parsed_expression_evaluates_to(char const*, char const *, Poincare::Preferences::AngleUnit, Poincare::Preferences::ComplexFormat, int); -template void assert_parsed_expression_approximates_with_value_for_symbol(Poincare::Expression, const char *, float, float, Poincare::Preferences::AngleUnit); -template void assert_parsed_expression_approximates_with_value_for_symbol(Poincare::Expression, const char *, double, double, Poincare::Preferences::AngleUnit); +template void assert_parsed_expression_approximates_with_value_for_symbol(Poincare::Expression, const char *, float, float, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit); +template void assert_parsed_expression_approximates_with_value_for_symbol(Poincare::Expression, const char *, double, double, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit); diff --git a/poincare/test/helper.h b/poincare/test/helper.h index e445f5488..ca04f6cb7 100644 --- a/poincare/test/helper.h +++ b/poincare/test/helper.h @@ -30,7 +30,7 @@ template void assert_parsed_expression_evaluates_to(const char * expression, const char * approximation, Poincare::Preferences::AngleUnit angleUnit = Degree, Poincare::Preferences::ComplexFormat complexFormat = Cartesian, int numberOfSignificantDigits = -1); template -void assert_parsed_expression_approximates_with_value_for_symbol(Poincare::Expression expression, const char * symbol, T value, T approximation, Poincare::Preferences::AngleUnit angleUnit = Degree); +void assert_parsed_expression_approximates_with_value_for_symbol(Poincare::Expression expression, const char * symbol, T value, T approximation, Poincare::Preferences::ComplexFormat complexFormat = Cartesian, Poincare::Preferences::AngleUnit angleUnit = Degree); void assert_parsed_expression_simplify_to(const char * expression, const char * simplifiedExpression, Poincare::Preferences::AngleUnit angleUnit = Poincare::Preferences::AngleUnit::Radian, Poincare::Preferences::ComplexFormat complexFormat = Poincare::Preferences::ComplexFormat::Cartesian); void assert_parsed_expression_serialize_to(Poincare::Expression expression, const char * serializedExpression, Poincare::Preferences::PrintFloatMode mode = DecimalMode, int numberOfSignifiantDigits = 7); diff --git a/poincare/test/user_variable.cpp b/poincare/test/user_variable.cpp index 5ac0ce40c..fc657cd3c 100644 --- a/poincare/test/user_variable.cpp +++ b/poincare/test/user_variable.cpp @@ -163,6 +163,17 @@ QUIZ_CASE(poincare_user_variable_functions_with_context) { // Clean the storage for other tests Ion::Storage::sharedStorage()->recordNamed("f.func").destroy(); + + // f: x->R(-1) + assert_simplify("R(-1)*R(-1)>f(x)"); + // Approximate f(?) with ? = 5 + // Cartesian + assert_parsed_expression_approximates_with_value_for_symbol(Function("f", 1, Symbol(Symbol::SpecialSymbols::UnknownX)), x, 1.0, -1.0); + // Real + assert_parsed_expression_approximates_with_value_for_symbol(Function("f", 1, Symbol(Symbol::SpecialSymbols::UnknownX)), x, 1.0, (double)NAN, Real); + + // Clean the storage for other tests + Ion::Storage::sharedStorage()->recordNamed("f.func").destroy(); } QUIZ_CASE(poincare_user_variable_properties) { From cbd3eeb3f6289811af55fde0dfdb4780357eb959 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 21 Dec 2018 18:04:04 +0100 Subject: [PATCH 142/373] [poincare] Turn i into unreal when complexFormat is Real --- poincare/src/constant.cpp | 14 ++++++++++---- poincare/src/number.cpp | 1 + poincare/test/properties.cpp | 5 +++++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/poincare/src/constant.cpp b/poincare/src/constant.cpp index 038ab3400..1e0964bd9 100644 --- a/poincare/src/constant.cpp +++ b/poincare/src/constant.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -54,10 +55,15 @@ Constant::Constant(char name) : SymbolAbstract(TreePool::sharedPool()->createTre } Expression Constant::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { - if (target == ExpressionNode::ReductionTarget::User && isIComplex()) { - ComplexCartesian c = ComplexCartesian::Builder(Rational(0), Rational(1)); - replaceWithInPlace(c); - return c; + Expression result; + if (complexFormat == Preferences::ComplexFormat::Real && isIComplex()) { + result = Unreal(); + } else if (target == ExpressionNode::ReductionTarget::User && isIComplex()) { + result = ComplexCartesian::Builder(Rational(0), Rational(1)); + } + if (!result.isUninitialized()) { + replaceWithInPlace(result); + return result; } return *this; } diff --git a/poincare/src/number.cpp b/poincare/src/number.cpp index 18875ba11..e991c254a 100644 --- a/poincare/src/number.cpp +++ b/poincare/src/number.cpp @@ -17,6 +17,7 @@ namespace Poincare { double NumberNode::doubleApproximation() const { switch (type()) { case Type::Undefined: + case Type::Unreal: return NAN; case Type::Infinity: return Number(this).sign() == Sign::Negative ? -INFINITY : INFINITY; diff --git a/poincare/test/properties.cpp b/poincare/test/properties.cpp index 031a3f043..01f7c7e30 100644 --- a/poincare/test/properties.cpp +++ b/poincare/test/properties.cpp @@ -56,6 +56,7 @@ QUIZ_CASE(poincare_polynomial_degree) { assert_parsed_expression_polynomial_degree("prediction(0.2,10)+1", -1); assert_parsed_expression_polynomial_degree("2-x-x^3", 3); assert_parsed_expression_polynomial_degree("P*x", 1); + assert_parsed_expression_polynomial_degree("R(-1)*x", -1, "x", Real); // f: x->x^2+Px+1 assert_simplify("1+P*x+x^2>f(x)"); assert_parsed_expression_polynomial_degree("f(x)", 2); @@ -157,4 +158,8 @@ QUIZ_CASE(poincare_get_polynomial_coefficients) { const char * coefficient4[] = {"1", "P", "1", 0}; //x^2+Pi*x+1 assert_simplify("1+P*x+x^2>f(x)"); assert_parsed_expression_has_polynomial_coefficient("f(x)", "x", coefficient4); + const char * coefficient5[] = {"0", "I", 0}; //R(-1)x + assert_parsed_expression_has_polynomial_coefficient("R(-1)x", "x", coefficient5); + const char * coefficient6[] = {0}; //R(-1)x + assert_parsed_expression_has_polynomial_coefficient("R(-1)x", "x", coefficient6, Real); } From 87391d65ee24d0219652d1c27eb387c04cb205c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 21 Dec 2018 18:11:15 +0100 Subject: [PATCH 143/373] [poincare] Missing header in sign_function --- poincare/src/sign_function.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/sign_function.cpp b/poincare/src/sign_function.cpp index ce7bd9868..329f62134 100644 --- a/poincare/src/sign_function.cpp +++ b/poincare/src/sign_function.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include namespace Poincare { From 05ef7008dcf0aac87aa9bb6c8f2827cedc1b649a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Sat, 22 Dec 2018 10:25:33 +0100 Subject: [PATCH 144/373] [solver] Fix bug: when the number of solutions is infinite, do not try to find the solution layouts --- apps/solver/equation_store.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/solver/equation_store.cpp b/apps/solver/equation_store.cpp index b7b444985..2b1ac89af 100644 --- a/apps/solver/equation_store.cpp +++ b/apps/solver/equation_store.cpp @@ -174,7 +174,7 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) { } /* Turn the results in layouts */ int solutionIndex = 0; - int initialNumberOfSolutions = m_numberOfSolutions; + int initialNumberOfSolutions = m_numberOfSolutions <= k_maxNumberOfExactSolutions ? m_numberOfSolutions : -1; // We iterate through the solutions and the potential delta for (int i = 0; i < initialNumberOfSolutions+1; i++) { if (!exactSolutions[i].isUninitialized()) { From 4e345b705096a1f3e1c0aa9db051294eb6493fbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 26 Dec 2018 15:30:26 +0100 Subject: [PATCH 145/373] [poincare] Unreal: approximating unreal set the sApproximationEncounterComplex to true --- poincare/include/poincare/undefined.h | 2 +- poincare/include/poincare/unreal.h | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/undefined.h b/poincare/include/poincare/undefined.h index 8a8ed7a10..25cffc411 100644 --- a/poincare/include/poincare/undefined.h +++ b/poincare/include/poincare/undefined.h @@ -35,7 +35,7 @@ public: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = 0) const override; -private: +protected: template Evaluation templatedApproximate() const; }; diff --git a/poincare/include/poincare/unreal.h b/poincare/include/poincare/unreal.h index 7b5e657e7..f09afa9ec 100644 --- a/poincare/include/poincare/unreal.h +++ b/poincare/include/poincare/unreal.h @@ -19,10 +19,24 @@ public: // Properties Type type() const override { return Type::Unreal; } + // Approximation + Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { + Expression::SetEncounterComplex(true); + return templatedApproximate(); + } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { + Expression::SetEncounterComplex(true); + return templatedApproximate(); + } + // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = 0) const override; private: + template Evaluation templatedApproximate() const { + Expression::SetEncounterComplex(true); + return UndefinedNode::templatedApproximate(); + } }; class Unreal final : public Number { From 2052ee43ae7f3414883a5d815ad78c79708c7161 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 26 Dec 2018 16:40:23 +0100 Subject: [PATCH 146/373] [apps][poincare] An expression is undefined if it is of type 'unreal' or 'undefined' --- apps/solver/equation.cpp | 2 +- apps/solver/equation_store.cpp | 2 +- poincare/src/complex_cartesian.cpp | 2 +- poincare/src/expression.cpp | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/solver/equation.cpp b/apps/solver/equation.cpp index 8032a9824..6d1083e36 100644 --- a/apps/solver/equation.cpp +++ b/apps/solver/equation.cpp @@ -28,7 +28,7 @@ void Equation::tidy() { Expression Equation::standardForm(Context * context) const { if (m_standardForm.isUninitialized()) { const Expression e = expression(context); - if (e.recursivelyMatches([](const Expression e, Context & context, bool replaceSymbols) { return e.type() == ExpressionNode::Type::Undefined || e.type() == ExpressionNode::Type::Infinity || Expression::IsMatrix(e, context, replaceSymbols); }, *context, true)) { + if (e.recursivelyMatches([](const Expression e, Context & context, bool replaceSymbols) { return e.isUndefined() || e.type() == ExpressionNode::Type::Infinity || Expression::IsMatrix(e, context, replaceSymbols); }, *context, true)) { m_standardForm = Undefined(); return m_standardForm; } diff --git a/apps/solver/equation_store.cpp b/apps/solver/equation_store.cpp index 2b1ac89af..f7748d336 100644 --- a/apps/solver/equation_store.cpp +++ b/apps/solver/equation_store.cpp @@ -108,7 +108,7 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) { int numberOfVariables = 0; for (int i = 0; i < numberOfDefinedModels(); i++) { const Expression e = definedModelAtIndex(i)->standardForm(context); - if (e.isUninitialized() || e.type() == ExpressionNode::Type::Undefined) { + if (e.isUninitialized() || e.isUndefined()) { return Error::EquationUndefined; } numberOfVariables = e.getVariables(*context, [](const char * symbol) { return true; }, (char *)m_variables, Poincare::SymbolAbstract::k_maxNameSize); diff --git a/poincare/src/complex_cartesian.cpp b/poincare/src/complex_cartesian.cpp index 74916e7a8..edcee823e 100644 --- a/poincare/src/complex_cartesian.cpp +++ b/poincare/src/complex_cartesian.cpp @@ -57,7 +57,7 @@ Expression ComplexCartesian::shallowBeautify(Context & context, Preferences::Com a = oppositeA.isUninitialized() ? a : oppositeA; b = oppositeB.isUninitialized() ? b : oppositeB; Expression e = Expression::CreateComplexExpression(a, b, Preferences::ComplexFormat::Cartesian, - a.type() == ExpressionNode::Type::Undefined || b.type() == ExpressionNode::Type::Undefined, + a.isUndefined() || b.isUndefined(), Expression::isZero(a), Expression::isOne(a), Expression::isZero(b), Expression::isOne(b), !oppositeA.isUninitialized(), !oppositeB.isUninitialized() diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index efb8737fa..1793f01c3 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -175,7 +175,7 @@ bool Expression::getLinearCoefficients(char * variables, int maxVariableSize, Ex /* degree is supposed to be 0 or 1. Otherwise, it means that equation * is 'undefined' due to the reduction of 0*inf for example. * (ie, x*y*inf = 0) */ - assert(!recursivelyMatches([](const Expression e, Context & context, bool replaceSymbols) { return e.type() == ExpressionNode::Type::Undefined; }, context, true)); + assert(!recursivelyMatches([](const Expression e, Context & context, bool replaceSymbols) { return e.isUndefined(); }, context, true)); return false; } /* The equation is can be written: a_1*x+a_0 with a_1 and a_0 x-independent. @@ -457,7 +457,7 @@ void Expression::simplifyAndApproximate(Expression * simplifiedExpression, Expre bool tbIsNegative = false; makePositive(&ra, &raIsNegative); makePositive(&tb, &tbIsNegative); - *simplifiedExpression = CreateComplexExpression(ra, tb, complexFormat, ra.type() == ExpressionNode::Type::Undefined || tb.type() == ExpressionNode::Type::Undefined, isZero(ra), isOne(ra), isZero(tb), isOne(tb), raIsNegative, tbIsNegative); + *simplifiedExpression = CreateComplexExpression(ra, tb, complexFormat, ra.isUndefined() || tb.isUndefined(), isZero(ra), isOne(ra), isZero(tb), isOne(tb), raIsNegative, tbIsNegative); } else { /* Case 2: The reduced expression has a complex component that could not * be bubbled up. */ From 226881773877e6fb620434587644ea58da24c92f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 26 Dec 2018 16:41:09 +0100 Subject: [PATCH 147/373] [poincare] The reduction routine is unterrupted if one of the expression leaves is unreal or undefined. If any leaf is unreal the result is unreal (unreal > undefined) --- poincare/src/expression.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 1793f01c3..793762992 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -207,13 +207,22 @@ void Expression::defaultDeepReduceChildren(Context & context, Preferences::Compl } Expression Expression::defaultShallowReduce() { + Expression result; for (int i = 0; i < numberOfChildren(); i++) { - if (childAtIndex(i).type() == ExpressionNode::Type::Undefined) { + // The reduction is shortcutted if one child is unreal or undefined: + // - the result is unreal is at least one child is unreal + // - the result is undefined is at least one child is undefined but no child is unreal + if (childAtIndex(i).type() == ExpressionNode::Type::Unreal) { + result = Unreal(); + break; + } else if (childAtIndex(i).type() == ExpressionNode::Type::Undefined) { Expression result = Undefined(); - replaceWithInPlace(result); - return result; } } + if (!result.isUninitialized()) { + replaceWithInPlace(result); + return result; + } return *this; } From e265b0319c87a76e01dfbb32e0d1ff5d7dbc4a02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 26 Dec 2018 16:42:15 +0100 Subject: [PATCH 148/373] [poincare] Power: avoid infinite loop of reduction 2^(1/2+a) --> 2^(1/2)*2^a --> 2^(1/2+a)-->... --- poincare/src/power.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index cb61da904..1edec1391 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -622,7 +622,7 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co } } } - // Step 12: a^(b+c+...) -> Rational(a^b)*a^c with a and b rational and a != 0 + // Step 12: a^(p/q+c+...) -> Rational(a^p)*a^(1/q+c+...) with a rational and a != 0 and p, q integers if (!letPowerAtRoot && childAtIndex(0).type() == ExpressionNode::Type::Rational && !childAtIndex(0).convert().isZero() @@ -631,12 +631,26 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co Addition a = childAtIndex(1).convert(); // Check is b is rational if (a.childAtIndex(0).type() == ExpressionNode::Type::Rational) { - const Rational rationalBase = childAtIndex(0).convert(); const Rational rationalIndex = a.childAtIndex(0).convert(); + if (rationalIndex.unsignedIntegerNumerator().isOne() && !rationalIndex.integerDenominator().isOne()) { + /* Do not reduce a^(1/q+c+...) to avoid potential infinite loop: + * a^(1/q+c+...) --> a^(1/q)*a^(c+...) --> a^(1/q+c+...)*/ + /* TODO: do something more sensible here: + * - add rule (-rational)^x --> (-1)^x*rational^x so we only consider + * positive rational or (-1) + * - change simplifyRationalRationalPower to be able to detect when no + * rational was extracted (ie 2^(1/2) --> 2^(1/2)) to avoid applying + * this rule in that case + * Once this is done, we can reduce 4^(1/2+a) --> 2*4^a which is not + * done so far to avoir the infinite loop: + * 2^(1/2+s) --> 2^(1/2)*2^s --> 2^(1/2+s)... */ + return *this; + } + const Rational rationalBase = childAtIndex(0).convert(); if (RationalExponentShouldNotBeReduced(rationalBase, rationalIndex)) { return *this; } - Power p1 = Power(childAtIndex(0).clone(), a.childAtIndex(0).clone()); + Power p1 = Power(childAtIndex(0).clone(), a.childAtIndex(0)); Power thisRef = *this; childAtIndex(1).convert().removeChildAtIndexInPlace(0); // p2 = a^(c+...) // if addition had only 2 children From c6177a8edc382e934dab0fb9d4d832d721451aa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 26 Dec 2018 17:59:29 +0100 Subject: [PATCH 149/373] [poincare] Power: fix bug: if a unreal node appears, it needs to be bubbled up --- poincare/src/power.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 1edec1391..0a7c0252b 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -911,8 +911,7 @@ Expression Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational r, bo m.addChildAtIndexInPlace(exp, m.numberOfChildren(), m.numberOfChildren()); exp.shallowReduce(context, complexFormat, angleUnit, target); } - m.sortChildrenInPlace(PowerNode::SimplificationOrder, false); - return m; + return m.shallowReduce(context, complexFormat, angleUnit, target); } Expression Power::removeSquareRootsFromDenominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { From ae2de436c25112a42c20f667e26750249199594b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 26 Dec 2018 18:00:14 +0100 Subject: [PATCH 150/373] [poincare] Add tests on ComplexFormat == Real --- poincare/test/complex.cpp | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/poincare/test/complex.cpp b/poincare/test/complex.cpp index 345d568fe..6bbd8dbb3 100644 --- a/poincare/test/complex.cpp +++ b/poincare/test/complex.cpp @@ -6,7 +6,33 @@ using namespace Poincare; -QUIZ_CASE(poincare_complex_parts) { +QUIZ_CASE(poincare_complex_evaluate) { + // Real + assert_parsed_expression_evaluates_to("I", "unreal", Radian, Real); + assert_parsed_expression_evaluates_to("R(-1)", "unreal", Radian, Real); + assert_parsed_expression_evaluates_to("R(-1)*R(-1)", "unreal", Radian, Real); + assert_parsed_expression_evaluates_to("ln(-2)", "unreal", Radian, Real); + + // Cartesian + assert_parsed_expression_evaluates_to("I", "I", Radian, Cartesian); + assert_parsed_expression_evaluates_to("R(-1)", "I", Radian, Cartesian); + assert_parsed_expression_evaluates_to("R(-1)*R(-1)", "-1", Radian, Cartesian); + assert_parsed_expression_evaluates_to("ln(-2)", "6.9314718055995E-1+3.1415926535898*I", Radian, Cartesian); + + // Real + assert_parsed_expression_evaluates_to("I", "X^(1.570796*I)", Radian, Polar); + assert_parsed_expression_evaluates_to("R(-1)", "X^(1.5707963267949*I)", Radian, Polar); + assert_parsed_expression_evaluates_to("R(-1)*R(-1)", "X^(3.1415926535898*I)", Radian, Polar); +} + +QUIZ_CASE(poincare_complex_simplify) { + // Real + assert_parsed_expression_simplify_to("I", "unreal", Radian, Real); + assert_parsed_expression_simplify_to("R(-1)", "unreal", Radian, Real); + assert_parsed_expression_simplify_to("R(-1)*R(-1)", "unreal", Radian, Real); + assert_parsed_expression_simplify_to("ln(-2)", "ln(-2)", Radian, Real); + + // Cartesian assert_parsed_expression_simplify_to("-2.3E3", "-2300", Radian, Cartesian); assert_parsed_expression_simplify_to("3", "3", Radian, Cartesian); assert_parsed_expression_simplify_to("inf", "inf", Radian, Cartesian); @@ -89,6 +115,7 @@ QUIZ_CASE(poincare_complex_parts) { // Clean the storage for other tests Ion::Storage::sharedStorage()->recordNamed("f.func").destroy(); + // Polar assert_parsed_expression_simplify_to("-2.3E3", "2300*X^(P*I)", Radian, Polar); assert_parsed_expression_simplify_to("3", "3", Radian, Polar); assert_parsed_expression_simplify_to("inf", "inf", Radian, Polar); @@ -134,5 +161,4 @@ QUIZ_CASE(poincare_complex_parts) { assert_parsed_expression_simplify_to("f(3)", "R(17)*X^((-2*atan(4)+P)/2*I)", Radian, Polar); // Clean the storage for other tests Ion::Storage::sharedStorage()->recordNamed("f.func").destroy(); - } From 786cefc3d4637c898f36ff24609cc5b2d89cb5e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 26 Dec 2018 18:00:45 +0100 Subject: [PATCH 151/373] [calculation] No special case for unreal calculation, it is handled in simplication and approximation routines. --- apps/calculation/calculation.cpp | 11 +++-------- apps/calculation/test/calculation_store.cpp | 8 ++++++-- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/apps/calculation/calculation.cpp b/apps/calculation/calculation.cpp index c37502501..36365d3d5 100644 --- a/apps/calculation/calculation.cpp +++ b/apps/calculation/calculation.cpp @@ -3,6 +3,7 @@ #include "../shared/poincare_helpers.h" #include #include +#include #include #include @@ -53,13 +54,6 @@ void Calculation::setContent(const char * c, Context * context, Expression ansEx PoincareHelpers::ParseAndSimplifyAndApproximate(m_inputText, &exactOutput, &approximateOutput, *context); PoincareHelpers::Serialize(exactOutput, m_exactOutputText, sizeof(m_exactOutputText)); PoincareHelpers::Serialize(approximateOutput, m_approximateOutputText, sizeof(m_approximateOutputText)); - /* Check ComplexFormat: if complex format is real and the input text doesn't - * contain any i complex, both approximate and exact result are set to - * Undefined if the approximate output is not a pure real.*/ - if (Preferences::sharedPreferences()->complexFormat() == Preferences::ComplexFormat::Real && strchr(m_inputText, Ion::Charset::IComplex) == nullptr && strchr(m_approximateOutputText, Ion::Charset::IComplex) != nullptr) { - strlcpy(m_exactOutputText, Undefined::Name(), Constant::MaxSerializedExpressionSize); - strlcpy(m_approximateOutputText, Undefined::Name(), Constant::MaxSerializedExpressionSize); - } } KDCoordinate Calculation::height(Context * context) { @@ -161,7 +155,8 @@ bool Calculation::shouldOnlyDisplayApproximateOutput(Context * context) { * significant digits, the two layouts are not equal, we display both. */ return exactAndApproximateDisplayedOutputsAreEqual(context) == Calculation::EqualSign::Equal; } - if (strcmp(m_exactOutputText, Undefined::Name()) == 0) { + if (strcmp(m_exactOutputText, Undefined::Name()) == 0 || strcmp(m_approximateOutputText, Unreal::Name()) == 0 ) { + /* if the approximate result is 'unreal' or the exact result is 'undef'*/ return true; } return input().isApproximate(*context) || exactOutput().isApproximate(*context); diff --git a/apps/calculation/test/calculation_store.cpp b/apps/calculation/test/calculation_store.cpp index f7679cc31..77672b631 100644 --- a/apps/calculation/test/calculation_store.cpp +++ b/apps/calculation/test/calculation_store.cpp @@ -120,17 +120,21 @@ QUIZ_CASE(calculation_complex_format) { Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Real); assertCalculationDisplay("1+I", false, true, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "1+I", &globalContext, &store); - assertCalculationDisplay("R(-1)", true, false, ::Calculation::Calculation::EqualSign::Unknown, "undef", nullptr, &globalContext, &store); - assertCalculationDisplay("ln(-2)", true, false, ::Calculation::Calculation::EqualSign::Unknown, "undef", nullptr, &globalContext, &store); + assertCalculationDisplay("R(-1)", false, true, ::Calculation::Calculation::EqualSign::Unknown, "unreal", nullptr, &globalContext, &store); + assertCalculationDisplay("ln(-2)", false, true, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "unreal", &globalContext, &store); + assertCalculationDisplay("R(-1)*R(-1)", false, true, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "unreal", &globalContext, &store); Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Cartesian); assertCalculationDisplay("1+I", false, true, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "1+I", &globalContext, &store); assertCalculationDisplay("R(-1)", false, true, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "I", &globalContext, &store); assertCalculationDisplay("ln(-2)", false, false, ::Calculation::Calculation::EqualSign::Approximation, "ln(-2)", nullptr, &globalContext, &store); + assertCalculationDisplay("R(-1)*R(-1)", false, true, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "-1", &globalContext, &store); Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Polar); assertCalculationDisplay("1+I", false, false, ::Calculation::Calculation::EqualSign::Approximation, "R(2)*X^(P/4*I)", nullptr, &globalContext, &store); assertCalculationDisplay("R(-1)", false, false, ::Calculation::Calculation::EqualSign::Approximation, "X^(P/2*I)", nullptr, &globalContext, &store); assertCalculationDisplay("ln(-2)", false, false, ::Calculation::Calculation::EqualSign::Approximation, "ln(-2)", nullptr, &globalContext, &store); + assertCalculationDisplay("R(-1)*R(-1)", false, false, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "X^(3.1415926535898*I)", &globalContext, &store); + Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Cartesian); } From 61d58b5dfa76c2d9b05ea1d08ce13e644a5e9300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 26 Dec 2018 18:01:53 +0100 Subject: [PATCH 152/373] [shared] SimplifyAndApproximate is used with already updated ComplexFormat --- apps/shared/poincare_helpers.h | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/shared/poincare_helpers.h b/apps/shared/poincare_helpers.h index 589d536a4..da42565a3 100644 --- a/apps/shared/poincare_helpers.h +++ b/apps/shared/poincare_helpers.h @@ -71,7 +71,6 @@ inline void ParseAndSimplifyAndApproximate(const char * text, Poincare::Expressi } inline void SimplifyAndApproximate(Poincare::Expression * e, Poincare::Expression * approximate, Poincare::Context & context, Poincare::Preferences::ComplexFormat complexFormat = Poincare::Preferences::sharedPreferences()->complexFormat()) { - complexFormat = Poincare::Expression::UpdatedComplexFormatWithExpressionInput(complexFormat, *e, context); e->simplifyAndApproximate(e, approximate, context, complexFormat, Poincare::Preferences::sharedPreferences()->angleUnit()); } From fc6793233f3c87c361209045a28eebb79b0d21ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 26 Dec 2018 18:02:30 +0100 Subject: [PATCH 153/373] [solver] I18n: add message 'unreal equation' --- apps/solver/base.de.i18n | 1 + apps/solver/base.en.i18n | 1 + apps/solver/base.es.i18n | 3 ++- apps/solver/base.fr.i18n | 1 + apps/solver/base.pt.i18n | 3 ++- 5 files changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/solver/base.de.i18n b/apps/solver/base.de.i18n index 7e5b250b1..47c1475e4 100644 --- a/apps/solver/base.de.i18n +++ b/apps/solver/base.de.i18n @@ -6,6 +6,7 @@ ResolveSystem = "Loesen des Gleichungssystems" UseEquationModel = "Verwenden Sie ein Gleichungsmodell" RequireEquation = "Die Eingabe muss eine Gleichung sein" UndefinedEquation = "Nicht definierte Gleichung" +UnrealEquation = "Nicht reelle Gleichung" TooManyVariables = "Es gibt zu viele Unbekannte" NonLinearSystem = "Das System ist nicht linear" Solution = "Loesung" diff --git a/apps/solver/base.en.i18n b/apps/solver/base.en.i18n index 0aaa4efe4..728584bab 100644 --- a/apps/solver/base.en.i18n +++ b/apps/solver/base.en.i18n @@ -5,6 +5,7 @@ ResolveEquation = "Solve the equation" ResolveSystem = "Solve the system" UseEquationModel = "Use an equation template" RequireEquation = "The input must be an equation" +UnrealEquation = "Unreal equation" UndefinedEquation = "Undefined equation" TooManyVariables = "There are too many unknowns" NonLinearSystem = "The system is not linear" diff --git a/apps/solver/base.es.i18n b/apps/solver/base.es.i18n index 7611eb06f..017826ef7 100644 --- a/apps/solver/base.es.i18n +++ b/apps/solver/base.es.i18n @@ -5,7 +5,8 @@ ResolveEquation = "Resolver la ecuación" ResolveSystem = "Resolver el sistema" UseEquationModel = "Usar un modelo de ecuación" RequireEquation = "La entrada debe ser una ecuación" -UndefinedEquation = "Ecuación indefinida" +UnrealEquation = "Una ecuación no es real" +UndefinedEquation = "Una ecuación es indefinida" TooManyVariables = "Hay demasiadas incógnitas" NonLinearSystem = "El sistema no es lineal" Solution = "Solucion" diff --git a/apps/solver/base.fr.i18n b/apps/solver/base.fr.i18n index f8d408d11..29a5c3b6d 100644 --- a/apps/solver/base.fr.i18n +++ b/apps/solver/base.fr.i18n @@ -6,6 +6,7 @@ ResolveSystem = "Résoudre le système" UseEquationModel = "Utiliser un modèle d'équation" RequireEquation = "L'entrée doit être une équation" UndefinedEquation = "Une equation est indéfinie" +UnrealEquation = "Une equation n'est pas réelle" TooManyVariables = "Le nombre d'inconnues est trop grand" NonLinearSystem = "Le système n'est pas linéaire" Solution = "Solution" diff --git a/apps/solver/base.pt.i18n b/apps/solver/base.pt.i18n index 96a97debf..147cf2025 100644 --- a/apps/solver/base.pt.i18n +++ b/apps/solver/base.pt.i18n @@ -5,7 +5,8 @@ ResolveEquation = "Resolver a equação" ResolveSystem = "Resolver o sistema" UseEquationModel = "Usar um modelo de equação" RequireEquation = "A entrada deve ser uma equação" -UndefinedEquation = "Equação indefinida" +UndefinedEquation = "Uma equação é indefinida" +UnrealEquation = "Uma equação não é real" TooManyVariables = "Existem muitas incógnitas" NonLinearSystem = "O sistema não é linear" Solution = "Solução" From 64d64507287165f1b617b1baab9ffb720c89c603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 26 Dec 2018 18:03:01 +0100 Subject: [PATCH 154/373] [solver] Handle unreal equations and equations whose solutions are unreal --- apps/solver/equation.cpp | 7 ++++++- apps/solver/equation_store.cpp | 17 ++++++++--------- apps/solver/equation_store.h | 7 ++++--- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/apps/solver/equation.cpp b/apps/solver/equation.cpp index 6d1083e36..faabddbf3 100644 --- a/apps/solver/equation.cpp +++ b/apps/solver/equation.cpp @@ -2,6 +2,7 @@ #include #include +#include #include using namespace Poincare; @@ -28,7 +29,11 @@ void Equation::tidy() { Expression Equation::standardForm(Context * context) const { if (m_standardForm.isUninitialized()) { const Expression e = expression(context); - if (e.recursivelyMatches([](const Expression e, Context & context, bool replaceSymbols) { return e.isUndefined() || e.type() == ExpressionNode::Type::Infinity || Expression::IsMatrix(e, context, replaceSymbols); }, *context, true)) { + if (e.type() == ExpressionNode::Type::Unreal) { + m_standardForm = Unreal(); + return m_standardForm; + } + if (e.recursivelyMatches([](const Expression e, Context & context, bool replaceSymbols) { return e.type() == ExpressionNode::Type::Undefined || e.type() == ExpressionNode::Type::Infinity || Expression::IsMatrix(e, context, replaceSymbols); }, *context, true)) { m_standardForm = Undefined(); return m_standardForm; } diff --git a/apps/solver/equation_store.cpp b/apps/solver/equation_store.cpp index f7748d336..97b66eaf1 100644 --- a/apps/solver/equation_store.cpp +++ b/apps/solver/equation_store.cpp @@ -108,9 +108,12 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) { int numberOfVariables = 0; for (int i = 0; i < numberOfDefinedModels(); i++) { const Expression e = definedModelAtIndex(i)->standardForm(context); - if (e.isUninitialized() || e.isUndefined()) { + if (e.isUninitialized() || e.type() == ExpressionNode::Type::Undefined) { return Error::EquationUndefined; } + if (e.type() == ExpressionNode::Type::Unreal) { + return Error::EquationUnreal; + } numberOfVariables = e.getVariables(*context, [](const char * symbol) { return true; }, (char *)m_variables, Poincare::SymbolAbstract::k_maxNameSize); if (numberOfVariables == -1) { return Error::TooManyVariables; @@ -178,19 +181,15 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) { // We iterate through the solutions and the potential delta for (int i = 0; i < initialNumberOfSolutions+1; i++) { if (!exactSolutions[i].isUninitialized()) { - /* Discard complex solutions if ComplexFormat is Real and the equation - * system was not explicitly complex. */ - if (Preferences::sharedPreferences()->complexFormat() == Preferences::ComplexFormat::Real && !isExplictlyComplex() && exactSolutionsApproximations[i].recursivelyMatches([](const Expression e, Context & context, bool replaceSymbols) { return e.type() == ExpressionNode::Type::Constant && static_cast(e).isIComplex(); }, *context, false)) { + if (exactSolutionsApproximations[i].type() == ExpressionNode::Type::Unreal) { + /* Discard unreal solutions. */ if (i < initialNumberOfSolutions) { // Discard the solution m_numberOfSolutions--; continue; - } else { - assert( i == initialNumberOfSolutions); - // Delta is not real - exactSolutions[i] = Undefined(); - exactSolutionsApproximations[i] = Undefined(); } + // Delta is not real + assert( i == initialNumberOfSolutions); } m_exactSolutionExactLayouts[solutionIndex] = PoincareHelpers::CreateLayout(exactSolutions[i]); m_exactSolutionApproximateLayouts[solutionIndex] = PoincareHelpers::CreateLayout(exactSolutionsApproximations[i]); diff --git a/apps/solver/equation_store.h b/apps/solver/equation_store.h index be4d91ff2..510c6dbdf 100644 --- a/apps/solver/equation_store.h +++ b/apps/solver/equation_store.h @@ -18,9 +18,10 @@ public: enum class Error : int16_t { NoError = 0, EquationUndefined = -1, - TooManyVariables = -2, - NonLinearSystem = -3, - RequireApproximateSolution = -4, + EquationUnreal = -2, + TooManyVariables = -3, + NonLinearSystem = -4, + RequireApproximateSolution = -5, }; /* EquationStore */ EquationStore(); From 8ac623be08c094defc8b181acb2f2a06f3172e5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 26 Dec 2018 18:03:29 +0100 Subject: [PATCH 155/373] [solver] ListController: display a pop up when an equation is 'unreal' --- apps/solver/list_controller.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/solver/list_controller.cpp b/apps/solver/list_controller.cpp index fdbef2483..d46095f21 100644 --- a/apps/solver/list_controller.cpp +++ b/apps/solver/list_controller.cpp @@ -182,6 +182,9 @@ void ListController::resolveEquations() { case EquationStore::Error::EquationUndefined: app()->displayWarning(I18n::Message::UndefinedEquation); return; + case EquationStore::Error::EquationUnreal: + app()->displayWarning(I18n::Message::UnrealEquation); + return; case EquationStore::Error::TooManyVariables: app()->displayWarning(I18n::Message::TooManyVariables); return; From d66d71a152d856cb5dda537d3e321a1128e65a0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 26 Dec 2018 18:05:21 +0100 Subject: [PATCH 156/373] [solver] Fix tests on unreal equations --- apps/solver/test/equation_store.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/solver/test/equation_store.cpp b/apps/solver/test/equation_store.cpp index 5e4f53e7f..9f5b86ff6 100644 --- a/apps/solver/test/equation_store.cpp +++ b/apps/solver/test/equation_store.cpp @@ -179,7 +179,7 @@ QUIZ_CASE(equation_solve_complex_format) { // x+R(-1) = 0 --> pas de solution dans R const char * equations1[] = {"x+R(-1)=0", 0}; - assert_equation_system_exact_solve_to(equations1, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesx, nullptr, 0); + assert_equation_system_exact_solve_to(equations1, EquationStore::Error::EquationUnreal, EquationStore::Type::LinearSystem, (const char **)variablesx, nullptr, 0); // x^2+x+1=0 --> pas de solution dans R const char * equations2[] = {"x^2+x+1=0", 0}; @@ -188,8 +188,8 @@ QUIZ_CASE(equation_solve_complex_format) { // x^2-R(-1)=0 --> pas de solution dans R const char * equations3[] = {"x^2-R(-1)=0", 0}; - const char * delta3[] = {"undef"}; - assert_equation_system_exact_solve_to(equations3, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, delta3, 0); + const char * delta3[] = {"unreal"}; + assert_equation_system_exact_solve_to(equations3, EquationStore::Error::EquationUnreal, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, delta3, 0); Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Cartesian); // x+I = 0 --> x = -I From ab555888aa3fb1dcb3449b2247938ec4a126c524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 27 Dec 2018 09:39:01 +0100 Subject: [PATCH 157/373] [solver] Clean and add tests on non-real equations --- apps/solver/test/equation_store.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/apps/solver/test/equation_store.cpp b/apps/solver/test/equation_store.cpp index 9f5b86ff6..5f6f28597 100644 --- a/apps/solver/test/equation_store.cpp +++ b/apps/solver/test/equation_store.cpp @@ -177,20 +177,24 @@ QUIZ_CASE(equation_solve_complex_format) { const char * solutions0[] = {"-I"}; assert_equation_system_exact_solve_to(equations0, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesx, solutions0, 1); - // x+R(-1) = 0 --> pas de solution dans R + // x+R(-1) = 0 --> Not defined in R const char * equations1[] = {"x+R(-1)=0", 0}; assert_equation_system_exact_solve_to(equations1, EquationStore::Error::EquationUnreal, EquationStore::Type::LinearSystem, (const char **)variablesx, nullptr, 0); - // x^2+x+1=0 --> pas de solution dans R + // x^2+x+1=0 --> No solution in R const char * equations2[] = {"x^2+x+1=0", 0}; const char * delta2[] = {"-3"}; assert_equation_system_exact_solve_to(equations2, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, delta2, 0); - // x^2-R(-1)=0 --> pas de solution dans R + // x^2-R(-1)=0 --> Not defined in R const char * equations3[] = {"x^2-R(-1)=0", 0}; const char * delta3[] = {"unreal"}; assert_equation_system_exact_solve_to(equations3, EquationStore::Error::EquationUnreal, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, delta3, 0); + // x+R(-1)*R(-1) = 0 --> Not defined in R + const char * equations4[] = {"x+R(-1)*R(-1)=0", 0}; + assert_equation_system_exact_solve_to(equations4, EquationStore::Error::EquationUnreal, EquationStore::Type::LinearSystem, (const char **)variablesx, nullptr, 0); + Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Cartesian); // x+I = 0 --> x = -I assert_equation_system_exact_solve_to(equations0, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesx, solutions0, 1); @@ -206,6 +210,10 @@ QUIZ_CASE(equation_solve_complex_format) { const char * solutions3[] = {"-(R(2))/(2)-(R(2))/(2)*I", "(R(2))/(2)+(R(2))/(2)*I","4*I"}; assert_equation_system_exact_solve_to(equations3, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions3, 2); + // x+R(-1)*R(-1) = 0 + const char * solutions4[] = {"1"}; + assert_equation_system_exact_solve_to(equations4, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesx, solutions4, 1); + Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Polar); // x+I = 0 --> x = e^(-pi/2*i) const char * solutions0Polar[] = {"X$-(P)/(2)*I#"}; From 6506588244952b5e75c2f7986c0b42feaec515b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 27 Dec 2018 11:32:07 +0100 Subject: [PATCH 158/373] [poincare] Complex: do not set the SetEncounterComplex flag when building an undefined complex --- poincare/src/complex.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/complex.cpp b/poincare/src/complex.cpp index 6f735d972..b0b9f54b1 100644 --- a/poincare/src/complex.cpp +++ b/poincare/src/complex.cpp @@ -22,7 +22,7 @@ namespace Poincare { template void ComplexNode::setComplex(std::complex c) { - if (c.imag() != 0.0) { + if (!std::isnan(c.imag()) && c.imag() != 0.0) { Expression::SetEncounterComplex(true); } this->real(c.real()); From b8826b1cf45b6b0213f1e9056065db39bbe9172d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 27 Dec 2018 11:32:50 +0100 Subject: [PATCH 159/373] [poincare] (-1)^(p/q) is not reduced the same way according to the complex format --- apps/calculation/test/calculation_store.cpp | 9 +++++++++ poincare/src/power.cpp | 22 ++++++++++++++++++--- poincare/test/complex.cpp | 5 +++++ 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/apps/calculation/test/calculation_store.cpp b/apps/calculation/test/calculation_store.cpp index 77672b631..3ca53e7f8 100644 --- a/apps/calculation/test/calculation_store.cpp +++ b/apps/calculation/test/calculation_store.cpp @@ -123,18 +123,27 @@ QUIZ_CASE(calculation_complex_format) { assertCalculationDisplay("R(-1)", false, true, ::Calculation::Calculation::EqualSign::Unknown, "unreal", nullptr, &globalContext, &store); assertCalculationDisplay("ln(-2)", false, true, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "unreal", &globalContext, &store); assertCalculationDisplay("R(-1)*R(-1)", false, true, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "unreal", &globalContext, &store); + assertCalculationDisplay("(-8)^(1/3)", false, true, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "-2", &globalContext, &store); + assertCalculationDisplay("(-8)^(2/3)", false, true, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "4", &globalContext, &store); + assertCalculationDisplay("(-2)^(1/4)", false, true, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "unreal", &globalContext, &store); Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Cartesian); assertCalculationDisplay("1+I", false, true, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "1+I", &globalContext, &store); assertCalculationDisplay("R(-1)", false, true, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "I", &globalContext, &store); assertCalculationDisplay("ln(-2)", false, false, ::Calculation::Calculation::EqualSign::Approximation, "ln(-2)", nullptr, &globalContext, &store); assertCalculationDisplay("R(-1)*R(-1)", false, true, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "-1", &globalContext, &store); + assertCalculationDisplay("(-8)^(1/3)", false, false, ::Calculation::Calculation::EqualSign::Approximation, "1+R(3)*I", nullptr, &globalContext, &store); + assertCalculationDisplay("(-8)^(2/3)", false, false, ::Calculation::Calculation::EqualSign::Approximation, "-2+2*R(3)*I", nullptr, &globalContext, &store); + assertCalculationDisplay("(-2)^(1/4)", false, false, ::Calculation::Calculation::EqualSign::Approximation, "root(8,4)/2+root(8,4)/2*I", nullptr, &globalContext, &store); Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Polar); assertCalculationDisplay("1+I", false, false, ::Calculation::Calculation::EqualSign::Approximation, "R(2)*X^(P/4*I)", nullptr, &globalContext, &store); assertCalculationDisplay("R(-1)", false, false, ::Calculation::Calculation::EqualSign::Approximation, "X^(P/2*I)", nullptr, &globalContext, &store); assertCalculationDisplay("ln(-2)", false, false, ::Calculation::Calculation::EqualSign::Approximation, "ln(-2)", nullptr, &globalContext, &store); assertCalculationDisplay("R(-1)*R(-1)", false, false, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "X^(3.1415926535898*I)", &globalContext, &store); + assertCalculationDisplay("(-8)^(1/3)", false, false, ::Calculation::Calculation::EqualSign::Approximation, "2*X^(P/3*I)", nullptr, &globalContext, &store); + assertCalculationDisplay("(-8)^(2/3)", false, false, ::Calculation::Calculation::EqualSign::Approximation, "4*X^((2*P)/3*I)", nullptr, &globalContext, &store); + assertCalculationDisplay("(-2)^(1/4)", false, false, ::Calculation::Calculation::EqualSign::Approximation, "root(2,4)*X^(P/4*I)", nullptr, &globalContext, &store); Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Cartesian); } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 0a7c0252b..b1e8b4394 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -907,9 +908,24 @@ Expression Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational r, bo m.addChildAtIndexInPlace(p, 1, 1); } if (i.isNegative()) { - Expression exp = CreateComplexExponent(r, context, complexFormat, angleUnit, target); - m.addChildAtIndexInPlace(exp, m.numberOfChildren(), m.numberOfChildren()); - exp.shallowReduce(context, complexFormat, angleUnit, target); + if (complexFormat == Preferences::ComplexFormat::Real) { + /* On real numbers (-1)^(p/q) = + * - 1 if p is even + * - -1 if p and q are odd + * - has no real solution otherwise */ + if (!r.unsignedIntegerNumerator().isEven()) { + if (r.integerDenominator().isEven()) { + return Unreal(); + } else { + m.addChildAtIndexInPlace(Rational(-1), 0, m.numberOfChildren()); + } + } + } else { + /* On complex numbers, we pick the first root (-1)^(p/q) = e^(i*pi*p/q) */ + Expression exp = CreateComplexExponent(r, context, complexFormat, angleUnit, target); + m.addChildAtIndexInPlace(exp, m.numberOfChildren(), m.numberOfChildren()); + exp.shallowReduce(context, complexFormat, angleUnit, target); + } } return m.shallowReduce(context, complexFormat, angleUnit, target); } diff --git a/poincare/test/complex.cpp b/poincare/test/complex.cpp index 6bbd8dbb3..3d7e1a06e 100644 --- a/poincare/test/complex.cpp +++ b/poincare/test/complex.cpp @@ -31,6 +31,11 @@ QUIZ_CASE(poincare_complex_simplify) { assert_parsed_expression_simplify_to("R(-1)", "unreal", Radian, Real); assert_parsed_expression_simplify_to("R(-1)*R(-1)", "unreal", Radian, Real); assert_parsed_expression_simplify_to("ln(-2)", "ln(-2)", Radian, Real); + assert_parsed_expression_simplify_to("(-8)^(2/3)", "4", Radian, Real); + assert_parsed_expression_simplify_to("(-8)^(2/5)", "2*root(2,5)", Radian, Real); + assert_parsed_expression_simplify_to("(-8)^(1/5)", "-root(8,5)", Radian, Real); + assert_parsed_expression_simplify_to("(-8)^(1/4)", "unreal", Radian, Real); + assert_parsed_expression_simplify_to("(-8)^(1/3)", "-2", Radian, Real); // Cartesian assert_parsed_expression_simplify_to("-2.3E3", "-2300", Radian, Cartesian); From 3fd737ab721c4ea39cbac7d2dc5a2c2f71a616cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 27 Dec 2018 14:02:58 +0100 Subject: [PATCH 160/373] [poincare] Change name: sApproximationEncounterComplex --> sApproximationEncounteredComplex --- poincare/include/poincare/expression.h | 2 +- poincare/src/derivative.cpp | 2 +- poincare/src/expression.cpp | 10 +++++----- poincare/src/integral.cpp | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index ae6d8dde2..9db6f5428 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -194,7 +194,7 @@ public: Expression degreeToRadian(); /* Approximation Helper */ - // These methods reset the sApproximationEncounterComplex flag. They should not be use to implement node approximation + // These methods reset the sApproximationEncounteredComplex flag. They should not be use to implement node approximation template static U epsilon(); template Expression approximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; template U approximateToScalar(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; diff --git a/poincare/src/derivative.cpp b/poincare/src/derivative.cpp index b59f02091..a6675617f 100644 --- a/poincare/src/derivative.cpp +++ b/poincare/src/derivative.cpp @@ -78,7 +78,7 @@ T DerivativeNode::approximateWithArgument(T x, Context & context, Preferences::A assert(childAtIndex(1)->type() == Type::Symbol); VariableContext variableContext = VariableContext(static_cast(childAtIndex(1))->name(), &context); variableContext.setApproximationForVariable(x); - // Here we cannot use Expression::approximateWithValueForSymbol which would reset the sApproximationEncounterComplex flag + // Here we cannot use Expression::approximateWithValueForSymbol which would reset the sApproximationEncounteredComplex flag return childAtIndex(0)->approximate(T(), variableContext, angleUnit).toScalar(); } diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 793762992..a2e0d9c80 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -14,7 +14,7 @@ namespace Poincare { bool Expression::sSymbolReplacementsCountLock = false; -static bool sApproximationEncounterComplex = false; +static bool sApproximationEncounteredComplex = false; /* Constructor & Destructor */ @@ -280,11 +280,11 @@ Expression Expression::makePositiveAnyNegativeNumeralFactor(Context & context, P template Evaluation Expression::approximateToEvaluation(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { - sApproximationEncounterComplex = false; + sApproximationEncounteredComplex = false; // Reset interrupting flag because some evaluation methods use it sSimplificationHasBeenInterrupted = false; Evaluation e = node()->approximate(U(), context, angleUnit); - if (complexFormat == Preferences::ComplexFormat::Real && sApproximationEncounterComplex) { + if (complexFormat == Preferences::ComplexFormat::Real && sApproximationEncounteredComplex) { e = Complex::Undefined(); } return e; @@ -330,7 +330,7 @@ Expression Expression::defaultReplaceUnknown(const Symbol & symbol) { /* Complex */ void Expression::SetEncounterComplex(bool encounterComplex) { - sApproximationEncounterComplex = encounterComplex; + sApproximationEncounteredComplex = encounterComplex; } Preferences::ComplexFormat Expression::UpdatedComplexFormatWithTextInput(Preferences::ComplexFormat complexFormat, const char * textInput) { @@ -599,7 +599,7 @@ bool Expression::isMinusOne(const Expression e) { } Expression Expression::CreateComplexExpression(Expression ra, Expression tb, Preferences::ComplexFormat complexFormat, bool undefined, bool isZeroRa, bool isOneRa, bool isZeroTb, bool isOneTb, bool isNegativeRa, bool isNegativeTb) { - if (complexFormat == Preferences::ComplexFormat::Real && sApproximationEncounterComplex) { + if (complexFormat == Preferences::ComplexFormat::Real && sApproximationEncounteredComplex) { return Unreal(); } else if (undefined) { return Undefined(); diff --git a/poincare/src/integral.cpp b/poincare/src/integral.cpp index 8d4383147..187bf27cf 100644 --- a/poincare/src/integral.cpp +++ b/poincare/src/integral.cpp @@ -67,7 +67,7 @@ Evaluation IntegralNode::templatedApproximate(Context & context, Preferences: template T IntegralNode::functionValueAtAbscissa(T x, Context & context, Preferences::AngleUnit angleUnit) const { - // Here we cannot use Expression::approximateWithValueForSymbol which would reset the sApproximationEncounterComplex flag + // Here we cannot use Expression::approximateWithValueForSymbol which would reset the sApproximationEncounteredComplex flag assert(childAtIndex(1)->type() == Type::Symbol); VariableContext variableContext = VariableContext(static_cast(childAtIndex(1))->name(), &context); variableContext.setApproximationForVariable(x); From fe8825df355c528a7957b945553ae6ca81c9ea88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 27 Dec 2018 15:08:12 +0100 Subject: [PATCH 161/373] [shared] PoincareHelpers: update the complexFormat (force it to Cartesian with complex input). --- apps/calculation/calculation.cpp | 3 +- apps/regression/model/model.cpp | 2 +- apps/shared/poincare_helpers.h | 51 +++++++++++++++------- apps/shared/storage_cartesian_function.cpp | 12 ++--- apps/solver/equation_store.cpp | 12 +++-- poincare/src/expression.cpp | 11 ++--- 6 files changed, 50 insertions(+), 41 deletions(-) diff --git a/apps/calculation/calculation.cpp b/apps/calculation/calculation.cpp index 36365d3d5..c98c20c34 100644 --- a/apps/calculation/calculation.cpp +++ b/apps/calculation/calculation.cpp @@ -181,7 +181,8 @@ Calculation::EqualSign Calculation::exactAndApproximateDisplayedOutputsAreEqual( if (exactOutputExpression.isUninitialized()) { exactOutputExpression = Undefined(); } - m_equalSign = exactOutputExpression.isEqualToItsApproximationLayout(approximateOutput(context), buffer, bufferSize, preferences->complexFormat(), preferences->angleUnit(), preferences->displayMode(), preferences->numberOfSignificantDigits(), *context) ? EqualSign::Equal : EqualSign::Approximation; + Preferences::ComplexFormat complexFormat = Expression::UpdatedComplexFormatWithTextInput(preferences->complexFormat(), m_inputText); + m_equalSign = exactOutputExpression.isEqualToItsApproximationLayout(approximateOutput(context), buffer, bufferSize, complexFormat, preferences->angleUnit(), preferences->displayMode(), preferences->numberOfSignificantDigits(), *context) ? EqualSign::Equal : EqualSign::Approximation; return m_equalSign; } diff --git a/apps/regression/model/model.cpp b/apps/regression/model/model.cpp index fb62cd1b0..867a88266 100644 --- a/apps/regression/model/model.cpp +++ b/apps/regression/model/model.cpp @@ -20,7 +20,7 @@ double Model::levelSet(double * modelCoefficients, double xMin, double step, dou PoincareHelpers::Simplify(&yExpression, *context); Expression modelExpression = simplifiedExpression(modelCoefficients, context); Preferences * preferences = Preferences::sharedPreferences(); - double result = modelExpression.nextIntersection("x", xMin, step, xMax, *context, preferences->complexFormat(), preferences->angleUnit(), yExpression).abscissa; + double result = PoincareHelpers::NextIntersection(modelExpression, "x", xMin, step, xMax, *context, yExpression).abscissa; return result; } diff --git a/apps/shared/poincare_helpers.h b/apps/shared/poincare_helpers.h index da42565a3..af2d43fa8 100644 --- a/apps/shared/poincare_helpers.h +++ b/apps/shared/poincare_helpers.h @@ -26,52 +26,72 @@ inline int Serialize(const Poincare::Expression e, char * buffer, int bufferSize template inline Poincare::Expression Approximate(const Poincare::Expression e, Poincare::Context & context) { Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); - Poincare::Preferences::ComplexFormat complexFormat = preferences->complexFormat(); - complexFormat = Poincare::Expression::UpdatedComplexFormatWithExpressionInput(complexFormat, e, context); + Poincare::Preferences::ComplexFormat complexFormat = Poincare::Expression::UpdatedComplexFormatWithExpressionInput(preferences->complexFormat(), e, context); return e.approximate(context, complexFormat, preferences->angleUnit()); } template inline T ApproximateToScalar(const Poincare::Expression e, Poincare::Context & context) { Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); - Poincare::Preferences::ComplexFormat complexFormat = preferences->complexFormat(); - complexFormat = Poincare::Expression::UpdatedComplexFormatWithExpressionInput(complexFormat, e, context); + Poincare::Preferences::ComplexFormat complexFormat = Poincare::Expression::UpdatedComplexFormatWithExpressionInput(preferences->complexFormat(), e, context); return e.approximateToScalar(context, complexFormat, preferences->angleUnit()); } template inline T ApproximateWithValueForSymbol(const Poincare::Expression e, const char * symbol, T x, Poincare::Context & context) { Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); - Poincare::Preferences::ComplexFormat complexFormat = preferences->complexFormat(); - complexFormat = Poincare::Expression::UpdatedComplexFormatWithExpressionInput(complexFormat, e, context); + Poincare::Preferences::ComplexFormat complexFormat = Poincare::Expression::UpdatedComplexFormatWithExpressionInput(preferences->complexFormat(), e, context); return e.approximateWithValueForSymbol(symbol, x, context, complexFormat, preferences->angleUnit()); } template inline T ApproximateToScalar(const char * text, Poincare::Context & context) { Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); - Poincare::Preferences::ComplexFormat complexFormat = preferences->complexFormat(); - complexFormat = Poincare::Expression::UpdatedComplexFormatWithTextInput(complexFormat, text); + Poincare::Preferences::ComplexFormat complexFormat = Poincare::Expression::UpdatedComplexFormatWithTextInput(preferences->complexFormat(), text); return Poincare::Expression::approximateToScalar(text, context, complexFormat, preferences->angleUnit()); } inline Poincare::Expression ParseAndSimplify(const char * text, Poincare::Context & context) { Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); - return Poincare::Expression::ParseAndSimplify(text, context, preferences->complexFormat(), preferences->angleUnit()); + Poincare::Preferences::ComplexFormat complexFormat = Poincare::Expression::UpdatedComplexFormatWithTextInput(preferences->complexFormat(), text); + return Poincare::Expression::ParseAndSimplify(text, context, complexFormat, preferences->angleUnit()); } -inline void Simplify(Poincare::Expression * e, Poincare::Context & context, Poincare::Preferences::ComplexFormat complexFormat = Poincare::Preferences::sharedPreferences()->complexFormat()) { - complexFormat = Poincare::Expression::UpdatedComplexFormatWithExpressionInput(complexFormat, *e, context); - *e = e->simplify(context, complexFormat, Poincare::Preferences::sharedPreferences()->angleUnit()); +inline void Simplify(Poincare::Expression * e, Poincare::Context & context) { + Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); + Poincare::Preferences::ComplexFormat complexFormat = Poincare::Expression::UpdatedComplexFormatWithExpressionInput(preferences->complexFormat(), *e, context); + *e = e->simplify(context, complexFormat, preferences->angleUnit()); } inline void ParseAndSimplifyAndApproximate(const char * text, Poincare::Expression * simplifiedExpression, Poincare::Expression * approximateExpression, Poincare::Context & context) { Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); - Poincare::Expression::ParseAndSimplifyAndApproximate(text, simplifiedExpression, approximateExpression, context, preferences->complexFormat(), preferences->angleUnit()); + Poincare::Preferences::ComplexFormat complexFormat = Poincare::Expression::UpdatedComplexFormatWithTextInput(preferences->complexFormat(), text); + Poincare::Expression::ParseAndSimplifyAndApproximate(text, simplifiedExpression, approximateExpression, context, complexFormat, preferences->angleUnit()); } -inline void SimplifyAndApproximate(Poincare::Expression * e, Poincare::Expression * approximate, Poincare::Context & context, Poincare::Preferences::ComplexFormat complexFormat = Poincare::Preferences::sharedPreferences()->complexFormat()) { - e->simplifyAndApproximate(e, approximate, context, complexFormat, Poincare::Preferences::sharedPreferences()->angleUnit()); +inline typename Poincare::Expression::Coordinate2D NextMinimum(const Poincare::Expression e, const char * symbol, double start, double step, double max, Poincare::Context & context) { + Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); + Poincare::Preferences::ComplexFormat complexFormat = Poincare::Expression::UpdatedComplexFormatWithExpressionInput(preferences->complexFormat(), e, context); + return e.nextMinimum(symbol, start, step, max, context, complexFormat, preferences->angleUnit()); +} + +inline typename Poincare::Expression::Coordinate2D NextMaximum(const Poincare::Expression e, const char * symbol, double start, double step, double max, Poincare::Context & context) { + Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); + Poincare::Preferences::ComplexFormat complexFormat = Poincare::Expression::UpdatedComplexFormatWithExpressionInput(preferences->complexFormat(), e, context); + return e.nextMaximum(symbol, start, step, max, context, complexFormat, preferences->angleUnit()); +} + +inline double NextRoot(const Poincare::Expression e, const char * symbol, double start, double step, double max, Poincare::Context & context) { + Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); + Poincare::Preferences::ComplexFormat complexFormat = Poincare::Expression::UpdatedComplexFormatWithExpressionInput(preferences->complexFormat(), e, context); + return e.nextRoot(symbol, start, step, max, context, complexFormat, preferences->angleUnit()); +} + +inline typename Poincare::Expression::Coordinate2D NextIntersection(const Poincare::Expression e, const char * symbol, double start, double step, double max, Poincare::Context & context, const Poincare::Expression expression) { + Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); + Poincare::Preferences::ComplexFormat complexFormat = Poincare::Expression::UpdatedComplexFormatWithExpressionInput(preferences->complexFormat(), e, context); + complexFormat = Poincare::Expression::UpdatedComplexFormatWithExpressionInput(complexFormat, expression, context); + return e.nextIntersection(symbol, start, step, max, context, complexFormat, preferences->angleUnit(), expression); } } @@ -79,4 +99,3 @@ inline void SimplifyAndApproximate(Poincare::Expression * e, Poincare::Expressio } #endif - diff --git a/apps/shared/storage_cartesian_function.cpp b/apps/shared/storage_cartesian_function.cpp index 1dc520041..ff46ec7cb 100644 --- a/apps/shared/storage_cartesian_function.cpp +++ b/apps/shared/storage_cartesian_function.cpp @@ -103,26 +103,22 @@ double StorageCartesianFunction::sumBetweenBounds(double start, double end, Poin Expression::Coordinate2D StorageCartesianFunction::nextMinimumFrom(double start, double step, double max, Context * context) const { const char unknownX[2] = {Poincare::Symbol::UnknownX, 0}; - Preferences * preferences = Preferences::sharedPreferences(); - return expressionReduced(context).nextMinimum(unknownX, start, step, max, *context, preferences->complexFormat(), preferences->angleUnit()); + return PoincareHelpers::NextMinimum(expressionReduced(context), unknownX, start, step, max, *context); } Expression::Coordinate2D StorageCartesianFunction::nextMaximumFrom(double start, double step, double max, Context * context) const { const char unknownX[2] = {Poincare::Symbol::UnknownX, 0}; - Preferences * preferences = Preferences::sharedPreferences(); - return expressionReduced(context).nextMaximum(unknownX, start, step, max, *context, preferences->complexFormat(), preferences->angleUnit()); + return PoincareHelpers::NextMaximum(expressionReduced(context), unknownX, start, step, max, *context); } double StorageCartesianFunction::nextRootFrom(double start, double step, double max, Context * context) const { const char unknownX[2] = {Poincare::Symbol::UnknownX, 0}; - Preferences * preferences = Preferences::sharedPreferences(); - return expressionReduced(context).nextRoot(unknownX, start, step, max, *context, preferences->complexFormat(), preferences->angleUnit()); + return PoincareHelpers::NextRoot(expressionReduced(context), unknownX, start, step, max, *context); } Expression::Coordinate2D StorageCartesianFunction::nextIntersectionFrom(double start, double step, double max, Poincare::Context * context, Expression e) const { const char unknownX[2] = {Poincare::Symbol::UnknownX, 0}; - Preferences * preferences = Preferences::sharedPreferences(); - return expressionReduced(context).nextIntersection(unknownX, start, step, max, *context, preferences->complexFormat(), preferences->angleUnit(), e); + return PoincareHelpers::NextIntersection(expressionReduced(context), unknownX, start, step, max, *context, e); } StorageCartesianFunction::CartesianFunctionRecordData * StorageCartesianFunction::recordData() const { diff --git a/apps/solver/equation_store.cpp b/apps/solver/equation_store.cpp index 97b66eaf1..1becac586 100644 --- a/apps/solver/equation_store.cpp +++ b/apps/solver/equation_store.cpp @@ -78,8 +78,7 @@ bool EquationStore::haveMoreApproximationSolutions(Context * context) { return false; } double step = (m_intervalApproximateSolutions[1]-m_intervalApproximateSolutions[0])*k_precision; - Preferences * preferences = Preferences::sharedPreferences(); - return !std::isnan(definedModelAtIndex(0)->standardForm(context).nextRoot(m_variables[0], m_approximateSolutions[m_numberOfSolutions-1], step, m_intervalApproximateSolutions[1], *context, preferences->complexFormat(), preferences->angleUnit())); + return !std::isnan(PoincareHelpers::NextRoot(definedModelAtIndex(0)->standardForm(context), m_variables[0], m_approximateSolutions[m_numberOfSolutions-1], step, m_intervalApproximateSolutions[1], *context)); } void EquationStore::approximateSolve(Poincare::Context * context) { @@ -88,9 +87,8 @@ void EquationStore::approximateSolve(Poincare::Context * context) { m_numberOfSolutions = 0; double start = m_intervalApproximateSolutions[0]; double step = (m_intervalApproximateSolutions[1]-m_intervalApproximateSolutions[0])*k_precision; - Preferences * preferences = Preferences::sharedPreferences(); for (int i = 0; i < k_maxNumberOfApproximateSolutions; i++) { - m_approximateSolutions[i] = definedModelAtIndex(0)->standardForm(context).nextRoot(m_variables[0], start, step, m_intervalApproximateSolutions[1], *context, preferences->complexFormat(), preferences->angleUnit()); + m_approximateSolutions[i] = PoincareHelpers::NextRoot(definedModelAtIndex(0)->standardForm(context), m_variables[0], start, step, m_intervalApproximateSolutions[1], *context); if (std::isnan(m_approximateSolutions[i])) { break; } else { @@ -252,7 +250,7 @@ EquationStore::Error EquationStore::resolveLinearSystem(Expression exactSolution m_numberOfSolutions = n; for (int i = 0; i < m_numberOfSolutions; i++) { exactSolutions[i] = Ab.matrixChild(i,n); - PoincareHelpers::SimplifyAndApproximate(&exactSolutions[i], &exactSolutionsApproximations[i], *context, updatedComplexFormat()); + exactSolutions[i].simplifyAndApproximate(&exactSolutions[i], &exactSolutionsApproximations[i], *context, updatedComplexFormat(), Poincare::Preferences::sharedPreferences()->angleUnit()); } } } @@ -264,7 +262,7 @@ EquationStore::Error EquationStore::oneDimensialPolynomialSolve(Expression exact assert(degree == 2); // Compute delta = b*b-4ac Expression delta = Subtraction(Power(coefficients[1].clone(), Rational(2)), Multiplication(Rational(4), coefficients[0].clone(), coefficients[2].clone())); - PoincareHelpers::Simplify(&delta, *context, updatedComplexFormat()); + delta = delta.simplify(*context, updatedComplexFormat(), Poincare::Preferences::sharedPreferences()->angleUnit()); if (delta.isUninitialized()) { delta = Poincare::Undefined(); } @@ -281,7 +279,7 @@ EquationStore::Error EquationStore::oneDimensialPolynomialSolve(Expression exact } exactSolutions[m_numberOfSolutions] = delta; for (int i = 0; i <= m_numberOfSolutions; i++) { - PoincareHelpers::SimplifyAndApproximate(&exactSolutions[i], &exactSolutionsApproximations[i], *context, updatedComplexFormat()); + exactSolutions[i].simplifyAndApproximate(&exactSolutions[i], &exactSolutionsApproximations[i], *context, updatedComplexFormat(), Poincare::Preferences::sharedPreferences()->angleUnit()); } return Error::NoError; #if 0 diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index a2e0d9c80..96dd82867 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -383,7 +383,7 @@ Expression Expression::ParseAndSimplify(const char * text, Context & context, Pr if (exp.isUninitialized()) { return Undefined(); } - exp = exp.simplify(context, UpdatedComplexFormatWithTextInput(complexFormat, text), angleUnit); + exp = exp.simplify(context, complexFormat, angleUnit); /* simplify might have been interrupted, in which case the resulting * expression is uninitialized, so we need to check that. */ if (exp.isUninitialized()) { @@ -400,7 +400,7 @@ void Expression::ParseAndSimplifyAndApproximate(const char * text, Expression * *approximateExpression = Undefined(); return; } - exp.simplifyAndApproximate(simplifiedExpression, approximateExpression, context, UpdatedComplexFormatWithTextInput(complexFormat, text), angleUnit); + exp.simplifyAndApproximate(simplifiedExpression, approximateExpression, context, complexFormat, angleUnit); /* simplify might have been interrupted, in which case the resulting * expression is uninitialized, so we need to check that. */ if (simplifiedExpression->isUninitialized()) { @@ -568,7 +568,7 @@ U Expression::approximateToScalar(Context& context, Preferences::ComplexFormat c template U Expression::approximateToScalar(const char * text, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { - Expression exp = ParseAndSimplify(text, context, UpdatedComplexFormatWithTextInput(complexFormat, text), angleUnit); + Expression exp = ParseAndSimplify(text, context, complexFormat, angleUnit); assert(!exp.isUninitialized()); return exp.approximateToScalar(context, complexFormat, angleUnit); } @@ -673,14 +673,12 @@ Expression Expression::CreateComplexExpression(Expression ra, Expression tb, Pre /* Expression roots/extrema solver*/ typename Expression::Coordinate2D Expression::nextMinimum(const char * symbol, double start, double step, double max, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { - complexFormat = UpdatedComplexFormatWithExpressionInput(complexFormat, *this, context); return nextMinimumOfExpression(symbol, start, step, max, [](const char * symbol, double x, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression0, const Expression expression1 = Expression()) { return expression0.approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit); }, context, complexFormat, angleUnit); } typename Expression::Coordinate2D Expression::nextMaximum(const char * symbol, double start, double step, double max, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { - complexFormat = UpdatedComplexFormatWithExpressionInput(complexFormat, *this, context); Coordinate2D minimumOfOpposite = nextMinimumOfExpression(symbol, start, step, max, [](const char * symbol, double x, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression0, const Expression expression1 = Expression()) { return -expression0.approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit); }, context, complexFormat, angleUnit); @@ -688,15 +686,12 @@ typename Expression::Coordinate2D Expression::nextMaximum(const char * symbol, d } double Expression::nextRoot(const char * symbol, double start, double step, double max, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { - complexFormat = UpdatedComplexFormatWithExpressionInput(complexFormat, *this, context); return nextIntersectionWithExpression(symbol, start, step, max, [](const char * symbol, double x, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression0, const Expression expression1 = Expression()) { return expression0.approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit); }, context, complexFormat, angleUnit, nullptr); } typename Expression::Coordinate2D Expression::nextIntersection(const char * symbol, double start, double step, double max, Poincare::Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression) const { - complexFormat = UpdatedComplexFormatWithExpressionInput(complexFormat, *this, context); - complexFormat = UpdatedComplexFormatWithExpressionInput(complexFormat, expression, context); double resultAbscissa = nextIntersectionWithExpression(symbol, start, step, max, [](const char * symbol, double x, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression0, const Expression expression1) { return expression0.approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit)-expression1.approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit); }, context, complexFormat, angleUnit, expression); From 2ea39fcaa4a66a069246ea7a6ed0fbb2aa1825ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 27 Dec 2018 15:09:20 +0100 Subject: [PATCH 162/373] [poincare] Addition: shallowBeautify sorts its children in decreasing order: 1+x+x^2 --> x^2+x+1 --- poincare/src/addition.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 279c6c9a4..26c48a371 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -99,6 +99,11 @@ Expression Addition::shallowBeautify(Context & context, Preferences::ComplexForm * Last but not least, special care must be taken when iterating over children * since we may remove some during the process. */ + /* Sort children in decreasing order: + * 1+x+x^2 --> x^2+x+1 + * 1+R(2) --> R(2)+1 */ + sortChildrenInPlace([](const ExpressionNode * e1, const ExpressionNode * e2, bool canBeInterrupted) { return ExpressionNode::SimplificationOrder(e2, e1, canBeInterrupted); }, true); + for (int i = 0; i < numberOfChildren(); i++) { // Try to make the child i positive if any negative numeral factor is found Expression subtractant = childAtIndex(i).makePositiveAnyNegativeNumeralFactor(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); From 6021579ae340fea63dd72c4285def0901bb9248e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 28 Dec 2018 09:40:14 +0100 Subject: [PATCH 163/373] [regression] Clean warnings --- apps/regression/model/model.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/regression/model/model.cpp b/apps/regression/model/model.cpp index 867a88266..f4a3e2cf6 100644 --- a/apps/regression/model/model.cpp +++ b/apps/regression/model/model.cpp @@ -19,7 +19,6 @@ double Model::levelSet(double * modelCoefficients, double xMin, double step, dou Expression yExpression = Number::DecimalNumber(y); PoincareHelpers::Simplify(&yExpression, *context); Expression modelExpression = simplifiedExpression(modelCoefficients, context); - Preferences * preferences = Preferences::sharedPreferences(); double result = PoincareHelpers::NextIntersection(modelExpression, "x", xMin, step, xMax, *context, yExpression).abscissa; return result; } From 97db53007a4b01d276580c248be34651aa9daf8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 28 Dec 2018 10:01:30 +0100 Subject: [PATCH 164/373] [apps] Fix wrong assertion that should be an escape case --- apps/shared/curve_view.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index 8b760d25e..165f8c843 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -186,7 +186,9 @@ enum class FloatingPosition : uint8_t { }; void CurveView::drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOrigin, bool graduationOnly, bool fixCoordinate, KDCoordinate fixedCoordinate) const { - assert(numberOfLabels(axis) > 1); + if (numberOfLabels(axis) < 1) { + return; + } float step = gridUnit(axis); float verticalCoordinate = fixCoordinate ? fixedCoordinate : std::round(floatToPixel(Axis::Vertical, 0.0f)); From ee974c0d34fda6a92bf9e2c1ea90a6295034fcf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 28 Dec 2018 10:18:02 +0100 Subject: [PATCH 165/373] [apps/probability] Factorize Normal law xMin and xMax --- apps/probability/law/normal_law.cpp | 22 ++++++++-------------- apps/probability/law/normal_law.h | 5 +++-- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/apps/probability/law/normal_law.cpp b/apps/probability/law/normal_law.cpp index e1c240d53..695094425 100644 --- a/apps/probability/law/normal_law.cpp +++ b/apps/probability/law/normal_law.cpp @@ -7,20 +7,6 @@ namespace Probability { -float NormalLaw::xMin() { - if (m_parameter2 == 0.0f) { - return m_parameter1 - 1.0f; - } - return m_parameter1 - 5.0f*std::fabs(m_parameter2); -} - -float NormalLaw::xMax() { - if (m_parameter2 == 0.0f) { - return m_parameter1 + 1.0f; - } - return m_parameter1 + 5.0f*std::fabs(m_parameter2); -} - float NormalLaw::yMin() { return -k_displayBottomMarginRatio*yMax(); } @@ -114,4 +100,12 @@ double NormalLaw::standardNormalCumulativeDistributiveInverseForProbability(doub return std::sqrt(2.0)*erfInv(2.0*probability-1.0); } +float NormalLaw::xExtremum(bool min) const { + int coefficient = (min ? -1 : 1); + if (m_parameter2 == 0.0f) { + return m_parameter1 + coefficient * 1.0f; + } + return m_parameter1 + coefficient * 5.0f * std::fabs(m_parameter2); +} + } diff --git a/apps/probability/law/normal_law.h b/apps/probability/law/normal_law.h index 7816ddaa7..c64eb5f2d 100644 --- a/apps/probability/law/normal_law.h +++ b/apps/probability/law/normal_law.h @@ -11,9 +11,9 @@ public: I18n::Message title() override { return I18n::Message::NormalLaw; } Type type() const override { return Type::Normal; } bool isContinuous() const override { return true; } - float xMin() override; + float xMin() override { return xExtremum(true); } float yMin() override; - float xMax() override; + float xMax() override { return xExtremum(false); } float yMax() override; I18n::Message parameterNameAtIndex(int index) override; I18n::Message parameterDefinitionAtIndex(int index) override; @@ -31,6 +31,7 @@ private: constexpr static double k_boundStandardNormalDistribution = 4.892; double standardNormalCumulativeDistributiveFunctionAtAbscissa(double abscissa) const; double standardNormalCumulativeDistributiveInverseForProbability(double probability); + float xExtremum(bool min) const; }; } From c9a0afc9503d4756473721c11d7921e2149941ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 28 Dec 2018 10:21:44 +0100 Subject: [PATCH 166/373] [apps/probability] Clean code spaces in NormalLaw --- apps/probability/law/normal_law.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/probability/law/normal_law.cpp b/apps/probability/law/normal_law.cpp index 695094425..4e8a51d03 100644 --- a/apps/probability/law/normal_law.cpp +++ b/apps/probability/law/normal_law.cpp @@ -8,7 +8,7 @@ namespace Probability { float NormalLaw::yMin() { - return -k_displayBottomMarginRatio*yMax(); + return - k_displayBottomMarginRatio * yMax(); } float NormalLaw::yMax() { @@ -17,7 +17,7 @@ float NormalLaw::yMax() { if (std::isnan(result) || result <= 0.0f) { result = 1.0f; } - return result*(1.0f+ k_displayTopMarginRatio); + return result * (1.0f + k_displayTopMarginRatio); } I18n::Message NormalLaw::parameterNameAtIndex(int index) { @@ -40,7 +40,7 @@ float NormalLaw::evaluateAtAbscissa(float x) const { if (m_parameter2 == 0.0f) { return NAN; } - return (1.0f/(std::fabs(m_parameter2)*std::sqrt(2.0f*M_PI)))*std::exp(-0.5f*std::pow((x-m_parameter1)/m_parameter2,2)); + return (1.0f/(std::fabs(m_parameter2) * std::sqrt(2.0f * M_PI))) * std::exp(-0.5f * std::pow((x - m_parameter1)/m_parameter2, 2)); } bool NormalLaw::authorizedValueAtIndex(float x, int index) const { @@ -61,17 +61,17 @@ void NormalLaw::setParameterAtIndex(float f, int index) { } double NormalLaw::cumulativeDistributiveFunctionAtAbscissa(double x) const { - if (m_parameter2 == 0.0f) { + if (m_parameter2 == 0.0f) { return NAN; } return standardNormalCumulativeDistributiveFunctionAtAbscissa((x-m_parameter1)/std::fabs(m_parameter2)); } double NormalLaw::cumulativeDistributiveInverseForProbability(double * probability) { - if (m_parameter2 == 0.0f) { + if (m_parameter2 == 0.0f) { return NAN; } - return standardNormalCumulativeDistributiveInverseForProbability(*probability)*std::fabs(m_parameter2) + m_parameter1; + return standardNormalCumulativeDistributiveInverseForProbability(*probability) * std::fabs(m_parameter2) + m_parameter1; } double NormalLaw::standardNormalCumulativeDistributiveFunctionAtAbscissa(double abscissa) const { @@ -84,7 +84,7 @@ double NormalLaw::standardNormalCumulativeDistributiveFunctionAtAbscissa(double if (abscissa > k_boundStandardNormalDistribution) { return 1.0; } - return 0.5+0.5*std::erf(abscissa/std::sqrt(2.0)); + return 0.5 + 0.5 * std::erf(abscissa/std::sqrt(2.0)); } double NormalLaw::standardNormalCumulativeDistributiveInverseForProbability(double probability) { @@ -97,7 +97,7 @@ double NormalLaw::standardNormalCumulativeDistributiveInverseForProbability(doub if (probability < 0.5) { return -standardNormalCumulativeDistributiveInverseForProbability(1-probability); } - return std::sqrt(2.0)*erfInv(2.0*probability-1.0); + return std::sqrt(2.0) * erfInv(2.0 * probability - 1.0); } float NormalLaw::xExtremum(bool min) const { From 4353d80b26847f6cae77075e1d3ac2397aa8cd57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 28 Dec 2018 13:45:47 +0100 Subject: [PATCH 167/373] [apps/probability] Increase Normal law values (draw centered reduced) --- apps/probability/law/normal_law.h | 2 +- apps/probability/law_curve_view.cpp | 32 ++++++++++++++++++++--------- apps/probability/law_curve_view.h | 14 +++++++++++-- apps/shared/curve_view.h | 1 + 4 files changed, 36 insertions(+), 13 deletions(-) diff --git a/apps/probability/law/normal_law.h b/apps/probability/law/normal_law.h index c64eb5f2d..77ebd4705 100644 --- a/apps/probability/law/normal_law.h +++ b/apps/probability/law/normal_law.h @@ -23,7 +23,7 @@ public: double cumulativeDistributiveFunctionAtAbscissa(double x) const override; double cumulativeDistributiveInverseForProbability(double * probability) override; private: - constexpr static double k_maxRatioMuSigma = 1000.0f; + constexpr static double k_maxRatioMuSigma = 1000000.0f; /* For the standard normal law, P(X < y) > 0.9999995 with y >= 4.892 so the * value displayed is 1. But this is dependent on the fact that we display * only 7 decimal values! */ diff --git a/apps/probability/law_curve_view.cpp b/apps/probability/law_curve_view.cpp index 4fbbd167d..19a4f63ad 100644 --- a/apps/probability/law_curve_view.cpp +++ b/apps/probability/law_curve_view.cpp @@ -1,20 +1,11 @@ #include "law_curve_view.h" +#include "law/normal_law.h" #include using namespace Shared; namespace Probability { -LawCurveView::LawCurveView(Law * law, Calculation * calculation) : - CurveView(law, nullptr, nullptr, nullptr), - m_labels{}, - m_law(law), - m_calculation(calculation) -{ - assert(law != nullptr); - assert(calculation != nullptr); -} - void LawCurveView::reload() { CurveView::reload(); markRectAsDirty(bounds()); @@ -26,6 +17,13 @@ void LawCurveView::drawRect(KDContext * ctx, KDRect rect) const { ctx->fillRect(bounds(), Palette::WallScreen); drawAxes(ctx, rect, Axis::Horizontal); drawLabels(ctx, rect, Axis::Horizontal, false); + if (m_law->type() == Law::Type::Normal) { + // Special case for the normal law, which has always the same curve + float pixelColorLowerBound = std::round(floatToPixel(Axis::Horizontal, lowerBound)); + float pixelColorUpperBound = std::round(floatToPixel(Axis::Horizontal, upperBound)); + drawStandardNormal(ctx, rect, pixelColorLowerBound, pixelColorUpperBound); + return; + } if (m_law->isContinuous()) { drawCurve(ctx, rect, EvaluateAtAbscissa, m_law, nullptr, Palette::YellowDark, true, lowerBound, upperBound, true); } else { @@ -45,4 +43,18 @@ float LawCurveView::EvaluateAtAbscissa(float abscissa, void * model, void * cont return law->evaluateAtAbscissa(abscissa); } +void LawCurveView::drawStandardNormal(KDContext * ctx, KDRect rect, float colorLowerBound, float colorUpperBound) const { + // Save the previous curve view range + LawCurveView * constCastedThis = const_cast(this); + CurveViewRange * previousRange = constCastedThis->curveViewRange(); + + // Draw a centered reduced normal curve + NormalLaw n; + constCastedThis->setCurveViewRange(&n); + drawCurve(ctx, rect, EvaluateAtAbscissa, &n, nullptr, Palette::YellowDark, true, pixelToFloat(Axis::Horizontal, colorLowerBound), pixelToFloat(Axis::Horizontal, colorUpperBound), true); + + // Put back the previous curve view range + constCastedThis->setCurveViewRange(previousRange); +} + } diff --git a/apps/probability/law_curve_view.h b/apps/probability/law_curve_view.h index c4517f528..bf1dc1354 100644 --- a/apps/probability/law_curve_view.h +++ b/apps/probability/law_curve_view.h @@ -12,14 +12,24 @@ namespace Probability { class LawCurveView : public Shared::CurveView { public: - LawCurveView(Law * law, Calculation * calculation); + LawCurveView(Law * law, Calculation * calculation) : + CurveView(law, nullptr, nullptr, nullptr), + m_labels{}, + m_law(law), + m_calculation(calculation) + { + assert(law != nullptr); + assert(calculation != nullptr); + } + void reload() override; void drawRect(KDContext * ctx, KDRect rect) const override; protected: char * label(Axis axis, int index) const override; private: - char m_labels[k_maxNumberOfXLabels][k_labelBufferMaxSize]; static float EvaluateAtAbscissa(float abscissa, void * model, void * context); + void drawStandardNormal(KDContext * ctx, KDRect rect, float colorLowerBound, float colorUpperBound) const; + char m_labels[k_maxNumberOfXLabels][k_labelBufferMaxSize]; Law * m_law; Calculation * m_calculation; }; diff --git a/apps/shared/curve_view.h b/apps/shared/curve_view.h index 7e295accc..952b12d18 100644 --- a/apps/shared/curve_view.h +++ b/apps/shared/curve_view.h @@ -38,6 +38,7 @@ public: float resolution() const; static float LabelsMarginRatio(Axis axis) { return axis == Axis::Horizontal ? k_labelsHorizontalMarginRatio : 0.0f; } protected: + CurveViewRange * curveViewRange() { return m_curveViewRange; } void setCurveViewRange(CurveViewRange * curveViewRange); // Drawing methods virtual float samplingRatio() const; From d3dd644e0d401d32b464ad90d85f034685b097ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 28 Dec 2018 15:59:10 +0100 Subject: [PATCH 168/373] [apps/curve_view] Draw graduations event if step << x --- apps/shared/curve_view.cpp | 42 +++++++++++++++----------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index 165f8c843..21669193c 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -186,11 +186,11 @@ enum class FloatingPosition : uint8_t { }; void CurveView::drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOrigin, bool graduationOnly, bool fixCoordinate, KDCoordinate fixedCoordinate) const { - if (numberOfLabels(axis) < 1) { + int numberLabels = numberOfLabels(axis); + if (numberLabels <= 1) { return; } - float step = gridUnit(axis); float verticalCoordinate = fixCoordinate ? fixedCoordinate : std::round(floatToPixel(Axis::Vertical, 0.0f)); float horizontalCoordinate = fixCoordinate ? fixedCoordinate : std::round(floatToPixel(Axis::Horizontal, 0.0f)); @@ -212,29 +212,28 @@ void CurveView::drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOr floatingLabels = FloatingPosition::Max; } } + /* There might be less labels than graduations, if the extrema labels are too * close to the screen edge to write them. We must thus draw the graduations * separately from the labels. */ + float labelStep = 2.0f * gridUnit(axis); + int minLabelPixelPosition = std::round(floatToPixel(axis, labelStep * std::ceil(min(axis)/labelStep))); + int maxLabelPixelPosition = std::round(floatToPixel(axis, labelStep * std::floor(max(axis)/labelStep))); + // Draw the graduations if (floatingLabels == FloatingPosition::None) { - float start = 2.0f*step*(std::ceil(min(axis)/(2.0f*step))); - float end = max(axis); - for (float x = start; x <= end; x += 2.0f*step) { - /* When |start| >> step, start + step = start. In that case, quit the - * infinite loop. */ - if (x == x-step || x == x+step) { - return; - } + for (int i = 0; i < numberLabels; i++) { + int labelPosition = minLabelPixelPosition + (((float)i)/((float)numberLabels-1)) * (maxLabelPixelPosition - minLabelPixelPosition); KDRect graduation = axis == Axis::Horizontal ? KDRect( - std::round(floatToPixel(Axis::Horizontal, x)), + labelPosition, verticalCoordinate -(k_labelGraduationLength-2)/2, 1, k_labelGraduationLength) : KDRect( horizontalCoordinate-(k_labelGraduationLength-2)/2, - std::round(floatToPixel(Axis::Vertical, x)), + labelPosition, k_labelGraduationLength, 1); ctx->fillRect(graduation, KDColorBlack); @@ -246,24 +245,18 @@ void CurveView::drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOr } // Draw the labels - float start = labelValueAtIndex(axis, 0); - float end = labelValueAtIndex(axis, numberOfLabels(axis) - 1); - int i = 0; - for (float x = start; x <= end + step; x += 2.0f*step) { - /* When |start| >> step, start + step = start. In that case, quit the - * infinite loop. */ - if (x == x-step || x == x+step) { - return; - } + for (int i = 0; i < numberLabels; i++) { + int labelPosition = minLabelPixelPosition + (((float)i)/((float)numberLabels-1)) * (maxLabelPixelPosition - minLabelPixelPosition); char * labelI = label(axis, i); KDSize textSize = k_font->stringSize(labelI); float xPosition = 0.0f; float yPosition = 0.0f; - if (-step < x && x < step && shiftOrigin && floatingLabels == FloatingPosition::None) { + + if (strcmp(labelI, "0") == 0 && shiftOrigin && floatingLabels == FloatingPosition::None) { xPosition = horizontalCoordinate - k_labelMargin - textSize.width(); yPosition = verticalCoordinate + k_labelMargin; } else if (axis == Axis::Horizontal) { - xPosition = std::round(floatToPixel(Axis::Horizontal, x)) - textSize.width()/2; + xPosition = labelPosition - textSize.width()/2; if (floatingLabels == FloatingPosition::None) { yPosition = verticalCoordinate + k_labelMargin; } else if (floatingLabels == FloatingPosition::Min) { @@ -272,7 +265,7 @@ void CurveView::drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOr yPosition = viewHeight - k_font->glyphSize().height() - k_labelMargin; } } else { - yPosition = std::round(floatToPixel(Axis::Vertical, x)) - textSize.height()/2; + yPosition = labelPosition - textSize.height()/2; if (floatingLabels == FloatingPosition::None) { xPosition = horizontalCoordinate - k_labelMargin - textSize.width(); } else if (floatingLabels == FloatingPosition::Min) { @@ -285,7 +278,6 @@ void CurveView::drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOr if (rect.intersects(KDRect(origin, textSize))) { ctx->drawString(labelI, origin, k_font, KDColorBlack); } - i++; } } From 155688540f662ee74d5d4a5cb38af03a04e902c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 28 Dec 2018 11:03:07 +0100 Subject: [PATCH 169/373] [apps/curve_view] Clean grid unit algorithm --- apps/shared/curve_view.h | 1 - apps/shared/curve_view_range.cpp | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/shared/curve_view.h b/apps/shared/curve_view.h index 952b12d18..e4381752e 100644 --- a/apps/shared/curve_view.h +++ b/apps/shared/curve_view.h @@ -36,7 +36,6 @@ public: void setOkView(View * okView); void setForceOkDisplay(bool force) { m_forceOkDisplay = force; } float resolution() const; - static float LabelsMarginRatio(Axis axis) { return axis == Axis::Horizontal ? k_labelsHorizontalMarginRatio : 0.0f; } protected: CurveViewRange * curveViewRange() { return m_curveViewRange; } void setCurveViewRange(CurveViewRange * curveViewRange); diff --git a/apps/shared/curve_view_range.cpp b/apps/shared/curve_view_range.cpp index dd958a2d4..8673ce7db 100644 --- a/apps/shared/curve_view_range.cpp +++ b/apps/shared/curve_view_range.cpp @@ -19,9 +19,7 @@ float CurveViewRange::yGridUnit() { return 0.0f; } -float CurveViewRange::computeGridUnit(Axis axis, float range1) { - float marginRatio = CurveView::LabelsMarginRatio(axis == Axis::X ? CurveView::Axis::Horizontal : CurveView::Axis::Vertical); - float range = range1 * (1.0f-2.0f*marginRatio); +float CurveViewRange::computeGridUnit(Axis axis, float range) { int a = 0; int b = 0; float maxNumberOfUnits = (axis == Axis::X) ? k_maxNumberOfXGridUnits : k_maxNumberOfYGridUnits; From 2cb921d501c982e8b0aa4ebd78f69ec89fe63a27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 28 Dec 2018 16:09:20 +0100 Subject: [PATCH 170/373] [apps] Clean comment --- apps/shared/curve_view.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/shared/curve_view.h b/apps/shared/curve_view.h index e4381752e..a53aedd53 100644 --- a/apps/shared/curve_view.h +++ b/apps/shared/curve_view.h @@ -6,6 +6,7 @@ #include "curve_view_range.h" #include "curve_view_cursor.h" #include "banner_view.h" +#include namespace Shared { @@ -46,7 +47,7 @@ protected: constexpr static KDCoordinate k_okHorizontalMargin = 10; constexpr static KDCoordinate k_labelGraduationLength = 6; constexpr static int k_numberSignificantDigits = 6; - constexpr static int k_labelBufferMaxSize = 1 + k_numberSignificantDigits + 3 + 3 + 1; // '-' + 6 significant digits + '.' + "E-" + 3 digits + null-terminating char + constexpr static int k_labelBufferMaxSize = 1 + k_numberSignificantDigits + 3 + 3 + 1; // '-' + significant digits + '.' + "E-" + 3 digits + null-terminating char constexpr static int k_maxNumberOfXLabels = CurveViewRange::k_maxNumberOfXGridUnits; constexpr static int k_maxNumberOfYLabels = CurveViewRange::k_maxNumberOfYGridUnits; constexpr static int k_externRectMargin = 2; From 57aada49ec78b1bb83ebb8a08e018a218bdb2a32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 28 Dec 2018 16:39:51 +0100 Subject: [PATCH 171/373] [apps/probability] Code cleaning --- apps/probability/Makefile | 1 - apps/probability/calculation/calculation.cpp | 5 -- apps/probability/calculation/calculation.h | 2 +- .../calculation/discrete_calculation.cpp | 20 -------- .../calculation/discrete_calculation.h | 12 ++--- .../finite_integral_calculation.cpp | 16 ------- .../calculation/finite_integral_calculation.h | 8 ++-- .../calculation/left_integral_calculation.cpp | 12 ----- .../calculation/left_integral_calculation.h | 8 ++-- .../right_integral_calculation.cpp | 12 ----- .../calculation/right_integral_calculation.h | 8 ++-- apps/probability/law/binomial_law.cpp | 17 ------- apps/probability/law/binomial_law.h | 10 ++-- apps/probability/law/exponential_law.cpp | 48 ++++--------------- apps/probability/law/exponential_law.h | 21 +++++--- apps/probability/law/law.cpp | 5 -- apps/probability/law/law.h | 2 +- apps/probability/law/one_parameter_law.cpp | 25 ---------- apps/probability/law/one_parameter_law.h | 15 ++++-- apps/probability/law/poisson_law.cpp | 43 ++++------------- apps/probability/law/poisson_law.h | 20 +++++--- apps/probability/law/two_parameter_law.cpp | 10 ---- apps/probability/law/two_parameter_law.h | 7 ++- apps/probability/law/uniform_law.cpp | 40 +++++----------- apps/probability/law/uniform_law.h | 10 ++-- 25 files changed, 102 insertions(+), 275 deletions(-) delete mode 100644 apps/probability/law/one_parameter_law.cpp diff --git a/apps/probability/Makefile b/apps/probability/Makefile index 7b0765032..8093a11a1 100644 --- a/apps/probability/Makefile +++ b/apps/probability/Makefile @@ -18,7 +18,6 @@ app_objs += $(addprefix apps/probability/,\ law/exponential_law.o\ law/law.o\ law/normal_law.o\ - law/one_parameter_law.o\ law/poisson_law.o\ law/two_parameter_law.o\ law/uniform_law.o\ diff --git a/apps/probability/calculation/calculation.cpp b/apps/probability/calculation/calculation.cpp index 69da88e76..80c5f1a6c 100644 --- a/apps/probability/calculation/calculation.cpp +++ b/apps/probability/calculation/calculation.cpp @@ -4,11 +4,6 @@ namespace Probability { -Calculation::Calculation(): - m_law(nullptr) -{ -} - void Calculation::setLaw(Law * law) { m_law = law; compute(0); diff --git a/apps/probability/calculation/calculation.h b/apps/probability/calculation/calculation.h index e30c42819..111f38599 100644 --- a/apps/probability/calculation/calculation.h +++ b/apps/probability/calculation/calculation.h @@ -13,7 +13,7 @@ public: RightIntegral, Discrete, }; - Calculation(); + Calculation() : m_law(nullptr) {} virtual ~Calculation() = default; virtual Type type() = 0; void setLaw(Law * law); diff --git a/apps/probability/calculation/discrete_calculation.cpp b/apps/probability/calculation/discrete_calculation.cpp index f9f15fb1b..46a166b7f 100644 --- a/apps/probability/calculation/discrete_calculation.cpp +++ b/apps/probability/calculation/discrete_calculation.cpp @@ -13,18 +13,6 @@ DiscreteCalculation::DiscreteCalculation() : compute(0); } -Calculation::Type DiscreteCalculation::type() { - return Type::Discrete; -} - -int DiscreteCalculation::numberOfParameters() { - return 2; -} - -int DiscreteCalculation::numberOfEditableParameters() { - return 1; -} - I18n::Message DiscreteCalculation::legendForParameterAtIndex(int index) { assert(index >= 0 && index < 2); if (index == 0) { @@ -49,14 +37,6 @@ double DiscreteCalculation::parameterAtIndex(int index) { return m_result; } -double DiscreteCalculation::lowerBound() { - return m_abscissa; -} - -double DiscreteCalculation::upperBound() { - return m_abscissa; -} - void DiscreteCalculation::compute(int indexKnownElement) { if (m_law == nullptr) { return; diff --git a/apps/probability/calculation/discrete_calculation.h b/apps/probability/calculation/discrete_calculation.h index e75eea55b..1273fd9dc 100644 --- a/apps/probability/calculation/discrete_calculation.h +++ b/apps/probability/calculation/discrete_calculation.h @@ -5,17 +5,17 @@ namespace Probability { -class DiscreteCalculation : public Calculation { +class DiscreteCalculation final : public Calculation { public: DiscreteCalculation(); - Type type() override; - int numberOfParameters() override; - int numberOfEditableParameters() override; + Type type() override { return Type::Discrete; } + int numberOfParameters() override { return 2; } + int numberOfEditableParameters() override { return 1; } I18n::Message legendForParameterAtIndex(int index) override; void setParameterAtIndex(double f, int index) override; double parameterAtIndex(int index) override; - double lowerBound() override; - double upperBound() override; + double lowerBound() override { return m_abscissa; } + double upperBound() override { return m_abscissa; } private: void compute(int indexKnownElement) override; double m_abscissa; diff --git a/apps/probability/calculation/finite_integral_calculation.cpp b/apps/probability/calculation/finite_integral_calculation.cpp index dc3c14e5a..3774a6439 100644 --- a/apps/probability/calculation/finite_integral_calculation.cpp +++ b/apps/probability/calculation/finite_integral_calculation.cpp @@ -15,14 +15,6 @@ FiniteIntegralCalculation::FiniteIntegralCalculation() : compute(0); } -Calculation::Type FiniteIntegralCalculation::type() { - return Type::FiniteIntegral; -} - -int FiniteIntegralCalculation::numberOfParameters() { - return 3; -} - int FiniteIntegralCalculation::numberOfEditableParameters() { if (m_law->type() == Law::Type::Normal) { return 3; @@ -67,14 +59,6 @@ double FiniteIntegralCalculation::parameterAtIndex(int index) { return m_result; } -double FiniteIntegralCalculation::lowerBound() { - return m_lowerBound; -} - -double FiniteIntegralCalculation::upperBound() { - return m_upperBound; -} - void FiniteIntegralCalculation::compute(int indexKnownElement) { if (m_law == nullptr) { return; diff --git a/apps/probability/calculation/finite_integral_calculation.h b/apps/probability/calculation/finite_integral_calculation.h index 5a6f79700..640279f46 100644 --- a/apps/probability/calculation/finite_integral_calculation.h +++ b/apps/probability/calculation/finite_integral_calculation.h @@ -8,14 +8,14 @@ namespace Probability { class FiniteIntegralCalculation : public Calculation { public: FiniteIntegralCalculation(); - Type type() override; - int numberOfParameters() override; + Type type() override { return Type::FiniteIntegral; } + int numberOfParameters() override { return 3; } int numberOfEditableParameters() override; I18n::Message legendForParameterAtIndex(int index) override; void setParameterAtIndex(double f, int index) override; double parameterAtIndex(int index) override; - double lowerBound() override; - double upperBound() override; + double lowerBound() override { return m_lowerBound; } + double upperBound() override { return m_upperBound; } private: void compute(int indexKnownElement) override; double m_lowerBound; diff --git a/apps/probability/calculation/left_integral_calculation.cpp b/apps/probability/calculation/left_integral_calculation.cpp index 3ddbf59ff..4dd9056a6 100644 --- a/apps/probability/calculation/left_integral_calculation.cpp +++ b/apps/probability/calculation/left_integral_calculation.cpp @@ -13,14 +13,6 @@ LeftIntegralCalculation::LeftIntegralCalculation() : compute(0); } -Calculation::Type LeftIntegralCalculation::type() { - return Type::LeftIntegral; -} - -int LeftIntegralCalculation::numberOfParameters() { - return 2; -} - I18n::Message LeftIntegralCalculation::legendForParameterAtIndex(int index) { assert(index >= 0 && index < 2); if (index == 0) { @@ -48,10 +40,6 @@ double LeftIntegralCalculation::parameterAtIndex(int index) { return m_result; } -double LeftIntegralCalculation::upperBound() { - return m_upperBound; -} - void LeftIntegralCalculation::compute(int indexKnownElement) { if (m_law == nullptr) { return; diff --git a/apps/probability/calculation/left_integral_calculation.h b/apps/probability/calculation/left_integral_calculation.h index ef58a9638..f998cdb12 100644 --- a/apps/probability/calculation/left_integral_calculation.h +++ b/apps/probability/calculation/left_integral_calculation.h @@ -5,15 +5,15 @@ namespace Probability { -class LeftIntegralCalculation : public Calculation { +class LeftIntegralCalculation final : public Calculation { public: LeftIntegralCalculation(); - Type type() override; - int numberOfParameters() override; + Type type() override { return Type::LeftIntegral; } + int numberOfParameters() override { return 2; } I18n::Message legendForParameterAtIndex(int index) override; void setParameterAtIndex(double f, int index) override; double parameterAtIndex(int index) override; - double upperBound() override; + double upperBound() override { return m_upperBound; } private: void compute(int indexKnownElement) override; double m_upperBound; diff --git a/apps/probability/calculation/right_integral_calculation.cpp b/apps/probability/calculation/right_integral_calculation.cpp index 20f8fdd07..48858f584 100644 --- a/apps/probability/calculation/right_integral_calculation.cpp +++ b/apps/probability/calculation/right_integral_calculation.cpp @@ -13,14 +13,6 @@ RightIntegralCalculation::RightIntegralCalculation() : compute(0); } -Calculation::Type RightIntegralCalculation::type() { - return Type::RightIntegral; -} - -int RightIntegralCalculation::numberOfParameters() { - return 2; -} - I18n::Message RightIntegralCalculation::legendForParameterAtIndex(int index) { assert(index >= 0 && index < 2); if (index == 0) { @@ -48,10 +40,6 @@ double RightIntegralCalculation::parameterAtIndex(int index) { return m_result; } -double RightIntegralCalculation::lowerBound() { - return m_lowerBound; -} - void RightIntegralCalculation::compute(int indexKnownElement) { if (m_law == nullptr) { return; diff --git a/apps/probability/calculation/right_integral_calculation.h b/apps/probability/calculation/right_integral_calculation.h index a6fcac127..71f1e5530 100644 --- a/apps/probability/calculation/right_integral_calculation.h +++ b/apps/probability/calculation/right_integral_calculation.h @@ -5,15 +5,15 @@ namespace Probability { -class RightIntegralCalculation : public Calculation { +class RightIntegralCalculation final : public Calculation { public: RightIntegralCalculation(); - Type type() override; - int numberOfParameters() override; + Type type() override { return Type::RightIntegral; } + int numberOfParameters() override { return 2; } I18n::Message legendForParameterAtIndex(int index) override; void setParameterAtIndex(double f, int index) override; double parameterAtIndex(int index) override; - double lowerBound() override; + double lowerBound() override { return m_lowerBound; } private: void compute(int indexKnownElement) override; double m_lowerBound; diff --git a/apps/probability/law/binomial_law.cpp b/apps/probability/law/binomial_law.cpp index 2c0f1490c..751247f62 100644 --- a/apps/probability/law/binomial_law.cpp +++ b/apps/probability/law/binomial_law.cpp @@ -4,23 +4,6 @@ namespace Probability { -BinomialLaw::BinomialLaw() : - TwoParameterLaw(20.0, 0.5) -{ -} - -I18n::Message BinomialLaw::title() { - return I18n::Message::BinomialLaw; -} - -Law::Type BinomialLaw::type() const { - return Type::Binomial; -} - -bool BinomialLaw::isContinuous() const { - return false; -} - I18n::Message BinomialLaw::parameterNameAtIndex(int index) { assert(index >= 0 && index < 2); if (index == 0) { diff --git a/apps/probability/law/binomial_law.h b/apps/probability/law/binomial_law.h index 54efc013a..ccd90e701 100644 --- a/apps/probability/law/binomial_law.h +++ b/apps/probability/law/binomial_law.h @@ -5,12 +5,12 @@ namespace Probability { -class BinomialLaw : public TwoParameterLaw { +class BinomialLaw final : public TwoParameterLaw { public: - BinomialLaw(); - I18n::Message title() override; - Type type() const override; - bool isContinuous() const override; + BinomialLaw() : TwoParameterLaw(20.0, 0.5) {} + I18n::Message title() override { return I18n::Message::BinomialLaw; } + Type type() const override { return Type::Binomial; } + bool isContinuous() const override { return false; } float xMin() override; float yMin() override; float xMax() override; diff --git a/apps/probability/law/exponential_law.cpp b/apps/probability/law/exponential_law.cpp index 5615d8e6d..b8111f9d9 100644 --- a/apps/probability/law/exponential_law.cpp +++ b/apps/probability/law/exponential_law.cpp @@ -1,41 +1,15 @@ #include "exponential_law.h" -#include #include #include -#include namespace Probability { -ExponentialLaw::ExponentialLaw() : - OneParameterLaw(1.0f) -{ -} - -I18n::Message ExponentialLaw::title() { - return I18n::Message::ExponentialLaw; -} - -Law::Type ExponentialLaw::type() const { - return Type::Exponential; -} - -bool ExponentialLaw::isContinuous() const { - return true; -} - -I18n::Message ExponentialLaw::parameterNameAtIndex(int index) { - assert(index == 0); - return I18n::Message::Lambda; -} - -I18n::Message ExponentialLaw::parameterDefinitionAtIndex(int index) { - assert(index == 0); - return I18n::Message::LambdaExponentialDefinition; -} - float ExponentialLaw::xMin() { - float max = xMax(); - return - k_displayLeftMarginRatio * max; + return - k_displayLeftMarginRatio * xMax(); +} + +float ExponentialLaw::yMin() { + return -k_displayBottomMarginRatio * yMax(); } float ExponentialLaw::xMax() { @@ -44,11 +18,7 @@ float ExponentialLaw::xMax() { if (result <= 0.0f) { result = 1.0f; } - return result*(1.0f+ k_displayRightMarginRatio); -} - -float ExponentialLaw::yMin() { - return -k_displayBottomMarginRatio*yMax(); + return result * (1.0f + k_displayRightMarginRatio); } float ExponentialLaw::yMax() { @@ -59,14 +29,14 @@ float ExponentialLaw::yMax() { if (result <= 0.0f) { result = 1.0f; } - return result*(1.0f+ k_displayTopMarginRatio); + return result * (1.0f + k_displayTopMarginRatio); } float ExponentialLaw::evaluateAtAbscissa(float x) const { if (x < 0.0f) { return NAN; } - return m_parameter1*std::exp(-m_parameter1*x); + return m_parameter1 * std::exp(-m_parameter1 * x); } bool ExponentialLaw::authorizedValueAtIndex(float x, int index) const { @@ -77,7 +47,7 @@ bool ExponentialLaw::authorizedValueAtIndex(float x, int index) const { } double ExponentialLaw::cumulativeDistributiveFunctionAtAbscissa(double x) const { - return 1.0 - std::exp((double)(-m_parameter1*x)); + return 1.0 - std::exp((double)(-m_parameter1 * x)); } double ExponentialLaw::cumulativeDistributiveInverseForProbability(double * probability) { diff --git a/apps/probability/law/exponential_law.h b/apps/probability/law/exponential_law.h index e9a6e206a..688070a71 100644 --- a/apps/probability/law/exponential_law.h +++ b/apps/probability/law/exponential_law.h @@ -2,21 +2,28 @@ #define PROBABILITE_EXPONENTIAL_LAW_H #include "one_parameter_law.h" +#include namespace Probability { -class ExponentialLaw : public OneParameterLaw { +class ExponentialLaw final : public OneParameterLaw { public: - ExponentialLaw(); - I18n::Message title() override; - Type type() const override; - bool isContinuous() const override; + ExponentialLaw() : OneParameterLaw(1.0f) {} + I18n::Message title() override { return I18n::Message::ExponentialLaw; } + Type type() const override { return Type::Exponential; } + bool isContinuous() const override { return true; } float xMin() override; float yMin() override; float xMax() override; float yMax() override; - I18n::Message parameterNameAtIndex(int index) override; - I18n::Message parameterDefinitionAtIndex(int index) override; + I18n::Message parameterNameAtIndex(int index) override { + assert(index == 0); + return I18n::Message::Lambda; + } + I18n::Message parameterDefinitionAtIndex(int index) override { + assert(index == 0); + return I18n::Message::LambdaExponentialDefinition; + } float evaluateAtAbscissa(float x) const override; bool authorizedValueAtIndex(float x, int index) const override; double cumulativeDistributiveFunctionAtAbscissa(double x) const override; diff --git a/apps/probability/law/law.cpp b/apps/probability/law/law.cpp index 7e20b3b46..241e2ae62 100644 --- a/apps/probability/law/law.cpp +++ b/apps/probability/law/law.cpp @@ -4,11 +4,6 @@ namespace Probability { -Law::Law() : - Shared::CurveViewRange() -{ -} - float Law::xGridUnit() { return computeGridUnit(Axis::X, xMax() - xMin()); } diff --git a/apps/probability/law/law.h b/apps/probability/law/law.h index d67d47895..61df4526f 100644 --- a/apps/probability/law/law.h +++ b/apps/probability/law/law.h @@ -10,7 +10,7 @@ namespace Probability { class Law : public Shared::CurveViewRange { public: - Law(); + Law() : Shared::CurveViewRange() {} enum class Type : uint8_t{ Binomial, Uniform, diff --git a/apps/probability/law/one_parameter_law.cpp b/apps/probability/law/one_parameter_law.cpp deleted file mode 100644 index 617c60af1..000000000 --- a/apps/probability/law/one_parameter_law.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "one_parameter_law.h" -#include - -namespace Probability { - -OneParameterLaw::OneParameterLaw(float parameterValue) : - m_parameter1(parameterValue) -{ -} - -int OneParameterLaw::numberOfParameter() { - return 1; -} - -float OneParameterLaw::parameterValueAtIndex(int index) { - assert(index == 0); - return m_parameter1; -} - -void OneParameterLaw::setParameterAtIndex(float f, int index) { - assert(index == 0); - m_parameter1 = f; -} - -} diff --git a/apps/probability/law/one_parameter_law.h b/apps/probability/law/one_parameter_law.h index 695a1795c..ea45abc58 100644 --- a/apps/probability/law/one_parameter_law.h +++ b/apps/probability/law/one_parameter_law.h @@ -2,15 +2,22 @@ #define PROBABILITE_ONE_PARAMETER_LAW_H #include "law.h" +#include namespace Probability { class OneParameterLaw : public Law { public: - OneParameterLaw(float parameterValue); - int numberOfParameter() override; - float parameterValueAtIndex(int index) override; - void setParameterAtIndex(float f, int index) override; + OneParameterLaw(float parameterValue) : m_parameter1(parameterValue) {} + int numberOfParameter() override { return 1; } + float parameterValueAtIndex(int index) override { + assert(index == 0); + return m_parameter1; + } + void setParameterAtIndex(float f, int index) override { + assert(index == 0); + m_parameter1 = f; + } protected: float m_parameter1; }; diff --git a/apps/probability/law/poisson_law.cpp b/apps/probability/law/poisson_law.cpp index 4cafce3e4..02e801f76 100644 --- a/apps/probability/law/poisson_law.cpp +++ b/apps/probability/law/poisson_law.cpp @@ -5,46 +5,19 @@ namespace Probability { -PoissonLaw::PoissonLaw() : - OneParameterLaw(4.0f) -{ -} - -I18n::Message PoissonLaw::title() { - return I18n::Message::PoissonLaw; -} - -Law::Type PoissonLaw::type() const { - return Type::Poisson; -} - -bool PoissonLaw::isContinuous() const { - return false; -} - -I18n::Message PoissonLaw::parameterNameAtIndex(int index) { - assert(index == 0); - return I18n::Message::Lambda; -} - -I18n::Message PoissonLaw::parameterDefinitionAtIndex(int index) { - assert(index == 0); - return I18n::Message::LambdaPoissonDefinition; -} - float PoissonLaw::xMin() { - return -k_displayLeftMarginRatio*xMax(); -} - -float PoissonLaw::xMax() { - assert(m_parameter1 != 0); - return (m_parameter1 + 5.0f*std::sqrt(m_parameter1))*(1.0f+k_displayRightMarginRatio); + return -k_displayLeftMarginRatio * xMax(); } float PoissonLaw::yMin() { return - k_displayBottomMarginRatio * yMax(); } +float PoissonLaw::xMax() { + assert(m_parameter1 != 0); + return (m_parameter1 + 5.0f * std::sqrt(m_parameter1)) * (1.0f + k_displayRightMarginRatio); +} + float PoissonLaw::yMax() { int maxAbscissa = (int)m_parameter1; assert(maxAbscissa >= 0.0f); @@ -52,7 +25,7 @@ float PoissonLaw::yMax() { if (result <= 0.0f) { result = 1.0f; } - return result*(1.0f+ k_displayTopMarginRatio); + return result * (1.0f + k_displayTopMarginRatio); } bool PoissonLaw::authorizedValueAtIndex(float x, int index) const { @@ -67,7 +40,7 @@ T PoissonLaw::templatedApproximateAtAbscissa(T x) const { if (x < 0) { return NAN; } - T lResult = -(T)m_parameter1+std::floor(x)*std::log((T)m_parameter1)-std::lgamma(std::floor(x)+1); + T lResult = -(T)m_parameter1 + std::floor(x) * std::log((T)m_parameter1) - std::lgamma(std::floor(x) + 1); return std::exp(lResult); } diff --git a/apps/probability/law/poisson_law.h b/apps/probability/law/poisson_law.h index 3ae372a1b..6b8708c46 100644 --- a/apps/probability/law/poisson_law.h +++ b/apps/probability/law/poisson_law.h @@ -5,18 +5,24 @@ namespace Probability { -class PoissonLaw : public OneParameterLaw { +class PoissonLaw final : public OneParameterLaw { public: - PoissonLaw(); - I18n::Message title() override; - Type type() const override; - bool isContinuous() const override; + PoissonLaw() : OneParameterLaw(4.0f) {} + I18n::Message title() override { return I18n::Message::PoissonLaw; } + Type type() const override { return Type::Poisson; } + bool isContinuous() const override { return false; } float xMin() override; float yMin() override; float xMax() override; float yMax() override; - I18n::Message parameterNameAtIndex(int index) override; - I18n::Message parameterDefinitionAtIndex(int index) override; + I18n::Message parameterNameAtIndex(int index) override { + assert(index == 0); + return I18n::Message::Lambda; + } + I18n::Message parameterDefinitionAtIndex(int index) override { + assert(index == 0); + return I18n::Message::LambdaPoissonDefinition; + } float evaluateAtAbscissa(float x) const override { return templatedApproximateAtAbscissa(x); } diff --git a/apps/probability/law/two_parameter_law.cpp b/apps/probability/law/two_parameter_law.cpp index bdee5f63f..8e6c7ac18 100644 --- a/apps/probability/law/two_parameter_law.cpp +++ b/apps/probability/law/two_parameter_law.cpp @@ -3,16 +3,6 @@ namespace Probability { -TwoParameterLaw::TwoParameterLaw(float parameterValue1, float parameterValue2) : - m_parameter1(parameterValue1), - m_parameter2(parameterValue2) -{ -} - -int TwoParameterLaw::numberOfParameter() { - return 2; -} - float TwoParameterLaw::parameterValueAtIndex(int index) { assert(index >= 0 && index < 2); if (index == 0) { diff --git a/apps/probability/law/two_parameter_law.h b/apps/probability/law/two_parameter_law.h index bcfa62c8c..1e1d1fcb3 100644 --- a/apps/probability/law/two_parameter_law.h +++ b/apps/probability/law/two_parameter_law.h @@ -7,8 +7,11 @@ namespace Probability { class TwoParameterLaw : public Law { public: - TwoParameterLaw(float parameterValue1, float parameterValue2); - int numberOfParameter() override; + TwoParameterLaw(float parameterValue1, float parameterValue2) : + m_parameter1(parameterValue1), + m_parameter2(parameterValue2) + {} + int numberOfParameter() override { return 2; } float parameterValueAtIndex(int index) override; void setParameterAtIndex(float f, int index) override; protected: diff --git a/apps/probability/law/uniform_law.cpp b/apps/probability/law/uniform_law.cpp index 9dc323f4a..8a0e072c1 100644 --- a/apps/probability/law/uniform_law.cpp +++ b/apps/probability/law/uniform_law.cpp @@ -5,22 +5,6 @@ namespace Probability { -UniformLaw::UniformLaw() : - TwoParameterLaw(-1.0f, 1.0f) -{ -} - -I18n::Message UniformLaw::title() { - return I18n::Message::UniformLaw; -} - -Law::Type UniformLaw::type() const { - return Type::Uniform; -} - -bool UniformLaw::isContinuous() const { - return true; -} I18n::Message UniformLaw::parameterNameAtIndex(int index) { assert(index >= 0 && index < 2); @@ -45,18 +29,18 @@ float UniformLaw::xMin() { if (m_parameter2 - m_parameter1 < FLT_EPSILON) { return m_parameter1 - 1.0f; } - return m_parameter1 - 0.6f*(m_parameter2 - m_parameter1); + return m_parameter1 - 0.6f * (m_parameter2 - m_parameter1); +} + +float UniformLaw::yMin() { + return -k_displayBottomMarginRatio * yMax(); } float UniformLaw::xMax() { if (m_parameter2 - m_parameter1 < FLT_EPSILON) { return m_parameter1 + 1.0f; } - return m_parameter2 + 0.6f*(m_parameter2 - m_parameter1); -} - -float UniformLaw::yMin() { - return -k_displayBottomMarginRatio*yMax(); + return m_parameter2 + 0.6f * (m_parameter2 - m_parameter1); } float UniformLaw::yMax() { @@ -64,18 +48,18 @@ float UniformLaw::yMax() { if (result <= 0.0f || std::isnan(result) || std::isinf(result)) { result = 1.0f; } - return result*(1.0f+ k_displayTopMarginRatio); + return result * (1.0f+ k_displayTopMarginRatio); } float UniformLaw::evaluateAtAbscissa(float t) const { if (m_parameter2 - m_parameter1 < FLT_EPSILON) { if (m_parameter1 - k_diracWidth<= t && t <= m_parameter2 + k_diracWidth) { - return 2.0f*k_diracMaximum; + return 2.0f * k_diracMaximum; } return 0.0f; } if (m_parameter1 <= t && t <= m_parameter2) { - return (1.0f/(m_parameter2-m_parameter1)); + return (1.0f/(m_parameter2 - m_parameter1)); } return 0.0f; } @@ -93,7 +77,7 @@ bool UniformLaw::authorizedValueAtIndex(float x, int index) const { void UniformLaw::setParameterAtIndex(float f, int index) { TwoParameterLaw::setParameterAtIndex(f, index); if (index == 0 && m_parameter2 < m_parameter1) { - m_parameter2 = m_parameter1+1.0f; + m_parameter2 = m_parameter1 + 1.0f; } } @@ -102,7 +86,7 @@ double UniformLaw::cumulativeDistributiveFunctionAtAbscissa(double x) const { return 0.0; } if (x < m_parameter2) { - return (x-m_parameter1)/(m_parameter2-m_parameter1); + return (x - m_parameter1)/(m_parameter2 - m_parameter1); } return 1.0; } @@ -114,7 +98,7 @@ double UniformLaw::cumulativeDistributiveInverseForProbability(double * probabil if (*probability <= 0.0f) { return m_parameter1; } - return m_parameter1*(1-*probability)+*probability*m_parameter2; + return m_parameter1 * (1 - *probability) + *probability * m_parameter2; } } diff --git a/apps/probability/law/uniform_law.h b/apps/probability/law/uniform_law.h index 7d095fa8a..fc10786e4 100644 --- a/apps/probability/law/uniform_law.h +++ b/apps/probability/law/uniform_law.h @@ -5,12 +5,12 @@ namespace Probability { -class UniformLaw : public TwoParameterLaw { +class UniformLaw final : public TwoParameterLaw { public: - UniformLaw(); - I18n::Message title() override; - Type type() const override; - bool isContinuous() const override; + UniformLaw() : TwoParameterLaw(-1.0f, 1.0f) {} + I18n::Message title() override { return I18n::Message::UniformLaw; } + Type type() const override { return Type::Uniform; } + bool isContinuous() const override { return true; } float xMin() override; float yMin() override; float xMax() override; From 1b0b9a5c420e600f9dfe83d4a5c5a7a1b22cc8ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 28 Dec 2018 16:50:41 +0100 Subject: [PATCH 172/373] [apps/probability] Color the background behind graph labels --- apps/probability/law_curve_view.cpp | 6 ++++-- apps/probability/law_curve_view.h | 1 + apps/shared/curve_view.cpp | 4 ++-- apps/shared/curve_view.h | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/apps/probability/law_curve_view.cpp b/apps/probability/law_curve_view.cpp index 19a4f63ad..6e672dc55 100644 --- a/apps/probability/law_curve_view.cpp +++ b/apps/probability/law_curve_view.cpp @@ -6,6 +6,8 @@ using namespace Shared; namespace Probability { +constexpr KDColor LawCurveView::k_backgroundColor; + void LawCurveView::reload() { CurveView::reload(); markRectAsDirty(bounds()); @@ -14,9 +16,9 @@ void LawCurveView::reload() { void LawCurveView::drawRect(KDContext * ctx, KDRect rect) const { float lowerBound = m_calculation->lowerBound(); float upperBound = m_calculation->upperBound(); - ctx->fillRect(bounds(), Palette::WallScreen); + ctx->fillRect(bounds(), k_backgroundColor); drawAxes(ctx, rect, Axis::Horizontal); - drawLabels(ctx, rect, Axis::Horizontal, false); + drawLabels(ctx, rect, Axis::Horizontal, false, false, false, 0, k_backgroundColor); if (m_law->type() == Law::Type::Normal) { // Special case for the normal law, which has always the same curve float pixelColorLowerBound = std::round(floatToPixel(Axis::Horizontal, lowerBound)); diff --git a/apps/probability/law_curve_view.h b/apps/probability/law_curve_view.h index bf1dc1354..2f142aa75 100644 --- a/apps/probability/law_curve_view.h +++ b/apps/probability/law_curve_view.h @@ -28,6 +28,7 @@ protected: char * label(Axis axis, int index) const override; private: static float EvaluateAtAbscissa(float abscissa, void * model, void * context); + static constexpr KDColor k_backgroundColor = Palette::WallScreen; void drawStandardNormal(KDContext * ctx, KDRect rect, float colorLowerBound, float colorUpperBound) const; char m_labels[k_maxNumberOfXLabels][k_labelBufferMaxSize]; Law * m_law; diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index 21669193c..9a806744d 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -185,7 +185,7 @@ enum class FloatingPosition : uint8_t { Max }; -void CurveView::drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOrigin, bool graduationOnly, bool fixCoordinate, KDCoordinate fixedCoordinate) const { +void CurveView::drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOrigin, bool graduationOnly, bool fixCoordinate, KDCoordinate fixedCoordinate, KDColor backgroundColor) const { int numberLabels = numberOfLabels(axis); if (numberLabels <= 1) { return; @@ -276,7 +276,7 @@ void CurveView::drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOr } KDPoint origin = KDPoint(xPosition, yPosition); if (rect.intersects(KDRect(origin, textSize))) { - ctx->drawString(labelI, origin, k_font, KDColorBlack); + ctx->drawString(labelI, origin, k_font, KDColorBlack, backgroundColor); } } } diff --git a/apps/shared/curve_view.h b/apps/shared/curve_view.h index a53aedd53..4f28eb480 100644 --- a/apps/shared/curve_view.h +++ b/apps/shared/curve_view.h @@ -66,7 +66,7 @@ protected: void drawHistogram(KDContext * ctx, KDRect rect, EvaluateModelWithParameter evaluation, void * model, void * context, float firstBarAbscissa, float barWidth, bool fillBar, KDColor defaultColor, KDColor highlightColor, float highlightLowerBound = INFINITY, float highlightUpperBound = -INFINITY) const; void computeLabels(Axis axis); - void drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOrigin, bool graduationOnly = false, bool fixCoordinate = false, KDCoordinate fixedCoordinate = 0) const; + void drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOrigin, bool graduationOnly = false, bool fixCoordinate = false, KDCoordinate fixedCoordinate = 0, KDColor backgroundColor = KDColorWhite) const; View * m_bannerView; CurveViewCursor * m_curveViewCursor; private: From ad8f0a73d91ccad5e4680ebcc443ee6ea5b782d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 28 Dec 2018 15:51:26 +0100 Subject: [PATCH 173/373] [poincare] Fix Addition::shallowBeautify B+A should be beautified in A+B 1+x should be beautified in x+1 --- poincare/include/poincare/decimal.h | 2 +- poincare/include/poincare/expression_node.h | 6 +++--- poincare/include/poincare/float.h | 2 +- poincare/include/poincare/n_ary_expression_node.h | 4 ++-- poincare/include/poincare/power.h | 4 ++-- poincare/include/poincare/rational.h | 2 +- poincare/include/poincare/symbol_abstract.h | 2 +- poincare/src/addition.cpp | 4 ++-- poincare/src/decimal.cpp | 5 ++++- poincare/src/expression.cpp | 2 +- poincare/src/expression_node.cpp | 14 +++++++------- poincare/src/float.cpp | 5 ++++- poincare/src/multiplication.cpp | 10 +++++----- poincare/src/n_ary_expression_node.cpp | 12 ++++++------ poincare/src/power.cpp | 12 ++++++------ poincare/src/rational.cpp | 5 ++++- poincare/src/symbol_abstract.cpp | 2 +- 17 files changed, 51 insertions(+), 42 deletions(-) diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index e78118224..267430441 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -59,7 +59,7 @@ public: } // Comparison - int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override; + int simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const override; // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index b5a8581dd..4d9cc0a95 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -140,15 +140,15 @@ public: * together (ie Pi, 2*Pi). * Because SimplificationOrder is a recursive call, we sometimes enable its * interruption to avoid freezing in the simplification process. */ - static int SimplificationOrder(const ExpressionNode * e1, const ExpressionNode * e2, bool canBeInterrupted = false); + static int SimplificationOrder(const ExpressionNode * e1, const ExpressionNode * e2, bool ascending, bool canBeInterrupted = false); /* In the simplification order, most expressions are compared by only * comparing their types. However hierarchical expressions of same type would * compare their operands and thus need to reimplement * simplificationOrderSameType. Besides, operations that can be simplified * (ie +, *, ^, !) have specific rules to group like terms together and thus * reimplement simplificationOrderGreaterType. */ - virtual int simplificationOrderGreaterType(const ExpressionNode * e, bool canBeInterrupted) const { return -1; } - virtual int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const; + virtual int simplificationOrderGreaterType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const { return ascending ? -1 : 1; } + virtual int simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const; /* Layout Helper */ virtual Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const = 0; diff --git a/poincare/include/poincare/float.h b/poincare/include/poincare/float.h index 0f488f094..059a70e01 100644 --- a/poincare/include/poincare/float.h +++ b/poincare/include/poincare/float.h @@ -41,7 +41,7 @@ public: Type type() const override { return Type::Float; } Sign sign(Context * context) const override { return m_value < 0 ? Sign::Negative : Sign::Positive; } Expression setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; - int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override; + int simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const override; // Layout int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/n_ary_expression_node.h b/poincare/include/poincare/n_ary_expression_node.h index 09e9dc879..b86dbf5eb 100644 --- a/poincare/include/poincare/n_ary_expression_node.h +++ b/poincare/include/poincare/n_ary_expression_node.h @@ -33,8 +33,8 @@ protected: * than 6144 children which fit in uint16_t. */ uint16_t m_numberOfChildren; private: - int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override; - int simplificationOrderGreaterType(const ExpressionNode * e, bool canBeInterrupted) const override; + int simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const override; + int simplificationOrderGreaterType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const override; }; class NAryExpression : public Expression { diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index f99c1b530..6ae251a7c 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -47,8 +47,8 @@ private: // Simplify Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) override; - int simplificationOrderGreaterType(const ExpressionNode * e, bool canBeInterrupted) const override; - int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override; + int simplificationOrderGreaterType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const override; + int simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const override; Expression denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override; // Evaluation template static MatrixComplex computeOnComplexAndMatrix(const std::complex c, const MatrixComplex n); diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index 6293dc28a..4998873ab 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -56,7 +56,7 @@ public: static int NaturalOrder(const RationalNode * i, const RationalNode * j); private: - int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override; + int simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const override; Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) override; Expression setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; diff --git a/poincare/include/poincare/symbol_abstract.h b/poincare/include/poincare/symbol_abstract.h index cab0fc9d3..3de47c6c5 100644 --- a/poincare/include/poincare/symbol_abstract.h +++ b/poincare/include/poincare/symbol_abstract.h @@ -32,7 +32,7 @@ public: void initToMatchSize(size_t goalSize) override; // ExpressionNode - int simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const override; + int simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const override; // Property Sign sign(Context * context) const override; diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 26c48a371..abaf601bf 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -102,7 +102,7 @@ Expression Addition::shallowBeautify(Context & context, Preferences::ComplexForm /* Sort children in decreasing order: * 1+x+x^2 --> x^2+x+1 * 1+R(2) --> R(2)+1 */ - sortChildrenInPlace([](const ExpressionNode * e1, const ExpressionNode * e2, bool canBeInterrupted) { return ExpressionNode::SimplificationOrder(e2, e1, canBeInterrupted); }, true); + sortChildrenInPlace([](const ExpressionNode * e1, const ExpressionNode * e2, bool canBeInterrupted) { return ExpressionNode::SimplificationOrder(e1, e2, false, canBeInterrupted); }, true); for (int i = 0; i < numberOfChildren(); i++) { // Try to make the child i positive if any negative numeral factor is found @@ -156,7 +156,7 @@ Expression Addition::shallowReduce(Context & context, Preferences::ComplexFormat } // Step 2: Sort the children - sortChildrenInPlace(ExpressionNode::SimplificationOrder, true); + sortChildrenInPlace([](const ExpressionNode * e1, const ExpressionNode * e2, bool canBeInterrupted) { return ExpressionNode::SimplificationOrder(e1, e2, true, canBeInterrupted); }, true); #if MATRIX_EXACT_REDUCING #if 0 diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index 5203266c8..8aa6cc094 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -60,7 +60,10 @@ Expression DecimalNode::setSign(Sign s, Context * context, Preferences::ComplexF return Decimal(this).setSign(s); } -int DecimalNode::simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const { +int DecimalNode::simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const { + if (!ascending) { + return e->simplificationOrderSameType(this, true, canBeInterrupted); + } assert(e->type() == Type::Decimal); const DecimalNode * other = static_cast(e); if (m_negative && !other->m_negative) { diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 96dd82867..8838f023f 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -352,7 +352,7 @@ Preferences::ComplexFormat Expression::UpdatedComplexFormatWithExpressionInput(P bool Expression::isIdenticalTo(const Expression e) const { /* We use the simplification order only because it is a already-coded total * order on expresssions. */ - return ExpressionNode::SimplificationOrder(node(), e.node(), true) == 0; + return ExpressionNode::SimplificationOrder(node(), e.node(), true, true) == 0; } bool Expression::isEqualToItsApproximationLayout(Expression approximation, char * buffer, int bufferSize, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits, Context & context) { diff --git a/poincare/src/expression_node.cpp b/poincare/src/expression_node.cpp index df89e10c7..73e7c3417 100644 --- a/poincare/src/expression_node.cpp +++ b/poincare/src/expression_node.cpp @@ -72,30 +72,30 @@ float ExpressionNode::characteristicXRange(Context & context, Preferences::Angle return range; } -int ExpressionNode::SimplificationOrder(const ExpressionNode * e1, const ExpressionNode * e2, bool canBeInterrupted) { +int ExpressionNode::SimplificationOrder(const ExpressionNode * e1, const ExpressionNode * e2, bool ascending, bool canBeInterrupted) { if (e1->type() > e2->type()) { if (canBeInterrupted && Expression::shouldStopProcessing()) { return 1; } - return -(e2->simplificationOrderGreaterType(e1, canBeInterrupted)); + return -(e2->simplificationOrderGreaterType(e1, ascending, canBeInterrupted)); } else if (e1->type() == e2->type()) { - return e1->simplificationOrderSameType(e2, canBeInterrupted); + return e1->simplificationOrderSameType(e2, ascending, canBeInterrupted); } else { if (canBeInterrupted && Expression::shouldStopProcessing()) { return -1; } - return e1->simplificationOrderGreaterType(e2, canBeInterrupted); + return e1->simplificationOrderGreaterType(e2, ascending, canBeInterrupted); } } -int ExpressionNode::simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const { +int ExpressionNode::simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const { int index = 0; for (ExpressionNode * c : children()) { // The NULL node is the least node type. if (e->numberOfChildren() <= index) { return 1; } - int childIOrder = SimplificationOrder(c, e->childAtIndex(index), canBeInterrupted); + int childIOrder = SimplificationOrder(c, e->childAtIndex(index), ascending, canBeInterrupted); if (childIOrder != 0) { return childIOrder; } @@ -103,7 +103,7 @@ int ExpressionNode::simplificationOrderSameType(const ExpressionNode * e, bool c } // The NULL node is the least node type. if (e->numberOfChildren() > numberOfChildren()) { - return -1; + return ascending ? -1 : 1; } return 0; } diff --git a/poincare/src/float.cpp b/poincare/src/float.cpp index 8fb98d2e1..95720f70d 100644 --- a/poincare/src/float.cpp +++ b/poincare/src/float.cpp @@ -14,7 +14,10 @@ Expression FloatNode::setSign(Sign s, Context * context, Preferences::Complex } template -int FloatNode::simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const { +int FloatNode::simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const { + if (!ascending) { + return e->simplificationOrderSameType(this, true, canBeInterrupted); + } assert(e->type() == ExpressionNode::Type::Float); const FloatNode * other = static_cast *>(e); if (value() < other->value()) { diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 08eb0028b..e2c13a4a7 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -268,7 +268,7 @@ Expression Multiplication::privateShallowReduce(Context & context, Preferences:: mergeMultiplicationChildrenInPlace(); // Step 2: Sort the children - sortChildrenInPlace(ExpressionNode::SimplificationOrder, canBeInterrupted); + sortChildrenInPlace([](const ExpressionNode * e1, const ExpressionNode * e2, bool canBeInterrupted) { return ExpressionNode::SimplificationOrder(e1, e2, true, canBeInterrupted); }, true); #if MATRIX_EXACT_REDUCING #if 0 // OLD CODE @@ -396,7 +396,7 @@ Expression Multiplication::privateShallowReduce(Context & context, Preferences:: /* Replacing sin/cos by tan factors may have mixed factors and factors are * guaranteed to be sorted (according ot SimplificationOrder) at the end of * shallowReduce */ - sortChildrenInPlace(ExpressionNode::SimplificationOrder, canBeInterrupted); + sortChildrenInPlace([](const ExpressionNode * e1, const ExpressionNode * e2, bool canBeInterrupted) { return ExpressionNode::SimplificationOrder(e1, e2, true, canBeInterrupted); }, true); } /* Step 5: We remove rational children that appeared in the middle of sorted @@ -641,7 +641,7 @@ void Multiplication::addMissingFactors(Expression factor, Context & context, Pre } } addChildAtIndexInPlace(factor.clone(), 0, numberOfChildren()); - sortChildrenInPlace(ExpressionNode::SimplificationOrder, false); + sortChildrenInPlace([](const ExpressionNode * e1, const ExpressionNode * e2, bool canBeInterrupted) { return ExpressionNode::SimplificationOrder(e1, e2, true, canBeInterrupted); }, true); } void Multiplication::factorizeSineAndCosine(int i, int j, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { @@ -767,10 +767,10 @@ Expression Multiplication::mergeNegativePower(Context & context, Preferences::Co if (m.numberOfChildren() == 0) { return *this; } - m.sortChildrenInPlace(ExpressionNode::SimplificationOrder, true); + m.sortChildrenInPlace([](const ExpressionNode * e1, const ExpressionNode * e2, bool canBeInterrupted) { return ExpressionNode::SimplificationOrder(e1, e2, true, canBeInterrupted); }, true); Power p(m.squashUnaryHierarchyInPlace(), Rational(-1)); addChildAtIndexInPlace(p, 0, numberOfChildren()); - sortChildrenInPlace(ExpressionNode::SimplificationOrder, true); + sortChildrenInPlace([](const ExpressionNode * e1, const ExpressionNode * e2, bool canBeInterrupted) { return ExpressionNode::SimplificationOrder(e1, e2, true, canBeInterrupted); }, true); return squashUnaryHierarchyInPlace(); } diff --git a/poincare/src/n_ary_expression_node.cpp b/poincare/src/n_ary_expression_node.cpp index 6606a9650..2b6ffd44e 100644 --- a/poincare/src/n_ary_expression_node.cpp +++ b/poincare/src/n_ary_expression_node.cpp @@ -44,7 +44,7 @@ Expression NAryExpressionNode::squashUnaryHierarchyInPlace() { // Private -int NAryExpressionNode::simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const { +int NAryExpressionNode::simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const { int m = numberOfChildren(); int n = e->numberOfChildren(); for (int i = 1; i <= m; i++) { @@ -52,30 +52,30 @@ int NAryExpressionNode::simplificationOrderSameType(const ExpressionNode * e, bo if (n < i) { return 1; } - int order = SimplificationOrder(childAtIndex(m-i), e->childAtIndex(n-i), canBeInterrupted); + int order = SimplificationOrder(childAtIndex(m-i), e->childAtIndex(n-i), ascending, canBeInterrupted); if (order != 0) { return order; } } // The NULL node is the least node type. if (n > m) { - return -1; + return ascending ? -1 : 1; } return 0; } -int NAryExpressionNode::simplificationOrderGreaterType(const ExpressionNode * e, bool canBeInterrupted) const { +int NAryExpressionNode::simplificationOrderGreaterType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const { int m = numberOfChildren(); if (m == 0) { return -1; } /* Compare e to last term of hierarchy. */ - int order = SimplificationOrder(childAtIndex(m-1), e, canBeInterrupted); + int order = SimplificationOrder(childAtIndex(m-1), e, ascending, canBeInterrupted); if (order != 0) { return order; } if (m > 1) { - return 1; + return ascending ? 1 : -1; } return 0; } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index b1e8b4394..b49ca6f36 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -173,23 +173,23 @@ Expression PowerNode::shallowBeautify(Context & context, Preferences::ComplexFor return Power(this).shallowBeautify(context, complexFormat, angleUnit); } -int PowerNode::simplificationOrderGreaterType(const ExpressionNode * e, bool canBeInterrupted) const { - int baseComparison = SimplificationOrder(childAtIndex(0), e, canBeInterrupted); +int PowerNode::simplificationOrderGreaterType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const { + int baseComparison = SimplificationOrder(childAtIndex(0), e, ascending, canBeInterrupted); if (baseComparison != 0) { return baseComparison; } Rational one(1); - return SimplificationOrder(childAtIndex(1), one.node(), canBeInterrupted); + return SimplificationOrder(childAtIndex(1), one.node(), ascending, canBeInterrupted); } -int PowerNode::simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const { +int PowerNode::simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const { assert(e->numberOfChildren() > 0); - int baseComparison = SimplificationOrder(childAtIndex(0), e->childAtIndex(0), canBeInterrupted); + int baseComparison = SimplificationOrder(childAtIndex(0), e->childAtIndex(0), ascending, canBeInterrupted); if (baseComparison != 0) { return baseComparison; } assert(e->numberOfChildren() > 1); - return SimplificationOrder(childAtIndex(1), e->childAtIndex(1), canBeInterrupted); + return SimplificationOrder(childAtIndex(1), e->childAtIndex(1), ascending, canBeInterrupted); } Expression PowerNode::denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index 9df0d44c4..78c591320 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -135,7 +135,10 @@ int RationalNode::NaturalOrder(const RationalNode * i, const RationalNode * j) { return Integer::NaturalOrder(i1, i2); } -int RationalNode::simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const { +int RationalNode::simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const { + if (!ascending) { + return e->simplificationOrderSameType(this, true, canBeInterrupted); + } assert(e->type() == ExpressionNode::Type::Rational); const RationalNode * other = static_cast(e); return NaturalOrder(this, other); diff --git a/poincare/src/symbol_abstract.cpp b/poincare/src/symbol_abstract.cpp index 2fd65125b..188a1cd05 100644 --- a/poincare/src/symbol_abstract.cpp +++ b/poincare/src/symbol_abstract.cpp @@ -45,7 +45,7 @@ Expression SymbolAbstractNode::setSign(ExpressionNode::Sign s, Context * context return e.setSign(s, context, complexFormat, angleUnit, target); } -int SymbolAbstractNode::simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const { +int SymbolAbstractNode::simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const { assert(type() == e->type()); return strcmp(name(), static_cast(e)->name()); } From 97b13bae5d03e479312515ff36020925872f2f47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 28 Dec 2018 15:52:40 +0100 Subject: [PATCH 174/373] [poincare] Fix SimplificationOrder: Sorting cos(2)*pi should return pi*cos(2) Sorting pi+cos(2) should return cos(2)+pi --- poincare/include/poincare/expression_node.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index 4d9cc0a95..9544f1a3e 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -37,6 +37,8 @@ public: Addition, Factorial, Division, + Constant, + Symbol, Store, Equal, Sine, @@ -85,8 +87,6 @@ public: SquareRoot, Subtraction, Sum, - Symbol, - Constant, ComplexCartesian, From 65527f22b2b85e501537345d4edfa19b0e49c0f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 28 Dec 2018 17:09:30 +0100 Subject: [PATCH 175/373] [poincare] Remove duplicate calls to SetEncounterComplex --- poincare/include/poincare/unreal.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/poincare/include/poincare/unreal.h b/poincare/include/poincare/unreal.h index f09afa9ec..a7b967c03 100644 --- a/poincare/include/poincare/unreal.h +++ b/poincare/include/poincare/unreal.h @@ -21,11 +21,9 @@ public: // Approximation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - Expression::SetEncounterComplex(true); return templatedApproximate(); } Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - Expression::SetEncounterComplex(true); return templatedApproximate(); } From 83bb2f1221533a898d38a4ead851fc9e77ae1ca6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 28 Dec 2018 17:10:32 +0100 Subject: [PATCH 176/373] [poincare] Fix Expression::CreateComplexExpression: should not check the sApproximationEncounteredComplex here as this method is also used int the reduction routine --- poincare/include/poincare/expression.h | 3 ++- poincare/include/poincare/unreal.h | 2 +- poincare/src/complex.cpp | 6 +++++- poincare/src/expression.cpp | 10 ++++++---- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 9db6f5428..5cfde6871 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -167,7 +167,8 @@ public: Expression defaultReplaceUnknown(const Symbol & symbol); /* Complex */ - static void SetEncounterComplex(bool encounterComplex); + static bool EncounteredComplex(); + static void SetEncounteredComplex(bool encounterComplex); static Preferences::ComplexFormat UpdatedComplexFormatWithTextInput(Preferences::ComplexFormat complexFormat, const char * textInput); static Preferences::ComplexFormat UpdatedComplexFormatWithExpressionInput(Preferences::ComplexFormat complexFormat, const Expression & e, Context & context); bool isReal(Context & context) const { return node()->isReal(context); } diff --git a/poincare/include/poincare/unreal.h b/poincare/include/poincare/unreal.h index a7b967c03..d004f8bc2 100644 --- a/poincare/include/poincare/unreal.h +++ b/poincare/include/poincare/unreal.h @@ -32,7 +32,7 @@ public: int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = 0) const override; private: template Evaluation templatedApproximate() const { - Expression::SetEncounterComplex(true); + Expression::SetEncounteredComplex(true); return UndefinedNode::templatedApproximate(); } }; diff --git a/poincare/src/complex.cpp b/poincare/src/complex.cpp index b0b9f54b1..5935fddce 100644 --- a/poincare/src/complex.cpp +++ b/poincare/src/complex.cpp @@ -15,6 +15,7 @@ extern "C" { #include #include #include +#include #include #include @@ -23,7 +24,7 @@ namespace Poincare { template void ComplexNode::setComplex(std::complex c) { if (!std::isnan(c.imag()) && c.imag() != 0.0) { - Expression::SetEncounterComplex(true); + Expression::SetEncounteredComplex(true); } this->real(c.real()); this->imag(c.imag()); @@ -45,6 +46,9 @@ T ComplexNode::toScalar() const { template Expression ComplexNode::complexToExpression(Preferences::ComplexFormat complexFormat) const { + if (complexFormat == Preferences::ComplexFormat::Real && Expression::EncounteredComplex()) { + return Unreal(); + } T ra, tb; if (complexFormat == Preferences::ComplexFormat::Polar) { ra = std::abs(*this); diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 8838f023f..069f51343 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -329,7 +329,11 @@ Expression Expression::defaultReplaceUnknown(const Symbol & symbol) { /* Complex */ -void Expression::SetEncounterComplex(bool encounterComplex) { +bool Expression::EncounteredComplex() { + return sApproximationEncounteredComplex; +} + +void Expression::SetEncounteredComplex(bool encounterComplex) { sApproximationEncounteredComplex = encounterComplex; } @@ -599,9 +603,7 @@ bool Expression::isMinusOne(const Expression e) { } Expression Expression::CreateComplexExpression(Expression ra, Expression tb, Preferences::ComplexFormat complexFormat, bool undefined, bool isZeroRa, bool isOneRa, bool isZeroTb, bool isOneTb, bool isNegativeRa, bool isNegativeTb) { - if (complexFormat == Preferences::ComplexFormat::Real && sApproximationEncounteredComplex) { - return Unreal(); - } else if (undefined) { + if (undefined) { return Undefined(); } switch (complexFormat) { From 284a020de32a60c9409280a17c7c5d318b9698cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 28 Dec 2018 17:11:44 +0100 Subject: [PATCH 177/373] [poincare] Constant: order constant e, i and pi correctly --- poincare/include/poincare/constant.h | 3 +++ poincare/src/constant.cpp | 22 ++++++++++++++++++++++ poincare/src/power.cpp | 10 +++++----- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/poincare/include/poincare/constant.h b/poincare/include/poincare/constant.h index 14e98e29f..1945fe818 100644 --- a/poincare/include/poincare/constant.h +++ b/poincare/include/poincare/constant.h @@ -37,6 +37,9 @@ public: bool isExponential() const { return isConstantChar(Ion::Charset::Exponential); } bool isIComplex() const { return isConstantChar(Ion::Charset::IComplex); } + // Comparison + int simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const override; + // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; private: diff --git a/poincare/src/constant.cpp b/poincare/src/constant.cpp index 1e0964bd9..b6e39cedb 100644 --- a/poincare/src/constant.cpp +++ b/poincare/src/constant.cpp @@ -22,6 +22,28 @@ bool ConstantNode::isReal(Context & context) const { return !isIComplex(); } +int rankOfConstant(char c) { + switch (c) { + case Ion::Charset::IComplex: + return 0; + case Ion::Charset::SmallPi: + return 1; + case Ion::Charset::Exponential: + return 2; + default: + assert(false); + return -1; + } +} + +int ConstantNode::simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const { + if (!ascending) { + return e->simplificationOrderSameType(this, true, canBeInterrupted); + } + assert(type() == e->type()); + return (rankOfConstant(name()[0]) - rankOfConstant(static_cast(e)->name()[0])); +} + Layout ConstantNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { return LayoutHelper::String(m_name, strlen(m_name)); } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index b49ca6f36..d58c6bf2d 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -532,11 +532,11 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co return m1.shallowReduce(context, complexFormat, angleUnit, target); } } - // Step 8: e^(i*Pi*r) with r rational --> cos(pi*r) + i*sin(pi*r) + // Step 8: e^(r*i*Pi) with r rational --> cos(pi*r) + i*sin(pi*r) if (!letPowerAtRoot && isNthRootOfUnity()) { Expression m = childAtIndex(1); - Expression i = m.childAtIndex(m.numberOfChildren()-1); - static_cast(m).removeChildAtIndexInPlace(m.numberOfChildren()-1); + Expression i = m.childAtIndex(m.numberOfChildren()-2); + static_cast(m).removeChildAtIndexInPlace(m.numberOfChildren()-2); if (angleUnit == Preferences::AngleUnit::Degree) { m.replaceChildAtIndexInPlace(m.numberOfChildren()-1, Rational(180)); } @@ -1076,11 +1076,11 @@ bool Power::isNthRootOfUnity() const { if (childAtIndex(1).numberOfChildren() < 2 || childAtIndex(1).numberOfChildren() > 3) { return false; } - const Expression i = childAtIndex(1).childAtIndex(childAtIndex(1).numberOfChildren()-1); + const Expression i = childAtIndex(1).childAtIndex(childAtIndex(1).numberOfChildren()-2); if (i.type() != ExpressionNode::Type::Constant || !static_cast(i).isIComplex()) { return false; } - const Expression pi = childAtIndex(1).childAtIndex(childAtIndex(1).numberOfChildren()-2); + const Expression pi = childAtIndex(1).childAtIndex(childAtIndex(1).numberOfChildren()-1); if (pi.type() != ExpressionNode::Type::Constant || !static_cast(pi).isPi()) { return false; } From 95248edde06a0e399e1e8927949901cdbe96b5f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 28 Dec 2018 17:36:50 +0100 Subject: [PATCH 178/373] [poincare] Fix tests with new beautify order --- apps/calculation/test/calculation_store.cpp | 4 +- apps/solver/test/equation_store.cpp | 6 +- poincare/test/addition.cpp | 30 +++---- poincare/test/complex.cpp | 14 +-- poincare/test/logarithm.cpp | 16 ++-- poincare/test/multiplication.cpp | 6 +- poincare/test/power.cpp | 18 ++-- poincare/test/simplify_mix.cpp | 38 ++++---- poincare/test/store.cpp | 6 +- poincare/test/trigo.cpp | 96 ++++++++++----------- poincare/test/user_variable.cpp | 4 +- 11 files changed, 119 insertions(+), 119 deletions(-) diff --git a/apps/calculation/test/calculation_store.cpp b/apps/calculation/test/calculation_store.cpp index 3ca53e7f8..ab9019fb9 100644 --- a/apps/calculation/test/calculation_store.cpp +++ b/apps/calculation/test/calculation_store.cpp @@ -104,13 +104,13 @@ QUIZ_CASE(calculation_display_exact_approximate) { assertCalculationDisplay("[[1,2,3]]", false, true, ::Calculation::Calculation::EqualSign::Unknown, nullptr, nullptr, &globalContext, &store); assertCalculationDisplay("[[1,x,3]]", false, true, ::Calculation::Calculation::EqualSign::Unknown, nullptr, nullptr, &globalContext, &store); assertCalculationDisplay("28^7", false, false, ::Calculation::Calculation::EqualSign::Unknown, nullptr, nullptr, &globalContext, &store); - assertCalculationDisplay("3+R(2)>a", false, false, ::Calculation::Calculation::EqualSign::Approximation, "3+R(2)", nullptr, &globalContext, &store); + assertCalculationDisplay("3+R(2)>a", false, false, ::Calculation::Calculation::EqualSign::Approximation, "R(2)+3", nullptr, &globalContext, &store); Ion::Storage::sharedStorage()->recordNamed("a.exp").destroy(); assertCalculationDisplay("3+2>a", false, false, ::Calculation::Calculation::EqualSign::Equal, "3+2", "5", &globalContext, &store); Ion::Storage::sharedStorage()->recordNamed("a.exp").destroy(); assertCalculationDisplay("3>a", false, true, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "3", &globalContext, &store); Ion::Storage::sharedStorage()->recordNamed("a.exp").destroy(); - assertCalculationDisplay("3+x>f(x)", true, false, ::Calculation::Calculation::EqualSign::Unknown, "3+x", nullptr, &globalContext, &store); + assertCalculationDisplay("3+x>f(x)", true, false, ::Calculation::Calculation::EqualSign::Unknown, "x+3", nullptr, &globalContext, &store); Ion::Storage::sharedStorage()->recordNamed("f.func").destroy(); } diff --git a/apps/solver/test/equation_store.cpp b/apps/solver/test/equation_store.cpp index 5f6f28597..2c3745d1a 100644 --- a/apps/solver/test/equation_store.cpp +++ b/apps/solver/test/equation_store.cpp @@ -110,7 +110,7 @@ QUIZ_CASE(equation_solve) { // 2*x^2-4*x+4=3 const char * equations9[] = {"2*x^2-4*x+4=3", 0}; - const char * solutions9[] = {"(2-R(2))/(2)","(2+R(2))/(2)", "8"}; + const char * solutions9[] = {"(-R(2)+2)/(2)","(R(2)+2)/(2)", "8"}; assert_equation_system_exact_solve_to(equations9, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions9, 2); // 2*x^2-4*x+2=0 @@ -120,7 +120,7 @@ QUIZ_CASE(equation_solve) { // x^2+x+1=3*x^2+pi*x-R(5) const char * equations11[] = {"x^2+x+1=3*x^2+P*x-R(5)", 0}; - const char * solutions11[] = {"(1-P+R(9+8*R(5)-2*P+P$2#))/(4)", "(1-P-R(9+8*R(5)-2*P+P$2#))/(4)", "9+8*R(5)-2*P+P$2#"}; + const char * solutions11[] = {"(R(P$2#-2*P+8*R(5)+9)-P+1)/(4)", "(-R(P$2#-2*P+8*R(5)+9)-P+1)/(4)", "P$2#-2*P+8*R(5)+9"}; assert_equation_system_exact_solve_to(equations11, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions11, 2); // TODO @@ -144,7 +144,7 @@ QUIZ_CASE(equation_solve) { const char * variablesxyz[] = {"x", "y", "z", ""}; const char * equations14[] = {"x+y=0", "3x+y+z=-5", "4z-P=0", 0}; - const char * solutions14[] = {"(-20-P)/(8)", "(20+P)/(8)", "(P)/(4)"}; + const char * solutions14[] = {"(-P-20)/(8)", "(P+20)/(8)", "(P)/(4)"}; assert_equation_system_exact_solve_to(equations14, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesxyz, solutions14, 3); // Monovariable non-polynomial equation diff --git a/poincare/test/addition.cpp b/poincare/test/addition.cpp index 42c2c4af1..f47829f2f 100644 --- a/poincare/test/addition.cpp +++ b/poincare/test/addition.cpp @@ -61,32 +61,32 @@ QUIZ_CASE(poincare_addition_evaluate) { } QUIZ_CASE(poincare_addition_simplify) { - assert_parsed_expression_simplify_to("1+x", "1+x"); + assert_parsed_expression_simplify_to("1+x", "x+1"); assert_parsed_expression_simplify_to("1/2+1/3+1/4+1/5+1/6+1/7", "223/140"); - assert_parsed_expression_simplify_to("1+x+4-i-2x", "5-i-x"); + assert_parsed_expression_simplify_to("1+x+4-i-2x", "-i-x+5"); assert_parsed_expression_simplify_to("2+1", "3"); assert_parsed_expression_simplify_to("1+2", "3"); assert_parsed_expression_simplify_to("1+2+3+4+5+6+7", "28"); assert_parsed_expression_simplify_to("(0+0)", "0"); - assert_parsed_expression_simplify_to("2+A", "2+A"); - assert_parsed_expression_simplify_to("1+2+3+4+5+A+6+7", "28+A"); - assert_parsed_expression_simplify_to("1+A+2+B+3", "6+A+B"); + assert_parsed_expression_simplify_to("2+A", "A+2"); + assert_parsed_expression_simplify_to("1+2+3+4+5+A+6+7", "A+28"); + assert_parsed_expression_simplify_to("1+A+2+B+3", "A+B+6"); assert_parsed_expression_simplify_to("-2+6", "4"); assert_parsed_expression_simplify_to("-2-6", "-8"); assert_parsed_expression_simplify_to("-A", "-A"); assert_parsed_expression_simplify_to("A-A", "0"); assert_parsed_expression_simplify_to("-5P+3P", "-2*P"); - assert_parsed_expression_simplify_to("1-3+A-5+2A-4A", "-7-A"); + assert_parsed_expression_simplify_to("1-3+A-5+2A-4A", "-A-7"); assert_parsed_expression_simplify_to("A+B-A-B", "0"); assert_parsed_expression_simplify_to("A+B+(-1)*A+(-1)*B", "0"); - assert_parsed_expression_simplify_to("2+13cos(2)-23cos(2)", "2-10*cos(2)"); - assert_parsed_expression_simplify_to("1+1+ln(2)+(5+3*2)/9-4/7+1/98", "(2347+882*ln(2))/882"); - assert_parsed_expression_simplify_to("1+2+0+cos(2)", "3+cos(2)"); + assert_parsed_expression_simplify_to("2+13cos(2)-23cos(2)", "-10*cos(2)+2"); + assert_parsed_expression_simplify_to("1+1+ln(2)+(5+3*2)/9-4/7+1/98", "(882*ln(2)+2347)/882"); + assert_parsed_expression_simplify_to("1+2+0+cos(2)", "cos(2)+3"); assert_parsed_expression_simplify_to("A-A+2cos(2)+B-B-cos(2)", "cos(2)"); - assert_parsed_expression_simplify_to("x+3+P+2*x", "3+3*x+P"); - assert_parsed_expression_simplify_to("1/(x+1)+1/(P+2)", "(3+x+P)/(2+2*x+P+x*P)"); - assert_parsed_expression_simplify_to("1/x^2+1/(x^2*P)", "(1+P)/(x^2*P)"); - assert_parsed_expression_simplify_to("1/x^2+1/(x^3*P)", "(1+x*P)/(x^3*P)"); - assert_parsed_expression_simplify_to("4x/x^2+3P/(x^3*P)", "(3+4*x^2)/x^3"); - assert_parsed_expression_simplify_to("3^(1/2)+2^(-2*3^(1/2)*X^P)/2", "(1+2*2^(2*R(3)*X^P)*R(3))/(2*2^(2*R(3)*X^P))"); + assert_parsed_expression_simplify_to("x+3+P+2*x", "3*x+P+3"); + assert_parsed_expression_simplify_to("1/(x+1)+1/(P+2)", "(x+P+3)/(P*x+2*x+P+2)"); + assert_parsed_expression_simplify_to("1/x^2+1/(x^2*P)", "(P+1)/(P*x^2)"); + assert_parsed_expression_simplify_to("1/x^2+1/(x^3*P)", "(P*x+1)/(P*x^3)"); + assert_parsed_expression_simplify_to("4x/x^2+3P/(x^3*P)", "(4*x^2+3)/x^3"); + assert_parsed_expression_simplify_to("3^(1/2)+2^(-2*3^(1/2)*X^P)/2", "(2*2^(2*R(3)*X^P)*R(3)+1)/(2*2^(2*R(3)*X^P))"); } diff --git a/poincare/test/complex.cpp b/poincare/test/complex.cpp index 3d7e1a06e..81739f1d4 100644 --- a/poincare/test/complex.cpp +++ b/poincare/test/complex.cpp @@ -52,8 +52,8 @@ QUIZ_CASE(poincare_complex_simplify) { assert_parsed_expression_simplify_to("(3+I)/(2+I)", "7/5-1/5*I", Radian, Cartesian); // The simplification of (3+I)^(2+I) in a Cartesian complex form generates to many nodes //assert_parsed_expression_simplify_to("(3+I)^(2+I)", "10*cos((-4*atan(3)+ln(2)+ln(5)+2*P)/2)*X^((2*atan(3)-P)/2)+10*sin((-4*atan(3)+ln(2)+ln(5)+2*P)/2)*X^((2*atan(3)-P)/2)*I", Radian, Cartesian); - assert_parsed_expression_simplify_to("(3+I)^(2+I)", "(3+I)^(2+I)", Radian, Cartesian); - assert_parsed_expression_simplify_to("R(1+6I)", "R(2+2*R(37))/2+R(-2+2*R(37))/2*I", Radian, Cartesian); + assert_parsed_expression_simplify_to("(3+I)^(2+I)", "(I+3)^(I+2)", Radian, Cartesian); + assert_parsed_expression_simplify_to("R(1+6I)", "R(2*R(37)+2)/2+R(2*R(37)-2)/2*I", Radian, Cartesian); assert_parsed_expression_simplify_to("(1+I)^2", "2*I", Radian, Cartesian); assert_parsed_expression_simplify_to("2*I", "2*I", Radian, Cartesian); assert_parsed_expression_simplify_to("I!", "I!", Radian, Cartesian); @@ -101,7 +101,7 @@ QUIZ_CASE(poincare_complex_simplify) { assert_parsed_expression_simplify_to("sign(x)", "sign(x)", Radian, Cartesian); assert_parsed_expression_simplify_to("sin(23)", "sin(23)", Radian, Cartesian); assert_parsed_expression_simplify_to("sin(23+I)", "sin(23+I)", Radian, Cartesian); - assert_parsed_expression_simplify_to("R(1-I)", "R(2+2*R(2))/2-R(-2+2*R(2))/2*I", Radian, Cartesian); + assert_parsed_expression_simplify_to("R(1-I)", "R(2*R(2)+2)/2-R(2*R(2)-2)/2*I", Radian, Cartesian); assert_parsed_expression_simplify_to("tan(23)", "tan(23)", Radian, Cartesian); assert_parsed_expression_simplify_to("tan(23+I)", "tan(23+I)", Radian, Cartesian); @@ -125,7 +125,7 @@ QUIZ_CASE(poincare_complex_simplify) { assert_parsed_expression_simplify_to("3", "3", Radian, Polar); assert_parsed_expression_simplify_to("inf", "inf", Radian, Polar); assert_parsed_expression_simplify_to("1+2+I", "R(10)*X^((-2*atan(3)+P)/2*I)", Radian, Polar); - assert_parsed_expression_simplify_to("1+2+I", "R(10)*X^((90*P-atan(3)*P)/180*I)", Degree, Polar); + assert_parsed_expression_simplify_to("1+2+I", "R(10)*X^((-P*atan(3)+90*P)/180*I)", Degree, Polar); assert_parsed_expression_simplify_to("-(5+2*I)", "R(29)*X^((-2*atan(5/2)-P)/2*I)", Radian, Polar); assert_parsed_expression_simplify_to("(5+2*I)", "R(29)*X^((-2*atan(5/2)+P)/2*I)", Radian, Polar); assert_parsed_expression_simplify_to("I+I", "2*X^(P/2*I)", Radian, Polar); @@ -139,7 +139,7 @@ QUIZ_CASE(poincare_complex_simplify) { //assert_parsed_expression_simplify_to("(3+I)^(2+I)", "10*X^((2*atan(3)-P)/2)*X^((-4*atan(3)+ln(2)+ln(5)+2*P)/2*I)", Radian, Polar); // The simplification of (3+I)^(2+I) in a Polar complex form generates to many nodes //assert_parsed_expression_simplify_to("(3+I)^(2+I)", "10*X^((2*atan(3)-P)/2)*X^((atan(tan((-4*atan(3)+ln(2)+ln(5)+2*P)/2))+P)*I)", Radian, Polar); - assert_parsed_expression_simplify_to("(3+I)^(2+I)", "(3+I)^(2+I)", Radian, Polar); + assert_parsed_expression_simplify_to("(3+I)^(2+I)", "(I+3)^(I+2)", Radian, Polar); assert_parsed_expression_simplify_to("(1+I)^2", "2*X^(P/2*I)", Radian, Polar); assert_parsed_expression_simplify_to("2*I", "2*X^(P/2*I)", Radian, Polar); assert_parsed_expression_simplify_to("3!", "6", Radian, Polar); @@ -153,14 +153,14 @@ QUIZ_CASE(poincare_complex_simplify) { assert_parsed_expression_simplify_to("-2*X^(I*P/2)", "2*X^(-P/2*I)", Radian, Polar); // User defined variable - assert_parsed_expression_simplify_to("a", "R(a^2)*X^((P-sign(a)*P)/2*I)", Radian, Polar); + assert_parsed_expression_simplify_to("a", "R(a^2)*X^((-P*sign(a)+P)/2*I)", Radian, Polar); // a = 2+i assert_simplify("2+I>a"); assert_parsed_expression_simplify_to("a", "R(5)*X^((-2*atan(2)+P)/2*I)", Radian, Polar); // Clean the storage for other tests Ion::Storage::sharedStorage()->recordNamed("a.exp").destroy(); // User defined function - assert_parsed_expression_simplify_to("f(3)", "R(f(3)^2)*X^((P-sign(f(3))*P)/2*I)", Radian, Polar); + assert_parsed_expression_simplify_to("f(3)", "R(f(3)^2)*X^((-P*sign(f(3))+P)/2*I)", Radian, Polar); // f: x -> x+1 assert_simplify("x+1+I>f(x)"); assert_parsed_expression_simplify_to("f(3)", "R(17)*X^((-2*atan(4)+P)/2*I)", Radian, Polar); diff --git a/poincare/test/logarithm.cpp b/poincare/test/logarithm.cpp index 89320e40d..8354a4bec 100644 --- a/poincare/test/logarithm.cpp +++ b/poincare/test/logarithm.cpp @@ -32,10 +32,10 @@ QUIZ_CASE(poincare_logarithm_simplify) { assert_parsed_expression_simplify_to("log(0,0.14+I)", Undefined::Name()); assert_parsed_expression_simplify_to("log(2,1)", Undefined::Name()); assert_parsed_expression_simplify_to("log(x,1)", Undefined::Name()); - assert_parsed_expression_simplify_to("log(12925)", "2*log(5)+log(11)+log(47)"); - assert_parsed_expression_simplify_to("ln(12925)", "2*ln(5)+ln(11)+ln(47)"); - assert_parsed_expression_simplify_to("log(1742279/12925, 6)", "-2*log(5,6)+log(7,6)+3*log(11,6)+log(17,6)-log(47,6)"); - assert_parsed_expression_simplify_to("ln(2/3)", "ln(2)-ln(3)"); + assert_parsed_expression_simplify_to("log(12925)", "log(47)+log(11)+2*log(5)"); + assert_parsed_expression_simplify_to("ln(12925)", "ln(47)+ln(11)+2*ln(5)"); + assert_parsed_expression_simplify_to("log(1742279/12925, 6)", "-log(47,6)+log(17,6)+3*log(11,6)+log(7,6)-2*log(5,6)"); + assert_parsed_expression_simplify_to("ln(2/3)", "-ln(3)+ln(2)"); assert_parsed_expression_simplify_to("log(1742279/12925, -6)", "log(158389/1175,-6)"); assert_parsed_expression_simplify_to("ln(R(2))", "ln(2)/2"); assert_parsed_expression_simplify_to("ln(X^3)", "3"); @@ -46,18 +46,18 @@ QUIZ_CASE(poincare_logarithm_simplify) { assert_parsed_expression_simplify_to("ln(X^(IP/7))", "P/7*I"); assert_parsed_expression_simplify_to("log(10^24)", "24"); assert_parsed_expression_simplify_to("log((23P)^4,23P)", "4"); - assert_parsed_expression_simplify_to("log(10^(2+P))", "2+P"); + assert_parsed_expression_simplify_to("log(10^(2+P))", "P+2"); assert_parsed_expression_simplify_to("ln(1881676377434183981909562699940347954480361860897069)", "ln(1881676377434183981909562699940347954480361860897069)"); /* log(1002101470343) does no reduce to 3*log(10007) because it involves * prime factors above k_biggestPrimeFactor */ assert_parsed_expression_simplify_to("log(1002101470343)", "log(1002101470343)"); assert_parsed_expression_simplify_to("log(64,2)", "6"); assert_parsed_expression_simplify_to("log(2,64)", "log(2,64)"); - assert_parsed_expression_simplify_to("log(1476225,5)", "2+10*log(3,5)"); + assert_parsed_expression_simplify_to("log(1476225,5)", "10*log(3,5)+2"); assert_parsed_expression_simplify_to("log(100)", "2"); assert_parsed_expression_simplify_to("log(1000000)", "6"); - assert_parsed_expression_simplify_to("log(70992768,14)", "5+2*log(2,14)+log(3,14)+log(11,14)"); - assert_parsed_expression_simplify_to("log(1/6991712,14)", "-5-log(13,14)"); + assert_parsed_expression_simplify_to("log(70992768,14)", "log(11,14)+log(3,14)+2*log(2,14)+5"); + assert_parsed_expression_simplify_to("log(1/6991712,14)", "-log(13,14)-5"); assert_parsed_expression_simplify_to("log(4,10)", "2*log(2)"); } diff --git a/poincare/test/multiplication.cpp b/poincare/test/multiplication.cpp index 69c34e72b..a1be66d6e 100644 --- a/poincare/test/multiplication.cpp +++ b/poincare/test/multiplication.cpp @@ -22,7 +22,7 @@ QUIZ_CASE(poincare_multiplication_evaluate) { QUIZ_CASE(poincare_multiplication_simplify) { assert_parsed_expression_simplify_to("0*x+B", "B"); assert_parsed_expression_simplify_to("0*x*0*32*cos(3)", "0"); - assert_parsed_expression_simplify_to("3*A^4*B^x*B^2*(A^2+2)*2*1.2", "(72*A^4*B^(2+x)+36*A^6*B^(2+x))/5"); + assert_parsed_expression_simplify_to("3*A^4*B^x*B^2*(A^2+2)*2*1.2", "(36*A^6*B^(x+2)+72*A^4*B^(x+2))/5"); assert_parsed_expression_simplify_to("A*(B+C)*(D+3)", "3*A*B+3*A*C+A*B*D+A*C*D"); assert_parsed_expression_simplify_to("A/B", "A/B"); assert_parsed_expression_simplify_to("(A*B)^2", "A^2*B^2"); @@ -52,8 +52,8 @@ QUIZ_CASE(poincare_multiplication_simplify) { assert_parsed_expression_simplify_to("A^3*A^(-3)", "1"); assert_parsed_expression_simplify_to("2^P*(1/2)^P", "1"); assert_parsed_expression_simplify_to("A^3*A^(-3)", "1"); - assert_parsed_expression_simplify_to("(x+1)*(x+2)", "2+3*x+x^2"); - assert_parsed_expression_simplify_to("(x+1)*(x-1)", "-1+x^2"); + assert_parsed_expression_simplify_to("(x+1)*(x+2)", "x^2+3*x+2"); + assert_parsed_expression_simplify_to("(x+1)*(x-1)", "x^2-1"); assert_parsed_expression_simplify_to("11P/(22P+11P)", "1/3"); assert_parsed_expression_simplify_to("11/(22P+11P)", "1/(3*P)"); assert_parsed_expression_simplify_to("-11/(22P+11P)", "-1/(3*P)"); diff --git a/poincare/test/power.cpp b/poincare/test/power.cpp index f21693f34..956dcc997 100644 --- a/poincare/test/power.cpp +++ b/poincare/test/power.cpp @@ -67,9 +67,9 @@ QUIZ_CASE(poincare_power_simplify) { assert_parsed_expression_simplify_to("R(P^2)", "P"); assert_parsed_expression_simplify_to("R((-P)^2)", "P"); assert_parsed_expression_simplify_to("R(x*144)", "12*R(x)"); - assert_parsed_expression_simplify_to("R(x*144*P^2)", "12*R(x)*P"); - assert_parsed_expression_simplify_to("R(x*144*P)", "12*R(x)*R(P)"); - assert_parsed_expression_simplify_to("(-1)*(2+(-4*R(2)))", "-2+4*R(2)"); + assert_parsed_expression_simplify_to("R(x*144*P^2)", "12*P*R(x)"); + assert_parsed_expression_simplify_to("R(x*144*P)", "12*R(P)*R(x)"); + assert_parsed_expression_simplify_to("(-1)*(2+(-4*R(2)))", "4*R(2)-2"); assert_parsed_expression_simplify_to("x^(1/2)", "R(x)"); assert_parsed_expression_simplify_to("x^(-1/2)", "1/R(x)"); assert_parsed_expression_simplify_to("x^(1/7)", "root(x,7)"); @@ -81,7 +81,7 @@ QUIZ_CASE(poincare_power_simplify) { assert_parsed_expression_simplify_to("10^log(P)", "P"); assert_parsed_expression_simplify_to("X^ln(65)", "65"); assert_parsed_expression_simplify_to("X^ln(PX)", "P*X"); - assert_parsed_expression_simplify_to("X^log(PX)", "X^(log(P)+log(X))"); + assert_parsed_expression_simplify_to("X^log(PX)", "X^(log(X)+log(P))"); assert_parsed_expression_simplify_to("R(X^2)", "X"); assert_parsed_expression_simplify_to("999^(10000/3)", "999^(10000/3)"); /* This does not reduce but should not as the integer is above @@ -92,11 +92,11 @@ QUIZ_CASE(poincare_power_simplify) { * factors above k_maxNumberOfPrimeFactors. */ assert_parsed_expression_simplify_to("1002101470343^(1/3)", "root(1002101470343,3)"); assert_parsed_expression_simplify_to("P*P*P", "P^3"); - assert_parsed_expression_simplify_to("(x+P)^(3)", "x^3+3*x^2*P+3*x*P^2+P^3"); - assert_parsed_expression_simplify_to("(5+R(2))^(-8)", "(1446241-1003320*R(2))/78310985281"); - assert_parsed_expression_simplify_to("(5*P+R(2))^(-5)", "1/(4*R(2)+100*P+500*R(2)*P^2+2500*P^3+3125*R(2)*P^4+3125*P^5)"); - assert_parsed_expression_simplify_to("(1+R(2)+R(3))^5", "296+224*R(2)+184*R(3)+120*R(6)"); - assert_parsed_expression_simplify_to("(P+R(2)+R(3)+x)^(-3)", "1/(11*R(2)+9*R(3)+15*x+6*R(6)*x+3*R(2)*x^2+3*R(3)*x^2+x^3+15*P+6*R(6)*P+6*R(2)*x*P+6*R(3)*x*P+3*x^2*P+3*R(2)*P^2+3*R(3)*P^2+3*x*P^2+P^3)"); + assert_parsed_expression_simplify_to("(x+P)^(3)", "x^3+3*P*x^2+3*P^2*x+P^3"); + assert_parsed_expression_simplify_to("(5+R(2))^(-8)", "(-1003320*R(2)+1446241)/78310985281"); + assert_parsed_expression_simplify_to("(5*P+R(2))^(-5)", "1/(3125*P^5+3125*R(2)*P^4+2500*P^3+500*R(2)*P^2+100*P+4*R(2))"); + assert_parsed_expression_simplify_to("(1+R(2)+R(3))^5", "120*R(6)+184*R(3)+224*R(2)+296"); + assert_parsed_expression_simplify_to("(P+R(2)+R(3)+x)^(-3)", "1/(x^3+3*P*x^2+3*R(3)*x^2+3*R(2)*x^2+3*P^2*x+6*R(3)*P*x+6*R(2)*P*x+6*R(6)*x+15*x+P^3+3*R(3)*P^2+3*R(2)*P^2+6*R(6)*P+15*P+9*R(3)+11*R(2))"); assert_parsed_expression_simplify_to("1.0066666666667^60", "(10066666666667/10000000000000)^60"); assert_parsed_expression_simplify_to("2^(6+P+x)", "64*2^(x+P)"); assert_parsed_expression_simplify_to("I^(2/3)", "1/2+R(3)/2*I"); diff --git a/poincare/test/simplify_mix.cpp b/poincare/test/simplify_mix.cpp index 03122c151..6ff433b1d 100644 --- a/poincare/test/simplify_mix.cpp +++ b/poincare/test/simplify_mix.cpp @@ -12,47 +12,47 @@ using namespace Poincare; QUIZ_CASE(poincare_simplify_mix) { // Root at denominator - assert_parsed_expression_simplify_to("1/(R(2)+R(3))", "-R(2)+R(3)"); - assert_parsed_expression_simplify_to("1/(5+R(3))", "(5-R(3))/22"); - assert_parsed_expression_simplify_to("1/(R(2)+4)", "(4-R(2))/14"); - assert_parsed_expression_simplify_to("1/(2R(2)-4)", "(-2-R(2))/4"); - assert_parsed_expression_simplify_to("1/(-2R(2)+4)", "(2+R(2))/4"); + assert_parsed_expression_simplify_to("1/(R(2)+R(3))", "R(3)-R(2)"); + assert_parsed_expression_simplify_to("1/(5+R(3))", "(-R(3)+5)/22"); + assert_parsed_expression_simplify_to("1/(R(2)+4)", "(-R(2)+4)/14"); + assert_parsed_expression_simplify_to("1/(2R(2)-4)", "(-R(2)-2)/4"); + assert_parsed_expression_simplify_to("1/(-2R(2)+4)", "(R(2)+2)/4"); assert_parsed_expression_simplify_to("45^2", "2025"); assert_parsed_expression_simplify_to("1/(R(2)ln(3))", "R(2)/(2*ln(3))"); assert_parsed_expression_simplify_to("R(3/2)", "R(6)/2"); // Common operation mix - assert_parsed_expression_simplify_to("(R(2)*P + R(2)*X)/R(2)", "P+X"); - assert_parsed_expression_simplify_to("P+(3R(2)-2R(3))/25", "(3*R(2)-2*R(3)+25*P)/25"); + assert_parsed_expression_simplify_to("(R(2)*P + R(2)*X)/R(2)", "X+P"); + assert_parsed_expression_simplify_to("P+(3R(2)-2R(3))/25", "(25*P-2*R(3)+3*R(2))/25"); assert_parsed_expression_simplify_to("ln(2+3)", "ln(5)"); - assert_parsed_expression_simplify_to("3*A*B*C+4*cos(2)-2*A*B*C+A*B*C+ln(3)+4*A*B-5*A*B*C+cos(3)*ln(5)+cos(2)-45*cos(2)", "-40*cos(2)+ln(3)+cos(3)*ln(5)+4*A*B-3*A*B*C"); - assert_parsed_expression_simplify_to("2*A+3*cos(2)+3+4*ln(5)+5*A+2*ln(5)+1+0", "4+3*cos(2)+6*ln(5)+7*A"); - assert_parsed_expression_simplify_to("2.3*A+3*cos(2)+3+4*ln(5)+5*A+2*ln(5)+1.2+0.235", "(887+600*cos(2)+1200*ln(5)+1460*A)/200"); + assert_parsed_expression_simplify_to("3*A*B*C+4*cos(2)-2*A*B*C+A*B*C+ln(3)+4*A*B-5*A*B*C+cos(3)*ln(5)+cos(2)-45*cos(2)", "cos(3)*ln(5)+ln(3)-40*cos(2)+4*A*B-3*A*B*C"); + assert_parsed_expression_simplify_to("2*A+3*cos(2)+3+4*ln(5)+5*A+2*ln(5)+1+0", "6*ln(5)+3*cos(2)+7*A+4"); + assert_parsed_expression_simplify_to("2.3*A+3*cos(2)+3+4*ln(5)+5*A+2*ln(5)+1.2+0.235", "(1200*ln(5)+600*cos(2)+1460*A+887)/200"); assert_parsed_expression_simplify_to("2*A*B*C+2.3*A*B+3*A^2+5.2*A*B*C+4*A^2", "(70*A^2+23*A*B+72*A*B*C)/10"); assert_parsed_expression_simplify_to("(A*B)^2*A+4*A^3", "4*A^3+A^3*B^2"); assert_parsed_expression_simplify_to("(A*3)^2*A+4*A^3", "13*A^3"); - assert_parsed_expression_simplify_to("A^2^2*A+4*A^3", "4*A^3+A^5"); - assert_parsed_expression_simplify_to("0.5+4*A*B-2.3+2*A*B-2*B*A^C-cos(4)+2*A^C*B+A*B*C*D", "(-9-5*cos(4)+30*A*B+5*A*B*C*D)/5"); - assert_parsed_expression_simplify_to("(1+R(2))/5", "(1+R(2))/5"); - assert_parsed_expression_simplify_to("(2+R(6))^2", "10+4*R(6)"); + assert_parsed_expression_simplify_to("A^2^2*A+4*A^3", "A^5+4*A^3"); + assert_parsed_expression_simplify_to("0.5+4*A*B-2.3+2*A*B-2*B*A^C-cos(4)+2*A^C*B+A*B*C*D", "(-5*cos(4)+30*A*B+5*A*B*C*D-9)/5"); + assert_parsed_expression_simplify_to("(1+R(2))/5", "(R(2)+1)/5"); + assert_parsed_expression_simplify_to("(2+R(6))^2", "4*R(6)+10"); assert_parsed_expression_simplify_to("tan(3)ln(2)+P", "tan(3)*ln(2)+P"); // Complex assert_parsed_expression_simplify_to("I", "I"); assert_parsed_expression_simplify_to("R(-33)", "R(33)*I"); - assert_parsed_expression_simplify_to("I^(3/5)", "(R(2)*R(5-R(5)))/4+(1+R(5))/4*I"); + assert_parsed_expression_simplify_to("I^(3/5)", "(R(2)*R(-R(5)+5))/4+(R(5)+1)/4*I"); assert_parsed_expression_simplify_to("IIII", "1"); assert_parsed_expression_simplify_to("R(-I)", "R(2)/2-R(2)/2*I"); - assert_parsed_expression_simplify_to("A*cos(9)IIln(2)", "-cos(9)*ln(2)*A"); + assert_parsed_expression_simplify_to("A*cos(9)IIln(2)", "-A*cos(9)*ln(2)"); assert_parsed_expression_simplify_to("(R(2)+R(2)*I)/2(R(2)+R(2)*I)/2(R(2)+R(2)*I)/2", "R(2)/32-R(2)/32*I"); assert_parsed_expression_simplify_to("root(5^((-I)3^9),I)", "1/X^atan(tan(19683*ln(5)))"); assert_parsed_expression_simplify_to("I^I", "1/X^(P/2)"); - assert_parsed_expression_simplify_to("I/(1+I*R(x))", "I/(1+R(x)*I)"); - assert_parsed_expression_simplify_to("x+I/(1+I*R(x))", "(x+I+x^(3/2)*I)/(1+R(x)*I)"); + assert_parsed_expression_simplify_to("I/(1+I*R(x))", "I/(R(x)*I+1)"); + assert_parsed_expression_simplify_to("x+I/(1+I*R(x))", "(x^(3/2)*I+I+x)/(R(x)*I+1)"); //assert_parsed_expression_simplify_to("log(cos(9)^ln(6), cos(9))", "ln(2)+ln(3)"); // TODO: for this to work, we must know the sign of cos(9) //assert_parsed_expression_simplify_to("log(cos(9)^ln(6), 9)", "ln(6)*log(cos(9), 9)"); // TODO: for this to work, we must know the sign of cos(9) - assert_parsed_expression_simplify_to("(((R(6)-R(2))/4)/((R(6)+R(2))/4))+1", "3-R(3)"); + assert_parsed_expression_simplify_to("(((R(6)-R(2))/4)/((R(6)+R(2))/4))+1", "-R(3)+3"); //assert_parsed_expression_simplify_to("1/R(I) * (R(2)-I*R(2))", "-2I"); // TODO: get rid of complex at denominator? } diff --git a/poincare/test/store.cpp b/poincare/test/store.cpp index bcd170f76..14f975d5e 100644 --- a/poincare/test/store.cpp +++ b/poincare/test/store.cpp @@ -15,8 +15,8 @@ QUIZ_CASE(poincare_store_evaluate) { } QUIZ_CASE(poincare_store_simplify) { - assert_parsed_expression_simplify_to("1+2>A", "1+2"); - assert_parsed_expression_simplify_to("1+2>x", "1+2"); + assert_parsed_expression_simplify_to("1+2>A", "2+1"); + assert_parsed_expression_simplify_to("1+2>x", "2+1"); // Clean the storage for other tests Ion::Storage::sharedStorage()->recordNamed("A.exp").destroy(); @@ -54,7 +54,7 @@ QUIZ_CASE(poincare_store_overwrite) { QUIZ_CASE(poincare_store_do_not_overwrite) { assert_parsed_expression_simplify_to("-1>g(x)", "-1"); - assert_parsed_expression_simplify_to("1+g(x)>f(x)", "1+g(x)"); + assert_parsed_expression_simplify_to("1+g(x)>f(x)", "g(x)+1"); assert_parsed_expression_simplify_to("2>g", Undefined::Name()); assert_parsed_expression_evaluates_to("g(4)", "-1"); assert_parsed_expression_evaluates_to("f(4)", "0"); diff --git a/poincare/test/trigo.cpp b/poincare/test/trigo.cpp index c86d2114b..a1467a794 100644 --- a/poincare/test/trigo.cpp +++ b/poincare/test/trigo.cpp @@ -339,17 +339,17 @@ QUIZ_CASE(poincare_trigo_simplify) { // -- sin/cos -> tan assert_parsed_expression_simplify_to("sin(x)/cos(x)", "tan(x)"); assert_parsed_expression_simplify_to("cos(x)/sin(x)", "1/tan(x)"); - assert_parsed_expression_simplify_to("sin(x)*P/cos(x)", "tan(x)*P"); + assert_parsed_expression_simplify_to("sin(x)*P/cos(x)", "P*tan(x)"); assert_parsed_expression_simplify_to("sin(x)/(P*cos(x))", "tan(x)/P"); assert_parsed_expression_simplify_to("1*tan(2)*tan(5)", "tan(2)*tan(5)"); assert_parsed_expression_simplify_to("tan(62P/21)", "-tan(P/21)"); assert_parsed_expression_simplify_to("cos(26P/21)/sin(25P/17)", "cos((5*P)/21)/sin((8*P)/17)"); assert_parsed_expression_simplify_to("cos(62P/21)*P*3/sin(62P/21)", "-(3*P)/tan(P/21)"); - assert_parsed_expression_simplify_to("cos(62P/21)/(P*3*sin(62P/21))", "-1/(3*tan(P/21)*P)"); - assert_parsed_expression_simplify_to("sin(62P/21)*P*3/cos(62P/21)", "-3*tan(P/21)*P"); + assert_parsed_expression_simplify_to("cos(62P/21)/(P*3*sin(62P/21))", "-1/(3*P*tan(P/21))"); + assert_parsed_expression_simplify_to("sin(62P/21)*P*3/cos(62P/21)", "-3*P*tan(P/21)"); assert_parsed_expression_simplify_to("sin(62P/21)/(P*3cos(62P/21))", "-tan(P/21)/(3*P)"); - assert_parsed_expression_simplify_to("-cos(P/62)ln(3)/(sin(P/62)P)", "-ln(3)/(tan(P/62)*P)"); - assert_parsed_expression_simplify_to("-2cos(P/62)ln(3)/(sin(P/62)P)", "-(2*ln(3))/(tan(P/62)*P)"); + assert_parsed_expression_simplify_to("-cos(P/62)ln(3)/(sin(P/62)P)", "-ln(3)/(P*tan(P/62))"); + assert_parsed_expression_simplify_to("-2cos(P/62)ln(3)/(sin(P/62)P)", "-(2*ln(3))/(P*tan(P/62))"); // -- cos assert_parsed_expression_simplify_to("cos(0)", "1"); assert_parsed_expression_simplify_to("cos(P)", "-1"); @@ -360,14 +360,14 @@ QUIZ_CASE(poincare_trigo_simplify) { assert_parsed_expression_simplify_to("cos(-P*340001)", "-1"); assert_parsed_expression_simplify_to("cos(-P*R(2))", "cos(R(2)*P)"); assert_parsed_expression_simplify_to("cos(1311P/6)", "0"); - assert_parsed_expression_simplify_to("cos(P/12)", "(R(2)+R(6))/4"); - assert_parsed_expression_simplify_to("cos(-P/12)", "(R(2)+R(6))/4"); - assert_parsed_expression_simplify_to("cos(-P17/8)", "R(2+R(2))/2"); + assert_parsed_expression_simplify_to("cos(P/12)", "(R(6)+R(2))/4"); + assert_parsed_expression_simplify_to("cos(-P/12)", "(R(6)+R(2))/4"); + assert_parsed_expression_simplify_to("cos(-P17/8)", "R(R(2)+2)/2"); assert_parsed_expression_simplify_to("cos(41P/6)", "-R(3)/2"); assert_parsed_expression_simplify_to("cos(P/4+1000P)", "R(2)/2"); assert_parsed_expression_simplify_to("cos(-P/3)", "1/2"); - assert_parsed_expression_simplify_to("cos(41P/5)", "(1+R(5))/4"); - assert_parsed_expression_simplify_to("cos(7P/10)", "-(R(2)*R(5-R(5)))/4"); + assert_parsed_expression_simplify_to("cos(41P/5)", "(R(5)+1)/4"); + assert_parsed_expression_simplify_to("cos(7P/10)", "-(R(2)*R(-R(5)+5))/4"); assert_parsed_expression_simplify_to("cos(0)", "1", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("cos(180)", "-1", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("cos(720/7)", "-cos(540/7)", Preferences::AngleUnit::Degree); @@ -377,14 +377,14 @@ QUIZ_CASE(poincare_trigo_simplify) { assert_parsed_expression_simplify_to("cos(-61200180)", "-1", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("cos(-180*R(2))", "cos(180*R(2))", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("cos(39330)", "0", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(15)", "(R(2)+R(6))/4", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(-15)", "(R(2)+R(6))/4", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(-765/2)", "R(2+R(2))/2", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(15)", "(R(6)+R(2))/4", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(-15)", "(R(6)+R(2))/4", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(-765/2)", "R(R(2)+2)/2", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("cos(7380/6)", "-R(3)/2", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("cos(180045)", "R(2)/2", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("cos(-60)", "1/2", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(7380/5)", "(1+R(5))/4", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(112.5)", "-R(2-R(2))/2", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(7380/5)", "(R(5)+1)/4", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(112.5)", "-R(-R(2)+2)/2", Preferences::AngleUnit::Degree); // -- sin assert_parsed_expression_simplify_to("sin(0)", "0"); assert_parsed_expression_simplify_to("sin(P)", "0"); @@ -393,17 +393,17 @@ QUIZ_CASE(poincare_trigo_simplify) { assert_parsed_expression_simplify_to("sin(P*340000)", "0"); assert_parsed_expression_simplify_to("sin(P*340001)", "0"); assert_parsed_expression_simplify_to("sin(-P*340001)", "0"); - assert_parsed_expression_simplify_to("sin(P/12)", "(-R(2)+R(6))/4"); - assert_parsed_expression_simplify_to("sin(-P/12)", "(R(2)-R(6))/4"); + assert_parsed_expression_simplify_to("sin(P/12)", "(R(6)-R(2))/4"); + assert_parsed_expression_simplify_to("sin(-P/12)", "(-R(6)+R(2))/4"); assert_parsed_expression_simplify_to("sin(-P*R(2))", "-sin(R(2)*P)"); assert_parsed_expression_simplify_to("sin(1311P/6)", "1"); - assert_parsed_expression_simplify_to("sin(-P17/8)", "-R(2-R(2))/2"); + assert_parsed_expression_simplify_to("sin(-P17/8)", "-R(-R(2)+2)/2"); assert_parsed_expression_simplify_to("sin(41P/6)", "1/2"); - assert_parsed_expression_simplify_to("sin(-3P/10)", "(-1-R(5))/4"); + assert_parsed_expression_simplify_to("sin(-3P/10)", "(-R(5)-1)/4"); assert_parsed_expression_simplify_to("sin(P/4+1000P)", "R(2)/2"); assert_parsed_expression_simplify_to("sin(-P/3)", "-R(3)/2"); - assert_parsed_expression_simplify_to("sin(17P/5)", "-(R(2)*R(5+R(5)))/4"); - assert_parsed_expression_simplify_to("sin(P/5)", "(R(2)*R(5-R(5)))/4"); + assert_parsed_expression_simplify_to("sin(17P/5)", "-(R(2)*R(R(5)+5))/4"); + assert_parsed_expression_simplify_to("sin(P/5)", "(R(2)*R(-R(5)+5))/4"); assert_parsed_expression_simplify_to("sin(0)", "0", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("sin(180)", "0", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("sin(6300/29)", "-sin(1080/29)", Preferences::AngleUnit::Degree); @@ -411,16 +411,16 @@ QUIZ_CASE(poincare_trigo_simplify) { assert_parsed_expression_simplify_to("sin(61200000)", "0", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("sin(61200180)", "0", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("sin(-61200180)", "0", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(15)", "(-R(2)+R(6))/4", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(-15)", "(R(2)-R(6))/4", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(15)", "(R(6)-R(2))/4", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(-15)", "(-R(6)+R(2))/4", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("sin(-180*R(2))", "-sin(180*R(2))", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("sin(39330)", "1", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(-765/2)", "-R(2-R(2))/2", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(-765/2)", "-R(-R(2)+2)/2", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("sin(1230)", "1/2", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("sin(180045)", "R(2)/2", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("sin(-60)", "-R(3)/2", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(612)", "-(R(2)*R(5+R(5)))/4", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(36)", "(R(2)*R(5-R(5)))/4", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(612)", "-(R(2)*R(R(5)+5))/4", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(36)", "(R(2)*R(-R(5)+5))/4", Preferences::AngleUnit::Degree); // -- tan assert_parsed_expression_simplify_to("tan(0)", "0"); assert_parsed_expression_simplify_to("tan(P)", "0"); @@ -429,15 +429,15 @@ QUIZ_CASE(poincare_trigo_simplify) { assert_parsed_expression_simplify_to("tan(P*340000)", "0"); assert_parsed_expression_simplify_to("tan(P*340001)", "0"); assert_parsed_expression_simplify_to("tan(-P*340001)", "0"); - assert_parsed_expression_simplify_to("tan(P/12)", "2-R(3)"); - assert_parsed_expression_simplify_to("tan(-P/12)", "-2+R(3)"); + assert_parsed_expression_simplify_to("tan(P/12)", "-R(3)+2"); + assert_parsed_expression_simplify_to("tan(-P/12)", "R(3)-2"); assert_parsed_expression_simplify_to("tan(-P*R(2))", "-tan(R(2)*P)"); assert_parsed_expression_simplify_to("tan(1311P/6)", Undefined::Name()); - assert_parsed_expression_simplify_to("tan(-P17/8)", "1-R(2)"); + assert_parsed_expression_simplify_to("tan(-P17/8)", "-R(2)+1"); assert_parsed_expression_simplify_to("tan(41P/6)", "-R(3)/3"); assert_parsed_expression_simplify_to("tan(P/4+1000P)", "1"); assert_parsed_expression_simplify_to("tan(-P/3)", "-R(3)"); - assert_parsed_expression_simplify_to("tan(-P/10)", "-(R(5)*R(5-2*R(5)))/5"); + assert_parsed_expression_simplify_to("tan(-P/10)", "-(R(5)*R(-2*R(5)+5))/5"); assert_parsed_expression_simplify_to("tan(0)", "0", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("tan(180)", "0", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("tan(6300/29)", "tan(1080/29)", Preferences::AngleUnit::Degree); @@ -445,11 +445,11 @@ QUIZ_CASE(poincare_trigo_simplify) { assert_parsed_expression_simplify_to("tan(61200000)", "0", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("tan(61200180)", "0", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("tan(-61200180)", "0", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("tan(15)", "2-R(3)", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("tan(-15)", "-2+R(3)", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(15)", "-R(3)+2", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(-15)", "R(3)-2", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("tan(-180*R(2))", "-tan(180*R(2))", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("tan(39330)", Undefined::Name(), Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("tan(-382.5)", "1-R(2)", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(-382.5)", "-R(2)+1", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("tan(1230)", "-R(3)/3", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("tan(180045)", "1", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("tan(-60)", "-R(3)", Preferences::AngleUnit::Degree); @@ -463,9 +463,9 @@ QUIZ_CASE(poincare_trigo_simplify) { assert_parsed_expression_simplify_to("cos(acos(2/3))", "2/3"); assert_parsed_expression_simplify_to("acos(cos(12))", "acos(cos(12))"); assert_parsed_expression_simplify_to("acos(cos(4P/7))", "(4*P)/7"); - assert_parsed_expression_simplify_to("acos(-cos(2))", "-2+P"); + assert_parsed_expression_simplify_to("acos(-cos(2))", "P-2"); assert_parsed_expression_simplify_to("acos(-1/2)", "120", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("acos(-1.2)", "180-acos(6/5)", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("acos(-1.2)", "-acos(6/5)+180", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("acos(cos(2/3))", "2/3", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("acos(cos(190))", "170", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("acos(cos(75))", "75", Preferences::AngleUnit::Degree); @@ -511,24 +511,24 @@ QUIZ_CASE(poincare_trigo_simplify) { assert_parsed_expression_simplify_to("atan(tan(1808))", "8", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("atan(tan(-180/7))", "-180/7", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("atan(R(3))", "60", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("atan(1/x)", "(-2*atan(x)+sign(x)*P)/2", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("atan(1/x)", "(P*sign(x)-2*atan(x))/2", Preferences::AngleUnit::Degree); // cos(arcsin) - assert_parsed_expression_simplify_to("cos(asin(x))", "R(1-x^2)", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(asin(-x))", "R(1-x^2)", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(asin(x))", "R(-x^2+1)", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(asin(-x))", "R(-x^2+1)", Preferences::AngleUnit::Degree); // cos(arctan) - assert_parsed_expression_simplify_to("cos(atan(x))", "1/R(1+x^2)", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(atan(-x))", "1/R(1+x^2)", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(atan(x))", "1/R(x^2+1)", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(atan(-x))", "1/R(x^2+1)", Preferences::AngleUnit::Degree); // sin(arccos) - assert_parsed_expression_simplify_to("sin(acos(x))", "R(1-x^2)", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(acos(-x))", "R(1-x^2)", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(acos(x))", "R(-x^2+1)", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(acos(-x))", "R(-x^2+1)", Preferences::AngleUnit::Degree); // sin(arctan) - assert_parsed_expression_simplify_to("sin(atan(x))", "x/R(1+x^2)", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(atan(-x))", "-x/R(1+x^2)", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(atan(x))", "x/R(x^2+1)", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(atan(-x))", "-x/R(x^2+1)", Preferences::AngleUnit::Degree); // tan(arccos) - assert_parsed_expression_simplify_to("tan(acos(x))", "R(1-x^2)/x", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("tan(acos(-x))", "-R(1-x^2)/x", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(acos(x))", "R(-x^2+1)/x", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(acos(-x))", "-R(-x^2+1)/x", Preferences::AngleUnit::Degree); // tan(arcsin) - assert_parsed_expression_simplify_to("tan(asin(x))", "x/R(1-x^2)", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("tan(asin(-x))", "-x/R(1-x^2)", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(asin(x))", "x/R(-x^2+1)", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(asin(-x))", "-x/R(-x^2+1)", Preferences::AngleUnit::Degree); } diff --git a/poincare/test/user_variable.cpp b/poincare/test/user_variable.cpp index fc657cd3c..aaab82c3b 100644 --- a/poincare/test/user_variable.cpp +++ b/poincare/test/user_variable.cpp @@ -8,11 +8,11 @@ using namespace Poincare; QUIZ_CASE(poincare_user_variable_simple) { // Fill variable - assert_parsed_expression_simplify_to("1+2>Adadas", "1+2"); + assert_parsed_expression_simplify_to("1+2>Adadas", "2+1"); assert_parsed_expression_simplify_to("Adadas", "3"); // Fill f1 - assert_parsed_expression_simplify_to("1+x>f1(x)", "1+x"); + assert_parsed_expression_simplify_to("1+x>f1(x)", "x+1"); assert_parsed_expression_simplify_to("f1(4)", "5"); assert_parsed_expression_simplify_to("f1(Adadas)", "4"); From 8e725ce328a41482935361b621a74afc784fa4cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 28 Dec 2018 17:43:26 +0100 Subject: [PATCH 179/373] [emscripten] Init the random seed to current time This way the random numbers sequence changes each time epsilon is launched. --- ion/src/emscripten/main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ion/src/emscripten/main.cpp b/ion/src/emscripten/main.cpp index daee539d3..dac995e3c 100644 --- a/ion/src/emscripten/main.cpp +++ b/ion/src/emscripten/main.cpp @@ -16,6 +16,9 @@ int main(int argc, char * argv[]) { Ion::Display::Emscripten::init(); Ion::Events::Emscripten::init(); + // Set the seed for random using the current time + srand(emscripten_get_now()); + ion_main(argc, argv); return 0; } From f962e92316b43cb078053625205e922e73e78bae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 3 Jan 2019 10:43:29 +0100 Subject: [PATCH 180/373] [apps/graph] Fix wrong assertion --- apps/graph/list/storage_list_controller.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/graph/list/storage_list_controller.cpp b/apps/graph/list/storage_list_controller.cpp index adaab3ddb..bad9924ec 100644 --- a/apps/graph/list/storage_list_controller.cpp +++ b/apps/graph/list/storage_list_controller.cpp @@ -176,13 +176,14 @@ void StorageListController::willDisplayExpressionCellAtIndex(HighlightCell * cel } void StorageListController::setFunctionNameInTextField(ExpiringPointer function, TextField * textField) { + assert(textField != nullptr); char bufferName[BufferTextView::k_maxNumberOfChar]; function->nameWithArgument(bufferName, BufferTextView::k_maxNumberOfChar, modelStore()->symbol()); textField->setText(bufferName); } KDCoordinate StorageListController::privateBaseline(int j) const { - assert(j>=0 && j= 0 && j < const_cast(this)->modelStore()->numberOfModels()); Shared::FunctionExpressionCell * cell = static_cast((const_cast(&m_selectableTableView))->cellAtLocation(1, j)); Poincare::Layout layout = cell->layout(); if (layout.isUninitialized()) { From ab4b4da069f0087c6cb644e3de9991010e13e366 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 3 Jan 2019 10:43:55 +0100 Subject: [PATCH 181/373] [apps/graph] Add assertions --- apps/graph/list/storage_list_controller.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/graph/list/storage_list_controller.cpp b/apps/graph/list/storage_list_controller.cpp index bad9924ec..3f560440d 100644 --- a/apps/graph/list/storage_list_controller.cpp +++ b/apps/graph/list/storage_list_controller.cpp @@ -46,6 +46,7 @@ void StorageListController::renameSelectedFunction() { } bool StorageListController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) { + assert(textField != nullptr); // Compute the new name size_t textLength = strlen(text); size_t argumentLength = StorageFunction::k_parenthesedArgumentLength; @@ -113,6 +114,7 @@ bool StorageListController::textFieldDidFinishEditing(TextField * textField, con } bool StorageListController::textFieldDidAbortEditing(TextField * textField) { + assert(textField != nullptr); // Put the name column back to normal size computeTitlesColumnWidth(); selectableTableView()->reloadData(); @@ -129,6 +131,7 @@ bool StorageListController::textFieldShouldFinishEditing(TextField * textField, } bool StorageListController::textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) { + assert(textField != nullptr); if (textField->isEditing() && textField->shouldFinishEditing(event)) { return false; } @@ -154,8 +157,10 @@ HighlightCell * StorageListController::expressionCells(int index) { } void StorageListController::willDisplayTitleCellAtIndex(HighlightCell * cell, int j) { + assert(cell != nullptr); + assert(j >= 0 && j < modelStore()->numberOfModels()); TextFieldFunctionTitleCell * titleCell = static_cast(cell); - // Update the corresponding expression cell in order to geet the baseline + // Update the corresponding expression cell in order to get the baseline StorageExpressionModelListController::willDisplayExpressionCellAtIndex(m_selectableTableView.cellAtLocation(1, j), j); titleCell->setBaseline(baseline(j)); if (!titleCell->isEditing()) { @@ -168,6 +173,8 @@ void StorageListController::willDisplayTitleCellAtIndex(HighlightCell * cell, in } void StorageListController::willDisplayExpressionCellAtIndex(HighlightCell * cell, int j) { + assert(cell != nullptr); + assert(j >= 0 && j < modelStore()->numberOfModels()); Shared::StorageFunctionListController::willDisplayExpressionCellAtIndex(cell, j); FunctionExpressionCell * myCell = (FunctionExpressionCell *)cell; ExpiringPointer f = modelStore()->modelForRecord(modelStore()->recordAtIndex(j)); From 101db272c8feca5dcbf9d691c38a89a0dfbfd80e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 3 Jan 2019 11:30:52 +0100 Subject: [PATCH 182/373] [test/calculation] 1+1->a shoud display 2, not 1+1=2 --- apps/calculation/test/calculation_store.cpp | 4 ++-- poincare/test/store.cpp | 10 +++++----- poincare/test/user_variable.cpp | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/apps/calculation/test/calculation_store.cpp b/apps/calculation/test/calculation_store.cpp index ab9019fb9..151d6254a 100644 --- a/apps/calculation/test/calculation_store.cpp +++ b/apps/calculation/test/calculation_store.cpp @@ -106,9 +106,9 @@ QUIZ_CASE(calculation_display_exact_approximate) { assertCalculationDisplay("28^7", false, false, ::Calculation::Calculation::EqualSign::Unknown, nullptr, nullptr, &globalContext, &store); assertCalculationDisplay("3+R(2)>a", false, false, ::Calculation::Calculation::EqualSign::Approximation, "R(2)+3", nullptr, &globalContext, &store); Ion::Storage::sharedStorage()->recordNamed("a.exp").destroy(); - assertCalculationDisplay("3+2>a", false, false, ::Calculation::Calculation::EqualSign::Equal, "3+2", "5", &globalContext, &store); + assertCalculationDisplay("3+2>a", false, true, ::Calculation::Calculation::EqualSign::Equal, "5", "5", &globalContext, &store); Ion::Storage::sharedStorage()->recordNamed("a.exp").destroy(); - assertCalculationDisplay("3>a", false, true, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "3", &globalContext, &store); + assertCalculationDisplay("3>a", false, true, ::Calculation::Calculation::EqualSign::Equal, "3", "3", &globalContext, &store); Ion::Storage::sharedStorage()->recordNamed("a.exp").destroy(); assertCalculationDisplay("3+x>f(x)", true, false, ::Calculation::Calculation::EqualSign::Unknown, "x+3", nullptr, &globalContext, &store); Ion::Storage::sharedStorage()->recordNamed("f.func").destroy(); diff --git a/poincare/test/store.cpp b/poincare/test/store.cpp index 14f975d5e..deb1dc30d 100644 --- a/poincare/test/store.cpp +++ b/poincare/test/store.cpp @@ -15,17 +15,17 @@ QUIZ_CASE(poincare_store_evaluate) { } QUIZ_CASE(poincare_store_simplify) { - assert_parsed_expression_simplify_to("1+2>A", "2+1"); - assert_parsed_expression_simplify_to("1+2>x", "2+1"); + assert_parsed_expression_simplify_to("1+2>x", "3"); + assert_parsed_expression_simplify_to("0.1+0.2>x", "3/10"); + assert_parsed_expression_simplify_to("a+a>x", "2*a"); // Clean the storage for other tests - Ion::Storage::sharedStorage()->recordNamed("A.exp").destroy(); Ion::Storage::sharedStorage()->recordNamed("x.exp").destroy(); } QUIZ_CASE(poincare_store_matrix) { assert_parsed_expression_evaluates_to("[[7]]>a", "[[7]]"); - assert_parsed_expression_simplify_to("1+1>a", "1+1"); + assert_parsed_expression_simplify_to("1+1>a", "2"); // Clean the storage for other tests Ion::Storage::sharedStorage()->recordNamed("a.exp").destroy(); @@ -54,7 +54,7 @@ QUIZ_CASE(poincare_store_overwrite) { QUIZ_CASE(poincare_store_do_not_overwrite) { assert_parsed_expression_simplify_to("-1>g(x)", "-1"); - assert_parsed_expression_simplify_to("1+g(x)>f(x)", "g(x)+1"); + assert_parsed_expression_simplify_to("1+g(x)>f(x)", "0"); assert_parsed_expression_simplify_to("2>g", Undefined::Name()); assert_parsed_expression_evaluates_to("g(4)", "-1"); assert_parsed_expression_evaluates_to("f(4)", "0"); diff --git a/poincare/test/user_variable.cpp b/poincare/test/user_variable.cpp index aaab82c3b..7fbc9dc57 100644 --- a/poincare/test/user_variable.cpp +++ b/poincare/test/user_variable.cpp @@ -8,7 +8,7 @@ using namespace Poincare; QUIZ_CASE(poincare_user_variable_simple) { // Fill variable - assert_parsed_expression_simplify_to("1+2>Adadas", "2+1"); + assert_parsed_expression_simplify_to("1+2>Adadas", "3"); assert_parsed_expression_simplify_to("Adadas", "3"); // Fill f1 @@ -22,7 +22,7 @@ QUIZ_CASE(poincare_user_variable_simple) { assert_parsed_expression_simplify_to("f2(Adadas)", "2"); // Define fBoth with f1 and f2 - assert_parsed_expression_simplify_to("f1(x)+f2(x)>fBoth(x)", "f1(x)+f2(x)"); + assert_parsed_expression_simplify_to("f1(x)+f2(x)>fBoth(x)", "2*x"); assert_parsed_expression_simplify_to("fBoth(4)", "8"); assert_parsed_expression_simplify_to("fBoth(Adadas)", "6"); From 300e79732480415d53f75a1c15e898d350df841b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 3 Jan 2019 11:49:16 +0100 Subject: [PATCH 183/373] [poincare/store] Store shallow reduces into the reduced left operand --- poincare/include/poincare/store.h | 2 +- poincare/src/store.cpp | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/store.h b/poincare/include/poincare/store.h index 3b2c21769..f46042765 100644 --- a/poincare/include/poincare/store.h +++ b/poincare/include/poincare/store.h @@ -55,7 +55,7 @@ public: } // Expression - Expression shallowReduce(Context & context); + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); }; } diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index 19226410f..b4327b575 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -20,7 +20,7 @@ void StoreNode::deepReduceChildren(Context & context, Preferences::ComplexFormat } Expression StoreNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Store(this).shallowReduce(context); + return Store(this).shallowReduce(context, complexFormat, angleUnit, target); } int StoreNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -50,7 +50,7 @@ Evaluation StoreNode::templatedApproximate(Context& context, Preferences::Ang return e.node()->approximate(T(), context, angleUnit); } -Expression Store::shallowReduce(Context & context) { +Expression Store::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { Expression finalValue; if (symbol().type() == ExpressionNode::Type::Function) { // In tata + 2 ->f(tata), replace tata with xUnknown symbol @@ -76,6 +76,7 @@ Expression Store::shallowReduce(Context & context) { e = e.replaceSymbolWithExpression(xUnknown, static_cast(userDefinedUnknown)); } replaceWithInPlace(e); + e = e.deepReduce(context, complexFormat, angleUnit, target); return e; } From 892dd2de4f29e416efa48a8c70ebb756407385d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 3 Jan 2019 11:50:06 +0100 Subject: [PATCH 184/373] [apps/poincare] Clean some comments --- apps/calculation/calculation_store.cpp | 8 ++++---- poincare/include/poincare/decimal.h | 2 +- poincare/include/poincare/number.h | 4 +++- poincare/src/number.cpp | 3 ++- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/apps/calculation/calculation_store.cpp b/apps/calculation/calculation_store.cpp index b3f747c9d..64813e188 100644 --- a/apps/calculation/calculation_store.cpp +++ b/apps/calculation/calculation_store.cpp @@ -92,10 +92,10 @@ Expression CalculationStore::ansExpression(Context * context) { } Calculation * lastCalculation = calculationAtIndex(numberOfCalculations()-1); /* Special case: the exact output is a Store/Equal expression. - * Store/Equal expression must be final root of an expression. - * To avoid turning 'ans->A' in '2->A->A' (or 2->A=A) which cannot be parsed), - * ans is replaced by the approximation output in when any Store or Equal - * expression appears.*/ + * Store/Equal expression can only be at the root of an expression. + * To avoid turning 'ans->A' in '2->A->A' or '2=A->A' (which cannot be + * parsed), ans is replaced by the approximation output when any Store or + * Equal expression appears. */ bool exactOuptutInvolvesStoreEqual = lastCalculation->exactOutput().recursivelyMatches([](const Expression e, Context & context, bool replaceSymbols) { return e.type() == ExpressionNode::Type::Store || e.type() == ExpressionNode::Type::Equal; }, *context, false); diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index 267430441..adc0ecf31 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -6,7 +6,7 @@ namespace Poincare { -/* A decimal as 0.01234 is stored that way: +/* The decimal 0.01234 is stored as: * - bool m_negative = false * - int m_exponent = -2 * - int m_numberOfDigitsInMantissa = 1 diff --git a/poincare/include/poincare/number.h b/poincare/include/poincare/number.h index 557fa5b0b..0047c6c22 100644 --- a/poincare/include/poincare/number.h +++ b/poincare/include/poincare/number.h @@ -11,7 +11,9 @@ namespace Poincare { * - Float * - Decimal * - Infinity - */ + * + * Before being approximated, an expression should be reduced and thus should + * not contain any Decimal. */ class Rational; diff --git a/poincare/src/number.cpp b/poincare/src/number.cpp index e991c254a..bfc42b518 100644 --- a/poincare/src/number.cpp +++ b/poincare/src/number.cpp @@ -91,7 +91,8 @@ Number Number::BinaryOperation(const Number & i, const Number & j, RationalBinar return a; } } - // one of the operand is Undefined/Infinity/Float or the Rational addition overflowed + /* At least one of the operands is Undefined/Infinity/Float, or the Rational + * addition overflowed */ double a = doubleOp(i.node()->doubleApproximation(), j.node()->doubleApproximation()); return FloatNumber(a); } From b25c8f4df2514bdfef0092f63463075b3fac416d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 3 Jan 2019 13:40:03 +0100 Subject: [PATCH 185/373] [poincare] Fix store tests --- poincare/test/helper.cpp | 10 +++++++--- poincare/test/helper.h | 2 ++ poincare/test/parser.cpp | 1 + poincare/test/user_variable.cpp | 4 ++-- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/poincare/test/helper.cpp b/poincare/test/helper.cpp index b72b72352..1674a519b 100644 --- a/poincare/test/helper.cpp +++ b/poincare/test/helper.cpp @@ -113,12 +113,16 @@ void assert_parsed_expression_polynomial_degree(const char * expression, int deg quiz_assert(result.polynomialDegree(globalContext, symbolName) == degree); } -void assert_simplify(const char * expression) { + +Expression parse_and_simplify(const char * expression) { Shared::GlobalContext globalContext; Expression e = parse_expression(expression); quiz_assert(!e.isUninitialized()); - e = e.simplify(globalContext, Cartesian, Radian); - quiz_assert(!e.isUninitialized()); + return e.simplify(globalContext, Cartesian, Radian); +} + +void assert_simplify(const char * expression) { + quiz_assert(!(parse_and_simplify(expression).isUninitialized())); } typedef Expression (*ProcessExpression)(Expression, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); diff --git a/poincare/test/helper.h b/poincare/test/helper.h index ca04f6cb7..c6a3d1722 100644 --- a/poincare/test/helper.h +++ b/poincare/test/helper.h @@ -20,6 +20,8 @@ bool expressions_are_equal(Poincare::Expression expected, Poincare::Expression g void translate_in_special_chars(char * expression); void translate_in_ASCII_chars(char * expression); Poincare::Expression parse_expression(const char * expression, bool canBeUnparsable = false); +Poincare::Expression parse_and_simplify(const char * expression); + void assert_expression_not_parsable(const char * expression); void assert_parsed_expression_type(const char * expression, Poincare::ExpressionNode::Type type); void assert_parsed_expression_is(const char * expression, Poincare::Expression r); diff --git a/poincare/test/parser.cpp b/poincare/test/parser.cpp index 56488fdfe..1bbfe27b5 100644 --- a/poincare/test/parser.cpp +++ b/poincare/test/parser.cpp @@ -338,6 +338,7 @@ QUIZ_CASE(poincare_parser_parse_store) { assert_parsed_expression_is("1>f(x)", Store(Rational(1),Function("f",1,Symbol("x",1)))); assert_parsed_expression_is("x>f(x)", Store(Symbol("x",1),Function("f",1,Symbol("x",1)))); assert_parsed_expression_is("n>f(x)", Store(Symbol("n",1),Function("f",1,Symbol("x",1)))); + assert_parsed_expression_is("[[x]]>f(x)", Store(Matrix(Symbol('x')), Function("f", 1, Symbol('x')))); assert_raises_parsing_error("a>b>c"); assert_raises_parsing_error("1>2"); assert_raises_parsing_error("1>"); diff --git a/poincare/test/user_variable.cpp b/poincare/test/user_variable.cpp index 7fbc9dc57..f962bd1e7 100644 --- a/poincare/test/user_variable.cpp +++ b/poincare/test/user_variable.cpp @@ -179,11 +179,11 @@ QUIZ_CASE(poincare_user_variable_functions_with_context) { QUIZ_CASE(poincare_user_variable_properties) { Shared::GlobalContext context; - assert_simplify("[[1]]>a"); + assert_parsed_expression_evaluates_to("[[1]]>a", "[[1]]"); assert(Symbol('a').isApproximate(context)); assert(Poincare::Expression::IsMatrix(Symbol('a'), context, true)); - assert_simplify("[[x]]>f(x)"); + parse_and_simplify("[[x]]>f(x)"); assert(Function("f", 1, Rational(2)).isApproximate(context)); assert(Poincare::Expression::IsMatrix(Function("f", 1, Symbol('x')), context, true)); From 4bfd77b0936c931e3ab6c8cb11641c00810c0e18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 3 Jan 2019 13:40:56 +0100 Subject: [PATCH 186/373] [test] Replace assert by quiz_assert --- poincare/test/user_variable.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/poincare/test/user_variable.cpp b/poincare/test/user_variable.cpp index f962bd1e7..9814cc638 100644 --- a/poincare/test/user_variable.cpp +++ b/poincare/test/user_variable.cpp @@ -180,12 +180,12 @@ QUIZ_CASE(poincare_user_variable_properties) { Shared::GlobalContext context; assert_parsed_expression_evaluates_to("[[1]]>a", "[[1]]"); - assert(Symbol('a').isApproximate(context)); - assert(Poincare::Expression::IsMatrix(Symbol('a'), context, true)); + quiz_assert(Symbol('a').isApproximate(context)); + quiz_assert(Poincare::Expression::IsMatrix(Symbol('a'), context, true)); parse_and_simplify("[[x]]>f(x)"); - assert(Function("f", 1, Rational(2)).isApproximate(context)); - assert(Poincare::Expression::IsMatrix(Function("f", 1, Symbol('x')), context, true)); + quiz_assert(Function("f", 1, Rational(2)).isApproximate(context)); + quiz_assert(Poincare::Expression::IsMatrix(Function("f", 1, Symbol('x')), context, true)); // Clean the storage for other tests Ion::Storage::sharedStorage()->recordNamed("a.exp").destroy(); From 34b22298c458d78d4c12aaa40670416972b13bb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 3 Jan 2019 13:42:24 +0100 Subject: [PATCH 187/373] [ion/storage] Add assertion on dot in record name --- ion/src/shared/storage.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ion/src/shared/storage.cpp b/ion/src/shared/storage.cpp index efa031ab9..66b303843 100644 --- a/ion/src/shared/storage.cpp +++ b/ion/src/shared/storage.cpp @@ -206,6 +206,7 @@ Storage::Record Storage::recordBaseNamedWithExtensions(const char * baseName, co if (strncmp(baseName, currentName, nameLength) == 0) { for (size_t i = 0; i < numberOfExtensions; i++) { if (strcmp(currentName+nameLength+1 /*+1 to pass the dot*/, extensions[i]) == 0) { + assert(*(currentName + nameLength) == '.'); return Record(currentName); } } From 014b481a9b44d848c8d47e470d6112bdcd74d72a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 3 Jan 2019 14:09:37 +0100 Subject: [PATCH 188/373] [apps/solver] Fix iteration max index --- apps/solver/equation_store.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/solver/equation_store.cpp b/apps/solver/equation_store.cpp index 1becac586..384a33b8c 100644 --- a/apps/solver/equation_store.cpp +++ b/apps/solver/equation_store.cpp @@ -176,9 +176,11 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) { /* Turn the results in layouts */ int solutionIndex = 0; int initialNumberOfSolutions = m_numberOfSolutions <= k_maxNumberOfExactSolutions ? m_numberOfSolutions : -1; + int maxNumberSolutions = initialNumberOfSolutions + (initialNumberOfSolutions >= k_maxNumberOfExactSolutions - 1 ? 0 : 1); // We iterate through the solutions and the potential delta - for (int i = 0; i < initialNumberOfSolutions+1; i++) { + for (int i = 0; i < maxNumberSolutions; i++) { if (!exactSolutions[i].isUninitialized()) { + assert(!exactSolutionsApproximations[i].isUninitialized()); if (exactSolutionsApproximations[i].type() == ExpressionNode::Type::Unreal) { /* Discard unreal solutions. */ if (i < initialNumberOfSolutions) { From d6e7f78705ba3f779f6428a0b137f815bd85636a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 3 Jan 2019 14:09:56 +0100 Subject: [PATCH 189/373] [apps/solver] Clean comments --- apps/solver/equation_store.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/apps/solver/equation_store.cpp b/apps/solver/equation_store.cpp index 384a33b8c..a5f654e22 100644 --- a/apps/solver/equation_store.cpp +++ b/apps/solver/equation_store.cpp @@ -101,7 +101,7 @@ void EquationStore::approximateSolve(Poincare::Context * context) { EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) { tidySolution(); - /* 0- Get unknown variables */ + // Step 0. Get unknown variables m_variables[0][0] = 0; int numberOfVariables = 0; for (int i = 0; i < numberOfDefinedModels(); i++) { @@ -121,9 +121,10 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) { assert(numberOfVariables >= 0); } - /* 1- Linear System? */ + // Step 1. Linear System? + /* Create matrix coefficients and vector constants as: - * coefficients*(x y z ...) = constants */ + * coefficients * (x y z ...) = constants */ Expression coefficients[k_maxNumberOfEquations][Expression::k_maxNumberOfVariables]; Expression constants[k_maxNumberOfEquations]; bool isLinear = true; // Invalid the linear system if one equation is non-linear @@ -148,7 +149,7 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) { } } - /* Initialize result */ + // Initialize result Expression exactSolutions[k_maxNumberOfExactSolutions]; Expression exactSolutionsApproximations[k_maxNumberOfExactSolutions]; EquationStore::Error error; @@ -157,23 +158,23 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) { m_type = Type::LinearSystem; error = resolveLinearSystem(exactSolutions, exactSolutionsApproximations, coefficients, constants, context); } else { - /* 2- Polynomial & Monovariable? */ + // Step 2. Polynomial & Monovariable? assert(numberOfVariables == 1 && numberOfDefinedModels() == 1); Expression polynomialCoefficients[Expression::k_maxNumberOfPolynomialCoefficients]; int degree = definedModelAtIndex(0)->standardForm(context).getPolynomialReducedCoefficients(m_variables[0], polynomialCoefficients, *context, updatedComplexFormat(), preferences->angleUnit()); if (degree == 2) { - /* Polynomial degree <= 2*/ + // Polynomial degree <= 2 m_type = Type::PolynomialMonovariable; error = oneDimensialPolynomialSolve(exactSolutions, exactSolutionsApproximations, polynomialCoefficients, degree, context); } else { - /* 3- Monovariable non-polynomial or polynomial with degree > 2 */ + // Step 3. Monovariable non-polynomial or polynomial with degree > 2 m_type = Type::Monovariable; m_intervalApproximateSolutions[0] = -10; m_intervalApproximateSolutions[1] = 10; return Error::RequireApproximateSolution; } } - /* Turn the results in layouts */ + // Create the results' layouts int solutionIndex = 0; int initialNumberOfSolutions = m_numberOfSolutions <= k_maxNumberOfExactSolutions ? m_numberOfSolutions : -1; int maxNumberSolutions = initialNumberOfSolutions + (initialNumberOfSolutions >= k_maxNumberOfExactSolutions - 1 ? 0 : 1); @@ -182,24 +183,23 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) { if (!exactSolutions[i].isUninitialized()) { assert(!exactSolutionsApproximations[i].isUninitialized()); if (exactSolutionsApproximations[i].type() == ExpressionNode::Type::Unreal) { - /* Discard unreal solutions. */ + // Discard unreal solutions. if (i < initialNumberOfSolutions) { // Discard the solution m_numberOfSolutions--; continue; } // Delta is not real - assert( i == initialNumberOfSolutions); + assert(i == initialNumberOfSolutions); } m_exactSolutionExactLayouts[solutionIndex] = PoincareHelpers::CreateLayout(exactSolutions[i]); m_exactSolutionApproximateLayouts[solutionIndex] = PoincareHelpers::CreateLayout(exactSolutionsApproximations[i]); - /* Check for identity between exact and approximate layouts */ + // Check for identity between exact and approximate layouts char exactBuffer[Shared::ExpressionModel::k_expressionBufferSize]; char approximateBuffer[Shared::ExpressionModel::k_expressionBufferSize]; m_exactSolutionExactLayouts[solutionIndex].serializeForParsing(exactBuffer, Shared::ExpressionModel::k_expressionBufferSize); m_exactSolutionApproximateLayouts[solutionIndex].serializeForParsing(approximateBuffer, Shared::ExpressionModel::k_expressionBufferSize); m_exactSolutionIdentity[solutionIndex] = strcmp(exactBuffer, approximateBuffer) == 0; - /* Check for equality between exact and approximate layouts */ if (!m_exactSolutionIdentity[solutionIndex]) { char buffer[Shared::ExpressionModel::k_expressionBufferSize]; m_exactSolutionEquality[solutionIndex] = exactSolutions[i].isEqualToItsApproximationLayout(exactSolutionsApproximations[i], buffer, Shared::ExpressionModel::k_expressionBufferSize, preferences->complexFormat(), preferences->angleUnit(), preferences->displayMode(), preferences->numberOfSignificantDigits(), *context); From 8a2bdb4c4239d46b18d9e95a61f98e8ac3a90fa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 3 Jan 2019 16:18:11 +0100 Subject: [PATCH 190/373] [poincare] When reducing store, handle non reductible left side --- poincare/include/poincare/expression.h | 1 + poincare/src/expression.cpp | 4 ++++ poincare/src/store.cpp | 15 ++++++++++++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 5cfde6871..9fc2dd62a 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -232,6 +232,7 @@ public: static void Tidy() { sSymbolReplacementsCountLock = false; } protected: + static bool SimplificationHasBeenInterrupted(); Expression(const ExpressionNode * n) : TreeHandle(n) {} template T convert() const { diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 069f51343..0238a0327 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -226,6 +226,10 @@ Expression Expression::defaultShallowReduce() { return *this; } +bool Expression::SimplificationHasBeenInterrupted() { + return sSimplificationHasBeenInterrupted; +} + Expression Expression::parent() const { TreeHandle p = TreeHandle::parent(); return static_cast(p); diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index b4327b575..7b733528d 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -75,8 +75,21 @@ Expression Store::shallowReduce(Context & context, Preferences::ComplexFormat co Symbol xUnknown = Symbol(Symbol::SpecialSymbols::UnknownX); e = e.replaceSymbolWithExpression(xUnknown, static_cast(userDefinedUnknown)); } + + /* We want to replace the store with its reduced left side. If the + * simplification of the left side failed, just replace with the left side of + * the store without simplifying it. + * The simplification fails for [x]->d(x) for instance, because we do not + * have exact simplification of matrices yet. */ + bool interruptedSimplification = SimplificationHasBeenInterrupted(); + Expression reducedE = e.clone().deepReduce(context, complexFormat, angleUnit, target); + if (!reducedE.isUninitialized() && !SimplificationHasBeenInterrupted()) { + e = reducedE; + } + // Restore the previous interruption flag + setInterruption(interruptedSimplification); + replaceWithInPlace(e); - e = e.deepReduce(context, complexFormat, angleUnit, target); return e; } From 271e22628bd6b3591502cb17e61d84c7731916db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 3 Jan 2019 16:19:48 +0100 Subject: [PATCH 191/373] Typo in comment --- apps/calculation/calculation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/calculation/calculation.cpp b/apps/calculation/calculation.cpp index c98c20c34..97bdfff95 100644 --- a/apps/calculation/calculation.cpp +++ b/apps/calculation/calculation.cpp @@ -166,7 +166,7 @@ bool Calculation::shouldOnlyDisplayExactOutput() { /* If the approximateOutput is undef, we not not want to display it. * This prevents: * x->f(x) from displaying x = undef - * x+x form displaying 2x = undef */ + * x+x from displaying 2x = undef */ return strcmp(m_approximateOutputText, Undefined::Name()) == 0; } From e5f0959239e8238904e13cc77e68626d6c056fa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 3 Jan 2019 16:39:12 +0100 Subject: [PATCH 192/373] [poincare] Static Expression methods start with uppercase --- apps/apps_container.cpp | 2 +- apps/regression/model/model.cpp | 4 ++-- apps/shared/poincare_helpers.h | 2 +- poincare/include/poincare/expression.h | 20 ++++++++++---------- poincare/src/absolute_value.cpp | 4 ++-- poincare/src/approximation_helper.cpp | 2 +- poincare/src/complex_argument.cpp | 4 ++-- poincare/src/complex_cartesian.cpp | 4 ++-- poincare/src/expression.cpp | 26 +++++++++++++------------- poincare/src/expression_node.cpp | 4 ++-- poincare/src/integral.cpp | 2 +- poincare/src/matrix.cpp | 6 +++--- poincare/src/power.cpp | 4 ++-- poincare/src/sequence.cpp | 2 +- poincare/src/store.cpp | 2 +- poincare/src/trigonometry.cpp | 6 +++--- poincare/test/helper.cpp | 2 +- 17 files changed, 48 insertions(+), 48 deletions(-) diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index 2b038e6e5..9963aaa24 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -84,7 +84,7 @@ AppsContainer::AppsContainer() : * We just remove the circuit breaker for now. * TODO: Put the Poincare circuit breaker back on epsilon's web emulator */ #else - Poincare::Expression::setCircuitBreaker(AppsContainer::poincareCircuitBreaker); + Poincare::Expression::SetCircuitBreaker(AppsContainer::poincareCircuitBreaker); #endif Ion::Storage::sharedStorage()->setDelegate(this); } diff --git a/apps/regression/model/model.cpp b/apps/regression/model/model.cpp index f4a3e2cf6..3b287687d 100644 --- a/apps/regression/model/model.cpp +++ b/apps/regression/model/model.cpp @@ -128,8 +128,8 @@ double Model::alphaPrimeCoefficient(Store * store, int series, double * modelCoe * a'(k,k) = 2*epsilon so that the inversion method does not detect a'(k,k) * as a zero. */ result = alphaCoefficient(store, series, modelCoefficients, k, l)*(1.0+lambda); - if (std::fabs(result) < Expression::epsilon()) { - result = 2*Expression::epsilon(); + if (std::fabs(result) < Expression::Epsilon()) { + result = 2*Expression::Epsilon(); } } else { result = alphaCoefficient(store, series, modelCoefficients, l, k); diff --git a/apps/shared/poincare_helpers.h b/apps/shared/poincare_helpers.h index af2d43fa8..e401f58f5 100644 --- a/apps/shared/poincare_helpers.h +++ b/apps/shared/poincare_helpers.h @@ -48,7 +48,7 @@ template inline T ApproximateToScalar(const char * text, Poincare::Context & context) { Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); Poincare::Preferences::ComplexFormat complexFormat = Poincare::Expression::UpdatedComplexFormatWithTextInput(preferences->complexFormat(), text); - return Poincare::Expression::approximateToScalar(text, context, complexFormat, preferences->angleUnit()); + return Poincare::Expression::ApproximateToScalar(text, context, complexFormat, preferences->angleUnit()); } inline Poincare::Expression ParseAndSimplify(const char * text, Poincare::Context & context) { diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 9fc2dd62a..4832cc711 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -99,7 +99,7 @@ class Expression : public TreeHandle { friend class SymbolNode; public: - static bool isExpression() { return true; } + static bool IsExpression() { return true; } /* Constructor & Destructor */ Expression() : TreeHandle() {} @@ -109,9 +109,9 @@ public: /* Circuit breaker */ typedef bool (*CircuitBreaker)(); - static void setCircuitBreaker(CircuitBreaker cb); - static bool shouldStopProcessing(); - static void setInterruption(bool interrupt); + static void SetCircuitBreaker(CircuitBreaker cb); + static bool ShouldStopProcessing(); + static void SetInterruption(bool interrupt); /* Hierarchy */ Expression childAtIndex(int i) const; @@ -196,10 +196,10 @@ public: /* Approximation Helper */ // These methods reset the sApproximationEncounteredComplex flag. They should not be use to implement node approximation - template static U epsilon(); + template static U Epsilon(); template Expression approximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; template U approximateToScalar(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; - template static U approximateToScalar(const char * text, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + template static U ApproximateToScalar(const char * text, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); template U approximateWithValueForSymbol(const char * symbol, U x, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; /* Expression roots/extrema solver */ struct Coordinate2D { @@ -247,7 +247,7 @@ protected: * ie, you can write: 'Rational a(2); AbsoluteValue b(a);' * */ - assert(T::isExpression()); + assert(T::IsExpression()); static_assert(sizeof(T) == sizeof(Expression), "Size mismatch"); return *reinterpret_cast(const_cast(this)); } @@ -309,9 +309,9 @@ private: int defaultGetPolynomialCoefficients(Context & context, const char * symbol, Expression expression[]) const; /* Builder */ - static bool isZero(const Expression e); - static bool isOne(const Expression e); - static bool isMinusOne(const Expression e); + static bool IsZero(const Expression e); + static bool IsOne(const Expression e); + static bool IsMinusOne(const Expression e); static Expression CreateComplexExpression(Expression ra, Expression tb, Preferences::ComplexFormat complexFormat, bool undefined, bool isZeroRa, bool isOneRa, bool isZeroTb, bool isOneTb, bool isNegativeRa, bool isNegativeTb); /* Expression roots/extrema solver*/ diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index e3b97bf27..9111efbec 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -50,11 +50,11 @@ Expression AbsoluteValue::shallowReduce(Context & context, Preferences::ComplexF Expression c = childAtIndex(0); if (c.isReal(context)) { float app = c.node()->approximate(float(), context, angleUnit).toScalar(); - if (!std::isnan(app) && app >= Expression::epsilon()) { + if (!std::isnan(app) && app >= Expression::Epsilon()) { // abs(a) = a with a > 0 replaceWithInPlace(c); return c; - } else if (!std::isnan(app) && app <= -Expression::epsilon()) { + } else if (!std::isnan(app) && app <= -Expression::Epsilon()) { // abs(a) = -a with a < 0 Multiplication m(Rational(-1), c); replaceWithInPlace(m); diff --git a/poincare/src/approximation_helper.cpp b/poincare/src/approximation_helper.cpp index d0f22e9f8..e0dfb7387 100644 --- a/poincare/src/approximation_helper.cpp +++ b/poincare/src/approximation_helper.cpp @@ -16,7 +16,7 @@ template T absMod(T a, T b) { template std::complex ApproximationHelper::TruncateRealOrImaginaryPartAccordingToArgument(std::complex c) { T arg = std::arg(c); - T precision = 10*Expression::epsilon(); + T precision = 10*Expression::Epsilon(); if (absMod(arg, (T)M_PI) <= precision) { c.imag(0); } diff --git a/poincare/src/complex_argument.cpp b/poincare/src/complex_argument.cpp index c4c6d9b0d..10ce8c9d3 100644 --- a/poincare/src/complex_argument.cpp +++ b/poincare/src/complex_argument.cpp @@ -49,12 +49,12 @@ Expression ComplexArgument::shallowReduce(Context & context, Preferences::Comple bool real = c.isReal(context); if (real) { float app = c.node()->approximate(float(), context, angleUnit).toScalar(); - if (!std::isnan(app) && app >= Expression::epsilon()) { + if (!std::isnan(app) && app >= Expression::Epsilon()) { // arg(x) = 0 if x > 0 Expression result = Rational(0); replaceWithInPlace(result); return result; - } else if (!std::isnan(app) && app <= -Expression::epsilon()) { + } else if (!std::isnan(app) && app <= -Expression::Epsilon()) { // arg(x) = Pi if x < 0 Expression result = Constant(Ion::Charset::SmallPi); replaceWithInPlace(result); diff --git a/poincare/src/complex_cartesian.cpp b/poincare/src/complex_cartesian.cpp index edcee823e..23de92eab 100644 --- a/poincare/src/complex_cartesian.cpp +++ b/poincare/src/complex_cartesian.cpp @@ -58,7 +58,7 @@ Expression ComplexCartesian::shallowBeautify(Context & context, Preferences::Com b = oppositeB.isUninitialized() ? b : oppositeB; Expression e = Expression::CreateComplexExpression(a, b, Preferences::ComplexFormat::Cartesian, a.isUndefined() || b.isUndefined(), - Expression::isZero(a), Expression::isOne(a), Expression::isZero(b), Expression::isOne(b), + Expression::IsZero(a), Expression::IsOne(a), Expression::IsZero(b), Expression::IsOne(b), !oppositeA.isUninitialized(), !oppositeB.isUninitialized() ); @@ -357,7 +357,7 @@ ComplexCartesian ComplexCartesian::power(ComplexCartesian & other, Context & con ComplexCartesian ComplexCartesian::interruptComputationIfManyNodes() { if (numberOfDescendants(true) > k_maxNumberOfNodesBeforeInterrupting) { - Expression::setInterruption(true); + Expression::SetInterruption(true); return ComplexCartesian(Undefined(), Undefined()); } return *this; diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 0238a0327..ed3801e07 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -45,11 +45,11 @@ Expression Expression::ExpressionFromAddress(const void * address, size_t size) static Expression::CircuitBreaker sCircuitBreaker = nullptr; static bool sSimplificationHasBeenInterrupted = false; -void Expression::setCircuitBreaker(CircuitBreaker cb) { +void Expression::SetCircuitBreaker(CircuitBreaker cb) { sCircuitBreaker = cb; } -bool Expression::shouldStopProcessing() { +bool Expression::ShouldStopProcessing() { if (sCircuitBreaker == nullptr) { return false; } @@ -60,7 +60,7 @@ bool Expression::shouldStopProcessing() { return false; } -void Expression::setInterruption(bool interrupt) { +void Expression::SetInterruption(bool interrupt) { sSimplificationHasBeenInterrupted = interrupt; } @@ -474,7 +474,7 @@ void Expression::simplifyAndApproximate(Expression * simplifiedExpression, Expre bool tbIsNegative = false; makePositive(&ra, &raIsNegative); makePositive(&tb, &tbIsNegative); - *simplifiedExpression = CreateComplexExpression(ra, tb, complexFormat, ra.isUndefined() || tb.isUndefined(), isZero(ra), isOne(ra), isZero(tb), isOne(tb), raIsNegative, tbIsNegative); + *simplifiedExpression = CreateComplexExpression(ra, tb, complexFormat, ra.isUndefined() || tb.isUndefined(), IsZero(ra), IsOne(ra), IsZero(tb), IsOne(tb), raIsNegative, tbIsNegative); } else { /* Case 2: The reduced expression has a complex component that could not * be bubbled up. */ @@ -575,7 +575,7 @@ U Expression::approximateToScalar(Context& context, Preferences::ComplexFormat c } template -U Expression::approximateToScalar(const char * text, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +U Expression::ApproximateToScalar(const char * text, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { Expression exp = ParseAndSimplify(text, context, complexFormat, angleUnit); assert(!exp.isUninitialized()); return exp.approximateToScalar(context, complexFormat, angleUnit); @@ -589,20 +589,20 @@ U Expression::approximateWithValueForSymbol(const char * symbol, U x, Context & } template -U Expression::epsilon() { +U Expression::Epsilon() { static U epsilon = sizeof(U) == sizeof(double) ? 1E-15 : 1E-7f; return epsilon; } /* Builder */ -bool Expression::isZero(const Expression e) { +bool Expression::IsZero(const Expression e) { return e.type() == ExpressionNode::Type::Rational && static_cast(e).isZero(); } -bool Expression::isOne(const Expression e) { +bool Expression::IsOne(const Expression e) { return e.type() == ExpressionNode::Type::Rational && static_cast(e).isOne(); } -bool Expression::isMinusOne(const Expression e) { +bool Expression::IsMinusOne(const Expression e) { return e.type() == ExpressionNode::Type::Rational && static_cast(e).isMinusOne(); } @@ -996,8 +996,8 @@ double Expression::brentRoot(const char * symbol, double ax, double bx, double p return NAN; } -template float Expression::epsilon(); -template double Expression::epsilon(); +template float Expression::Epsilon(); +template double Expression::Epsilon(); template Expression Expression::approximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; template Expression Expression::approximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; @@ -1005,8 +1005,8 @@ template Expression Expression::approximate(Context& context, Preference template float Expression::approximateToScalar(Context& context, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) const; template double Expression::approximateToScalar(Context& context, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) const; -template float Expression::approximateToScalar(const char * text, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); -template double Expression::approximateToScalar(const char * text, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); +template float Expression::ApproximateToScalar(const char * text, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); +template double Expression::ApproximateToScalar(const char * text, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); template Evaluation Expression::approximateToEvaluation(Context& context, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) const; template Evaluation Expression::approximateToEvaluation(Context& context, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) const; diff --git a/poincare/src/expression_node.cpp b/poincare/src/expression_node.cpp index 73e7c3417..476cc2e4f 100644 --- a/poincare/src/expression_node.cpp +++ b/poincare/src/expression_node.cpp @@ -74,14 +74,14 @@ float ExpressionNode::characteristicXRange(Context & context, Preferences::Angle int ExpressionNode::SimplificationOrder(const ExpressionNode * e1, const ExpressionNode * e2, bool ascending, bool canBeInterrupted) { if (e1->type() > e2->type()) { - if (canBeInterrupted && Expression::shouldStopProcessing()) { + if (canBeInterrupted && Expression::ShouldStopProcessing()) { return 1; } return -(e2->simplificationOrderGreaterType(e1, ascending, canBeInterrupted)); } else if (e1->type() == e2->type()) { return e1->simplificationOrderSameType(e2, ascending, canBeInterrupted); } else { - if (canBeInterrupted && Expression::shouldStopProcessing()) { + if (canBeInterrupted && Expression::ShouldStopProcessing()) { return -1; } return e1->simplificationOrderGreaterType(e2, ascending, canBeInterrupted); diff --git a/poincare/src/integral.cpp b/poincare/src/integral.cpp index 187bf27cf..bb5be5305 100644 --- a/poincare/src/integral.cpp +++ b/poincare/src/integral.cpp @@ -184,7 +184,7 @@ IntegralNode::DetailedResult IntegralNode::kronrodGaussQuadrature(T a, T b, C template T IntegralNode::adaptiveQuadrature(T a, T b, T eps, int numberOfIterations, Context & context, Preferences::AngleUnit angleUnit) const { - if (Integral::shouldStopProcessing()) { + if (Expression::ShouldStopProcessing()) { return NAN; } DetailedResult quadKG = kronrodGaussQuadrature(a, b, context, angleUnit); diff --git a/poincare/src/matrix.cpp b/poincare/src/matrix.cpp index 6d5bd5398..6a88201cf 100644 --- a/poincare/src/matrix.cpp +++ b/poincare/src/matrix.cpp @@ -147,7 +147,7 @@ int Matrix::ArrayInverse(T * array, int numberOfRows, int numberOfColumns) { ArrayRowCanonize(operands, dim, 2*dim); // Check inversibility for (int i = 0; i < dim; i++) { - if (std::abs(operands[i*2*dim+i] - (T)1.0) > Expression::epsilon()) { + if (std::abs(operands[i*2*dim+i] - (T)1.0) > Expression::Epsilon()) { return -2; } } @@ -160,7 +160,7 @@ int Matrix::ArrayInverse(T * array, int numberOfRows, int numberOfColumns) { } Matrix Matrix::rowCanonize(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, Multiplication determinant) { - Expression::setInterruption(false); + Expression::SetInterruption(false); // The matrix children have to be reduced to be able to spot 0 deepReduceChildren(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); @@ -230,7 +230,7 @@ void Matrix::ArrayRowCanonize(T * array, int numberOfRows, int numberOfColumns, while (h < numberOfRows && k < numberOfColumns) { // Find the first non-null pivot int iPivot = h; - while (iPivot < numberOfRows && std::abs(array[iPivot*numberOfColumns+k]) < Expression::epsilon()) { + while (iPivot < numberOfRows && std::abs(array[iPivot*numberOfColumns+k]) < Expression::Epsilon()) { iPivot++; } if (iPivot == numberOfRows) { diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index d58c6bf2d..e3a397372 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -28,7 +28,7 @@ namespace Poincare { // Properties ExpressionNode::Sign PowerNode::sign(Context * context) const { - if (Expression::shouldStopProcessing()) { + if (Expression::ShouldStopProcessing()) { return Sign::Unknown; } if (childAtIndex(0)->sign(context) == Sign::Positive && childAtIndex(1)->sign(context) != Sign::Unknown) { @@ -221,7 +221,7 @@ template MatrixComplex PowerNode::computeOnMatrixAndComplex(const MatrixComplex result = MatrixComplex::createIdentity(m.numberOfRows()); // TODO: implement a quick exponentiation for (int k = 0; k < (int)power; k++) { - if (Expression::shouldStopProcessing()) { + if (Expression::ShouldStopProcessing()) { return MatrixComplex::Undefined(); } result = MultiplicationNode::computeOnMatrices(result, m); diff --git a/poincare/src/sequence.cpp b/poincare/src/sequence.cpp index 5e3748ac6..33eebc3d6 100644 --- a/poincare/src/sequence.cpp +++ b/poincare/src/sequence.cpp @@ -31,7 +31,7 @@ Evaluation SequenceNode::templatedApproximate(Context& context, Preferences:: VariableContext nContext = VariableContext(static_cast(childAtIndex(1))->name(), &context); Evaluation result = Complex((T)emptySequenceValue()); for (int i = (int)start; i <= (int)end; i++) { - if (Expression::shouldStopProcessing()) { + if (Expression::ShouldStopProcessing()) { return Complex::Undefined(); } nContext.setApproximationForVariable((T)i); diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index 7b733528d..35bb87b2c 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -87,7 +87,7 @@ Expression Store::shallowReduce(Context & context, Preferences::ComplexFormat co e = reducedE; } // Restore the previous interruption flag - setInterruption(interruptedSimplification); + SetInterruption(interruptedSimplification); replaceWithInPlace(e); return e; diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 07c761684..d27aa2530 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -455,7 +455,7 @@ Expression Trigonometry::table(const Expression e, ExpressionNode::Type type, Co } for (int i = 0; i < k_numberOfEntries; i++) { float inputValue = cheatTable[i][inputIndex].value; - if (std::isnan(inputValue) || std::fabs(inputValue-eValue) > Expression::epsilon()) { + if (std::isnan(inputValue) || std::fabs(inputValue-eValue) > Expression::Epsilon()) { continue; } // Our given expression approximation matches a table entry, we check that both expressions are identical @@ -502,8 +502,8 @@ T Trigonometry::RoundToMeaningfulDigits(T result, T input) { * have sin(pi) ~ 0 and sin(1E-15)=1E-15. * We can't do that for all evaluation as the user can operate on values as * small as 1E-308 (in double) and most results still be correct. */ - if (input == 0.0 || std::fabs(result/input) <= Expression::epsilon()) { - T precision = 10*Expression::epsilon(); + if (input == 0.0 || std::fabs(result/input) <= Expression::Epsilon()) { + T precision = 10*Expression::Epsilon(); result = std::round(result/precision)*precision; } return result; diff --git a/poincare/test/helper.cpp b/poincare/test/helper.cpp index 1674a519b..5b8340e85 100644 --- a/poincare/test/helper.cpp +++ b/poincare/test/helper.cpp @@ -166,7 +166,7 @@ template void assert_parsed_expression_approximates_with_value_for_symbol(Expression expression, const char * symbol, T value, T approximation, Poincare::Preferences::ComplexFormat complexFormat, Poincare::Preferences::AngleUnit angleUnit) { Shared::GlobalContext globalContext; T result = expression.approximateWithValueForSymbol(symbol, value, globalContext, complexFormat, angleUnit); - quiz_assert((std::isnan(result) && std::isnan(approximation)) || std::fabs(result - approximation) < 10.0*Expression::epsilon()); + quiz_assert((std::isnan(result) && std::isnan(approximation)) || std::fabs(result - approximation) < 10.0*Expression::Epsilon()); } void assert_parsed_expression_simplify_to(const char * expression, const char * simplifiedExpression, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) { From 335264e944ac489478e232ae6c49b4d8454d3625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 3 Jan 2019 17:06:12 +0100 Subject: [PATCH 193/373] [apps] Typo: drawAxes is now drawAxis --- apps/probability/law_curve_view.cpp | 2 +- apps/regression/graph_view.cpp | 4 ++-- apps/shared/curve_view.cpp | 2 +- apps/shared/curve_view.h | 2 +- apps/shared/function_graph_view.cpp | 4 ++-- apps/shared/storage_function_graph_view.cpp | 4 ++-- apps/statistics/histogram_view.cpp | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/probability/law_curve_view.cpp b/apps/probability/law_curve_view.cpp index 6e672dc55..f2d34f077 100644 --- a/apps/probability/law_curve_view.cpp +++ b/apps/probability/law_curve_view.cpp @@ -17,7 +17,7 @@ void LawCurveView::drawRect(KDContext * ctx, KDRect rect) const { float lowerBound = m_calculation->lowerBound(); float upperBound = m_calculation->upperBound(); ctx->fillRect(bounds(), k_backgroundColor); - drawAxes(ctx, rect, Axis::Horizontal); + drawAxis(ctx, rect, Axis::Horizontal); drawLabels(ctx, rect, Axis::Horizontal, false, false, false, 0, k_backgroundColor); if (m_law->type() == Law::Type::Normal) { // Special case for the normal law, which has always the same curve diff --git a/apps/regression/graph_view.cpp b/apps/regression/graph_view.cpp index a314f40f6..130f47a8b 100644 --- a/apps/regression/graph_view.cpp +++ b/apps/regression/graph_view.cpp @@ -20,8 +20,8 @@ GraphView::GraphView(Store * store, CurveViewCursor * cursor, BannerView * banne void GraphView::drawRect(KDContext * ctx, KDRect rect) const { ctx->fillRect(rect, KDColorWhite); drawGrid(ctx, rect); - drawAxes(ctx, rect, Axis::Horizontal); - drawAxes(ctx, rect, Axis::Vertical); + drawAxis(ctx, rect, Axis::Horizontal); + drawAxis(ctx, rect, Axis::Vertical); drawLabels(ctx, rect, Axis::Horizontal, true); drawLabels(ctx, rect, Axis::Vertical, true); for (int series = 0; series < Store::k_numberOfSeries; series++) { diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index 9a806744d..5106584e8 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -388,7 +388,7 @@ void CurveView::drawGrid(KDContext * ctx, KDRect rect) const { drawGridLines(ctx, rect, Axis::Vertical, m_curveViewRange->yGridUnit(), Palette::GreyWhite); } -void CurveView::drawAxes(KDContext * ctx, KDRect rect, Axis axis) const { +void CurveView::drawAxis(KDContext * ctx, KDRect rect, Axis axis) const { drawLine(ctx, rect, axis, 0.0f, KDColorBlack, 1); } diff --git a/apps/shared/curve_view.h b/apps/shared/curve_view.h index 4f28eb480..7467251d8 100644 --- a/apps/shared/curve_view.h +++ b/apps/shared/curve_view.h @@ -61,7 +61,7 @@ protected: void drawDot(KDContext * ctx, KDRect rect, float x, float y, KDColor color, bool oversize = false) const; void drawGridLines(KDContext * ctx, KDRect rect, Axis axis, float step, KDColor color) const; void drawGrid(KDContext * ctx, KDRect rect) const; - void drawAxes(KDContext * ctx, KDRect rect, Axis axis) const; + void drawAxis(KDContext * ctx, KDRect rect, Axis axis) const; void drawCurve(KDContext * ctx, KDRect rect, EvaluateModelWithParameter evaluation, void * model, void * context, KDColor color, bool colorUnderCurve = false, float colorLowerBound = 0.0f, float colorUpperBound = 0.0f, bool continuously = false) const; void drawHistogram(KDContext * ctx, KDRect rect, EvaluateModelWithParameter evaluation, void * model, void * context, float firstBarAbscissa, float barWidth, bool fillBar, KDColor defaultColor, KDColor highlightColor, float highlightLowerBound = INFINITY, float highlightUpperBound = -INFINITY) const; diff --git a/apps/shared/function_graph_view.cpp b/apps/shared/function_graph_view.cpp index 78592d635..10a88b912 100644 --- a/apps/shared/function_graph_view.cpp +++ b/apps/shared/function_graph_view.cpp @@ -22,8 +22,8 @@ FunctionGraphView::FunctionGraphView(InteractiveCurveViewRange * graphRange, void FunctionGraphView::drawRect(KDContext * ctx, KDRect rect) const { ctx->fillRect(rect, KDColorWhite); drawGrid(ctx, rect); - drawAxes(ctx, rect, Axis::Horizontal); - drawAxes(ctx, rect, Axis::Vertical); + drawAxis(ctx, rect, Axis::Horizontal); + drawAxis(ctx, rect, Axis::Vertical); drawLabels(ctx, rect, Axis::Horizontal, true); drawLabels(ctx, rect, Axis::Vertical, true); } diff --git a/apps/shared/storage_function_graph_view.cpp b/apps/shared/storage_function_graph_view.cpp index 4c517b4d2..4e698c9bb 100644 --- a/apps/shared/storage_function_graph_view.cpp +++ b/apps/shared/storage_function_graph_view.cpp @@ -22,8 +22,8 @@ StorageFunctionGraphView::StorageFunctionGraphView(InteractiveCurveViewRange * g void StorageFunctionGraphView::drawRect(KDContext * ctx, KDRect rect) const { ctx->fillRect(rect, KDColorWhite); drawGrid(ctx, rect); - drawAxes(ctx, rect, Axis::Horizontal); - drawAxes(ctx, rect, Axis::Vertical); + drawAxis(ctx, rect, Axis::Horizontal); + drawAxis(ctx, rect, Axis::Vertical); drawLabels(ctx, rect, Axis::Horizontal, true); drawLabels(ctx, rect, Axis::Vertical, true); } diff --git a/apps/statistics/histogram_view.cpp b/apps/statistics/histogram_view.cpp index c50972cbc..94b681aa2 100644 --- a/apps/statistics/histogram_view.cpp +++ b/apps/statistics/histogram_view.cpp @@ -41,7 +41,7 @@ void HistogramView::reloadSelectedBar() { void HistogramView::drawRect(KDContext * ctx, KDRect rect) const { m_controller->setCurrentDrawnSeries(m_series); ctx->fillRect(rect, KDColorWhite); - drawAxes(ctx, rect, Axis::Horizontal); + drawAxis(ctx, rect, Axis::Horizontal); drawLabels(ctx, rect, Axis::Horizontal, false, !m_displayLabels); /* We memoize the total size to avoid recomputing it in double precision at * every call to EvaluateHistogramAtAbscissa() */ From 69105572ef2ac662f9eb59d12c1cd894726b98c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 3 Jan 2019 17:12:15 +0100 Subject: [PATCH 194/373] [apps] Change axes drawing order in curve views --- apps/regression/graph_view.cpp | 6 ++---- apps/shared/curve_view.cpp | 10 ++++++++++ apps/shared/curve_view.h | 2 ++ apps/shared/function_graph_view.cpp | 6 ++---- apps/shared/storage_function_graph_view.cpp | 6 ++---- 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/apps/regression/graph_view.cpp b/apps/regression/graph_view.cpp index 130f47a8b..b08575c6c 100644 --- a/apps/regression/graph_view.cpp +++ b/apps/regression/graph_view.cpp @@ -20,10 +20,8 @@ GraphView::GraphView(Store * store, CurveViewCursor * cursor, BannerView * banne void GraphView::drawRect(KDContext * ctx, KDRect rect) const { ctx->fillRect(rect, KDColorWhite); drawGrid(ctx, rect); - drawAxis(ctx, rect, Axis::Horizontal); - drawAxis(ctx, rect, Axis::Vertical); - drawLabels(ctx, rect, Axis::Horizontal, true); - drawLabels(ctx, rect, Axis::Vertical, true); + drawAxes(ctx, rect); + simpleDrawBothAxesLabels(ctx, rect); for (int series = 0; series < Store::k_numberOfSeries; series++) { if (!m_store->seriesIsEmpty(series)) { KDColor color = Palette::DataColor[series]; diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index 5106584e8..31cd77b6d 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -185,6 +185,11 @@ enum class FloatingPosition : uint8_t { Max }; +void CurveView::simpleDrawBothAxesLabels(KDContext * ctx, KDRect rect) const { + drawLabels(ctx, rect, Axis::Vertical, true); + drawLabels(ctx, rect, Axis::Horizontal, true); +} + void CurveView::drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOrigin, bool graduationOnly, bool fixCoordinate, KDCoordinate fixedCoordinate, KDColor backgroundColor) const { int numberLabels = numberOfLabels(axis); if (numberLabels <= 1) { @@ -388,6 +393,11 @@ void CurveView::drawGrid(KDContext * ctx, KDRect rect) const { drawGridLines(ctx, rect, Axis::Vertical, m_curveViewRange->yGridUnit(), Palette::GreyWhite); } +void CurveView::drawAxes(KDContext * ctx, KDRect rect) const { + drawAxis(ctx, rect, Axis::Vertical); + drawAxis(ctx, rect, Axis::Horizontal); +} + void CurveView::drawAxis(KDContext * ctx, KDRect rect, Axis axis) const { drawLine(ctx, rect, axis, 0.0f, KDColorBlack, 1); } diff --git a/apps/shared/curve_view.h b/apps/shared/curve_view.h index 7467251d8..afd375cb9 100644 --- a/apps/shared/curve_view.h +++ b/apps/shared/curve_view.h @@ -61,11 +61,13 @@ protected: void drawDot(KDContext * ctx, KDRect rect, float x, float y, KDColor color, bool oversize = false) const; void drawGridLines(KDContext * ctx, KDRect rect, Axis axis, float step, KDColor color) const; void drawGrid(KDContext * ctx, KDRect rect) const; + void drawAxes(KDContext * ctx, KDRect rect) const; void drawAxis(KDContext * ctx, KDRect rect, Axis axis) const; void drawCurve(KDContext * ctx, KDRect rect, EvaluateModelWithParameter evaluation, void * model, void * context, KDColor color, bool colorUnderCurve = false, float colorLowerBound = 0.0f, float colorUpperBound = 0.0f, bool continuously = false) const; void drawHistogram(KDContext * ctx, KDRect rect, EvaluateModelWithParameter evaluation, void * model, void * context, float firstBarAbscissa, float barWidth, bool fillBar, KDColor defaultColor, KDColor highlightColor, float highlightLowerBound = INFINITY, float highlightUpperBound = -INFINITY) const; void computeLabels(Axis axis); + void simpleDrawBothAxesLabels(KDContext * ctx, KDRect rect) const; void drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOrigin, bool graduationOnly = false, bool fixCoordinate = false, KDCoordinate fixedCoordinate = 0, KDColor backgroundColor = KDColorWhite) const; View * m_bannerView; CurveViewCursor * m_curveViewCursor; diff --git a/apps/shared/function_graph_view.cpp b/apps/shared/function_graph_view.cpp index 10a88b912..a7a65bad7 100644 --- a/apps/shared/function_graph_view.cpp +++ b/apps/shared/function_graph_view.cpp @@ -22,10 +22,8 @@ FunctionGraphView::FunctionGraphView(InteractiveCurveViewRange * graphRange, void FunctionGraphView::drawRect(KDContext * ctx, KDRect rect) const { ctx->fillRect(rect, KDColorWhite); drawGrid(ctx, rect); - drawAxis(ctx, rect, Axis::Horizontal); - drawAxis(ctx, rect, Axis::Vertical); - drawLabels(ctx, rect, Axis::Horizontal, true); - drawLabels(ctx, rect, Axis::Vertical, true); + drawAxes(ctx, rect); + simpleDrawBothAxesLabels(ctx, rect); } void FunctionGraphView::setContext(Context * context) { diff --git a/apps/shared/storage_function_graph_view.cpp b/apps/shared/storage_function_graph_view.cpp index 4e698c9bb..91e0fe8cd 100644 --- a/apps/shared/storage_function_graph_view.cpp +++ b/apps/shared/storage_function_graph_view.cpp @@ -22,10 +22,8 @@ StorageFunctionGraphView::StorageFunctionGraphView(InteractiveCurveViewRange * g void StorageFunctionGraphView::drawRect(KDContext * ctx, KDRect rect) const { ctx->fillRect(rect, KDColorWhite); drawGrid(ctx, rect); - drawAxis(ctx, rect, Axis::Horizontal); - drawAxis(ctx, rect, Axis::Vertical); - drawLabels(ctx, rect, Axis::Horizontal, true); - drawLabels(ctx, rect, Axis::Vertical, true); + drawAxes(ctx, rect); + simpleDrawBothAxesLabels(ctx, rect); } void StorageFunctionGraphView::setContext(Context * context) { From 5d7a7c73717eb09d51267f72a069e1f416bc62ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 3 Jan 2019 17:16:59 +0100 Subject: [PATCH 195/373] [apps/curve_view] Make drawGridLines private --- apps/shared/curve_view.cpp | 42 +++++++++++++++++++------------------- apps/shared/curve_view.h | 2 +- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index 31cd77b6d..bdd2c6833 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -92,6 +92,27 @@ float CurveView::samplingRatio() const { return 1.1f; } +void CurveView::drawGridLines(KDContext * ctx, KDRect rect, Axis axis, float step, KDColor color) const { + float rectMin = pixelToFloat(Axis::Horizontal, rect.left()); + float rectMax = pixelToFloat(Axis::Horizontal, rect.right()); + if (axis == Axis::Vertical) { + rectMax = pixelToFloat(Axis::Vertical, rect.top()); + rectMin = pixelToFloat(Axis::Vertical, rect.bottom()); + } + float start = step * ((int)(min(axis)/step)); + Axis otherAxis = (axis == Axis::Horizontal) ? Axis::Vertical : Axis::Horizontal; + for (float x = start; x < max(axis); x+= step) { + /* When |start| >> step, start + step = start. In that case, quit the + * infinite loop. */ + if (x == x-step || x == x+step) { + return; + } + if (rectMin <= x && x <= rectMax) { + drawLine(ctx, rect, otherAxis, x, color); + } + } +} + float CurveView::min(Axis axis) const { assert(axis == Axis::Horizontal || axis == Axis::Vertical); return (axis == Axis::Horizontal ? m_curveViewRange->xMin(): m_curveViewRange->yMin()); @@ -367,27 +388,6 @@ void CurveView::drawDot(KDContext * ctx, KDRect rect, float x, float y, KDColor } } -void CurveView::drawGridLines(KDContext * ctx, KDRect rect, Axis axis, float step, KDColor color) const { - float rectMin = pixelToFloat(Axis::Horizontal, rect.left()); - float rectMax = pixelToFloat(Axis::Horizontal, rect.right()); - if (axis == Axis::Vertical) { - rectMax = pixelToFloat(Axis::Vertical, rect.top()); - rectMin = pixelToFloat(Axis::Vertical, rect.bottom()); - } - float start = step*((int)(min(axis)/step)); - Axis otherAxis = (axis == Axis::Horizontal) ? Axis::Vertical : Axis::Horizontal; - for (float x = start; x < max(axis); x+= step) { - /* When |start| >> step, start + step = start. In that case, quit the - * infinite loop. */ - if (x == x-step || x == x+step) { - return; - } - if (rectMin <= x && x <= rectMax) { - drawLine(ctx, rect, otherAxis, x, color); - } - } -} - void CurveView::drawGrid(KDContext * ctx, KDRect rect) const { drawGridLines(ctx, rect, Axis::Horizontal, m_curveViewRange->xGridUnit(), Palette::GreyWhite); drawGridLines(ctx, rect, Axis::Vertical, m_curveViewRange->yGridUnit(), Palette::GreyWhite); diff --git a/apps/shared/curve_view.h b/apps/shared/curve_view.h index afd375cb9..0fd40af52 100644 --- a/apps/shared/curve_view.h +++ b/apps/shared/curve_view.h @@ -59,7 +59,6 @@ protected: float coordinate, float lowerBound, float upperBound, KDColor color, KDCoordinate thickness = 1) const; void drawDot(KDContext * ctx, KDRect rect, float x, float y, KDColor color, bool oversize = false) const; - void drawGridLines(KDContext * ctx, KDRect rect, Axis axis, float step, KDColor color) const; void drawGrid(KDContext * ctx, KDRect rect) const; void drawAxes(KDContext * ctx, KDRect rect) const; void drawAxis(KDContext * ctx, KDRect rect, Axis axis) const; @@ -73,6 +72,7 @@ protected: CurveViewCursor * m_curveViewCursor; private: static constexpr const KDFont * k_font = KDFont::SmallFont; + void drawGridLines(KDContext * ctx, KDRect rect, Axis axis, float step, KDColor color) const; /* The window bounds are deduced from the model bounds but also take into account a margin (computed with k_marginFactor) */ float min(Axis axis) const; From 718160b96478525362a9b750ffc2433f1db957cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 3 Jan 2019 17:36:52 +0100 Subject: [PATCH 196/373] [apps] Draw grid lines in bold and light colors in curve_view --- apps/shared/curve_view.cpp | 13 +++++++++---- apps/shared/curve_view.h | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index bdd2c6833..4a27e5014 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -92,7 +92,7 @@ float CurveView::samplingRatio() const { return 1.1f; } -void CurveView::drawGridLines(KDContext * ctx, KDRect rect, Axis axis, float step, KDColor color) const { +void CurveView::drawGridLines(KDContext * ctx, KDRect rect, Axis axis, float step, KDColor boldColor, KDColor lightColor) const { float rectMin = pixelToFloat(Axis::Horizontal, rect.left()); float rectMax = pixelToFloat(Axis::Horizontal, rect.right()); if (axis == Axis::Vertical) { @@ -100,6 +100,8 @@ void CurveView::drawGridLines(KDContext * ctx, KDRect rect, Axis axis, float ste rectMin = pixelToFloat(Axis::Vertical, rect.bottom()); } float start = step * ((int)(min(axis)/step)); + float boldStart = 2*step * ((int)(min(axis)/(2*step))); + bool drawBold = std::fabs(start - boldStart) < FLT_EPSILON; Axis otherAxis = (axis == Axis::Horizontal) ? Axis::Vertical : Axis::Horizontal; for (float x = start; x < max(axis); x+= step) { /* When |start| >> step, start + step = start. In that case, quit the @@ -108,8 +110,9 @@ void CurveView::drawGridLines(KDContext * ctx, KDRect rect, Axis axis, float ste return; } if (rectMin <= x && x <= rectMax) { - drawLine(ctx, rect, otherAxis, x, color); + drawLine(ctx, rect, otherAxis, x, drawBold ? boldColor : lightColor); } + drawBold = !drawBold; } } @@ -389,8 +392,10 @@ void CurveView::drawDot(KDContext * ctx, KDRect rect, float x, float y, KDColor } void CurveView::drawGrid(KDContext * ctx, KDRect rect) const { - drawGridLines(ctx, rect, Axis::Horizontal, m_curveViewRange->xGridUnit(), Palette::GreyWhite); - drawGridLines(ctx, rect, Axis::Vertical, m_curveViewRange->yGridUnit(), Palette::GreyWhite); + KDColor boldColor = Palette::GreyMiddle; + KDColor lightColor = Palette::GreyWhite; + drawGridLines(ctx, rect, Axis::Horizontal, m_curveViewRange->xGridUnit(), boldColor, lightColor); + drawGridLines(ctx, rect, Axis::Vertical, m_curveViewRange->yGridUnit(), boldColor, lightColor); } void CurveView::drawAxes(KDContext * ctx, KDRect rect) const { diff --git a/apps/shared/curve_view.h b/apps/shared/curve_view.h index 0fd40af52..a3093ec21 100644 --- a/apps/shared/curve_view.h +++ b/apps/shared/curve_view.h @@ -72,7 +72,7 @@ protected: CurveViewCursor * m_curveViewCursor; private: static constexpr const KDFont * k_font = KDFont::SmallFont; - void drawGridLines(KDContext * ctx, KDRect rect, Axis axis, float step, KDColor color) const; + void drawGridLines(KDContext * ctx, KDRect rect, Axis axis, float step, KDColor boldColor, KDColor lightColor) const; /* The window bounds are deduced from the model bounds but also take into account a margin (computed with k_marginFactor) */ float min(Axis axis) const; From 37117ed7e75a749dc85da7be581f853d777f4b90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 4 Jan 2019 09:56:10 +0100 Subject: [PATCH 197/373] [apps/curve_view] Do not draw extremal Y label if it overlaps X labels --- apps/shared/curve_view.cpp | 46 +++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index 4a27e5014..80dba9713 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -224,20 +224,23 @@ void CurveView::drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOr float horizontalCoordinate = fixCoordinate ? fixedCoordinate : std::round(floatToPixel(Axis::Horizontal, 0.0f)); int viewHeight = bounds().height() - (bannerIsVisible() ? m_bannerView->minimalSizeForOptimalDisplay().height() : 0); - // If the axis is not visible, draw floating labels on the edge of the screen + + /* If the axis is not visible, draw floating labels on the edge of the screen. + * The X axis floating status is needed when drawing both axes labels. */ + FloatingPosition floatingHorizontalLabels = FloatingPosition::None; + if (verticalCoordinate > viewHeight - k_font->glyphSize().height() - k_labelMargin) { + floatingHorizontalLabels = FloatingPosition::Max; + } else if (max(Axis::Vertical) < 0.0f) { + floatingHorizontalLabels = FloatingPosition::Min; + } + FloatingPosition floatingLabels = FloatingPosition::None; if (axis == Axis::Horizontal) { - Axis otherAxis = Axis::Vertical; - if (verticalCoordinate > viewHeight - k_font->glyphSize().height() - k_labelMargin) { - floatingLabels = FloatingPosition::Max; - } else if (max(otherAxis) < 0.0f) { - floatingLabels = FloatingPosition::Min; - } + floatingLabels = floatingHorizontalLabels; } else { - Axis otherAxis = Axis::Horizontal; - if (horizontalCoordinate < k_labelMargin + k_font->glyphSize().width()*3) { // We want do display at least three characters left of the Y axis + if (horizontalCoordinate < k_labelMargin + k_font->glyphSize().width() * 3) { // We want do display at least 3 characters left of the Y axis floatingLabels = FloatingPosition::Min; - } else if (max(otherAxis) < 0.0f) { + } else if (max(Axis::Horizontal) < 0.0f) { floatingLabels = FloatingPosition::Max; } } @@ -251,8 +254,25 @@ void CurveView::drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOr int maxLabelPixelPosition = std::round(floatToPixel(axis, labelStep * std::floor(max(axis)/labelStep))); // Draw the graduations + + int minDrawnLabel = 0; + int maxDrawnLabel = numberLabels; + if (axis == Axis::Vertical) { + /* Do not draw an extremal vertical label if it collides with the horizontal + * labels */ + int horizontalLabelsMargin = k_font->glyphSize().height() * 2; + if (floatingHorizontalLabels == FloatingPosition::Min + && maxLabelPixelPosition < horizontalLabelsMargin) { + maxDrawnLabel--; + } else if (floatingHorizontalLabels == FloatingPosition::Max + && minLabelPixelPosition > viewHeight - horizontalLabelsMargin) + { + minDrawnLabel++; + } + } + if (floatingLabels == FloatingPosition::None) { - for (int i = 0; i < numberLabels; i++) { + for (int i = minDrawnLabel; i < maxDrawnLabel; i++) { int labelPosition = minLabelPixelPosition + (((float)i)/((float)numberLabels-1)) * (maxLabelPixelPosition - minLabelPixelPosition); KDRect graduation = axis == Axis::Horizontal ? KDRect( @@ -274,7 +294,7 @@ void CurveView::drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOr } // Draw the labels - for (int i = 0; i < numberLabels; i++) { + for (int i = minDrawnLabel; i < maxDrawnLabel; i++) { int labelPosition = minLabelPixelPosition + (((float)i)/((float)numberLabels-1)) * (maxLabelPixelPosition - minLabelPixelPosition); char * labelI = label(axis, i); KDSize textSize = k_font->stringSize(labelI); @@ -303,7 +323,7 @@ void CurveView::drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOr xPosition = Ion::Display::Width - textSize.width() - k_labelMargin; } } - KDPoint origin = KDPoint(xPosition, yPosition); + KDPoint origin = KDPoint(xPosition, yPosition); if (rect.intersects(KDRect(origin, textSize))) { ctx->drawString(labelI, origin, k_font, KDColorBlack, backgroundColor); } From 460b49010c4a336e2af0c0612cbea6026aa795ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 4 Jan 2019 10:04:19 +0100 Subject: [PATCH 198/373] [apps/curve_view] Do not draw the 0 label if the axis is floating The 0 is represented by the other axis --- apps/shared/curve_view.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index 80dba9713..3288aae7d 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -301,9 +301,15 @@ void CurveView::drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOr float xPosition = 0.0f; float yPosition = 0.0f; - if (strcmp(labelI, "0") == 0 && shiftOrigin && floatingLabels == FloatingPosition::None) { - xPosition = horizontalCoordinate - k_labelMargin - textSize.width(); - yPosition = verticalCoordinate + k_labelMargin; + if (strcmp(labelI, "0") == 0) { + if (floatingLabels != FloatingPosition::None) { + // Do not draw the zero, it is symbolized by the other axis + continue; + } + if (shiftOrigin && floatingLabels == FloatingPosition::None) { + xPosition = horizontalCoordinate - k_labelMargin - textSize.width(); + yPosition = verticalCoordinate + k_labelMargin; + } } else if (axis == Axis::Horizontal) { xPosition = labelPosition - textSize.width()/2; if (floatingLabels == FloatingPosition::None) { From 4d1114ef63cd119266678018a8b4388e835017a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 4 Jan 2019 10:28:16 +0100 Subject: [PATCH 199/373] [apps/curve_view] Increase numberOfSignificant digits when needed Labels might be rounded to the same value (for example, in Probability, draw a normal law with mu = 100000 and sigma = 0.1), in which case we need to display extremal labels only, with increased number of significant digits. --- apps/shared/curve_view.cpp | 24 ++++++++++++++++-------- apps/shared/curve_view.h | 5 +++-- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index 3288aae7d..e37616915 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -183,7 +183,7 @@ void CurveView::computeLabels(Axis axis) { } /* Label cannot hold more than k_labelBufferSize characters to prevent them - * from overprinting one another.*/ + * from overprinting one another. */ char * labelBuffer = label(axis, i); PrintFloat::convertFloatToText( @@ -194,11 +194,19 @@ void CurveView::computeLabels(Axis axis) { Preferences::PrintFloatMode::Decimal, axis == Axis::Vertical); - if (labelBuffer[0] == 0 && axis == Axis::Horizontal) { - /* Some labels are too big and may overlap their neighbours. We write the - * extrema labels only. */ - computeHorizontalExtremaLabels(); - return; + if (axis == Axis::Horizontal) { + if (labelBuffer[0] == 0) { + /* Some labels are too big and may overlap their neighbours. We write the + * extrema labels only. */ + computeHorizontalExtremaLabels(); + return; + } + if (i > 0 && strcmp(labelBuffer, label(axis, i-1)) == 0) { + /* We need to increase the number if significant digits, otherwise some + * labels are rounded to the same value. */ + computeHorizontalExtremaLabels(true); + return; + } } } } @@ -729,7 +737,7 @@ View * CurveView::subviewAtIndex(int index) { return m_bannerView; } -void CurveView::computeHorizontalExtremaLabels() { +void CurveView::computeHorizontalExtremaLabels(bool increaseNumberOfSignificantDigits) { Axis axis = Axis::Horizontal; int axisLabelsCount = numberOfLabels(axis); float minA = min(axis); @@ -762,7 +770,7 @@ void CurveView::computeHorizontalExtremaLabels() { labelValueAtIndex(axis, i), label(axis, i), k_labelBufferMaxSize, - k_numberSignificantDigits, + increaseNumberOfSignificantDigits ? k_bigNumberSignificantDigits : k_numberSignificantDigits, Preferences::PrintFloatMode::Decimal, false); } diff --git a/apps/shared/curve_view.h b/apps/shared/curve_view.h index a3093ec21..1d745383c 100644 --- a/apps/shared/curve_view.h +++ b/apps/shared/curve_view.h @@ -47,7 +47,8 @@ protected: constexpr static KDCoordinate k_okHorizontalMargin = 10; constexpr static KDCoordinate k_labelGraduationLength = 6; constexpr static int k_numberSignificantDigits = 6; - constexpr static int k_labelBufferMaxSize = 1 + k_numberSignificantDigits + 3 + 3 + 1; // '-' + significant digits + '.' + "E-" + 3 digits + null-terminating char + constexpr static int k_bigNumberSignificantDigits = Constant::LargeNumberOfSignificantDigits; + constexpr static int k_labelBufferMaxSize = 1 + k_bigNumberSignificantDigits + 3 + 3 + 1; // '-' + significant digits + '.' + "E-" + 3 digits + null-terminating char constexpr static int k_maxNumberOfXLabels = CurveViewRange::k_maxNumberOfXGridUnits; constexpr static int k_maxNumberOfYLabels = CurveViewRange::k_maxNumberOfYGridUnits; constexpr static int k_externRectMargin = 2; @@ -98,7 +99,7 @@ private: View * subviewAtIndex(int index) override; /* m_curveViewRange has to be non null but the cursor model, the banner and * cursor views may be nullptr if not needed. */ - void computeHorizontalExtremaLabels(); + void computeHorizontalExtremaLabels(bool increaseNumberOfSignificantDigits = false); float labelValueAtIndex(Axis axis, int i) const; bool bannerIsVisible() const; CurveViewRange * m_curveViewRange; From 17a93886237896ea221186daf0eb27fa450f0d69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 4 Jan 2019 10:44:31 +0100 Subject: [PATCH 200/373] [apps/sequence] Clean GraphController --- apps/sequence/graph/graph_controller.cpp | 28 ------------------------ apps/sequence/graph/graph_controller.h | 16 +++++++------- 2 files changed, 8 insertions(+), 36 deletions(-) diff --git a/apps/sequence/graph/graph_controller.cpp b/apps/sequence/graph/graph_controller.cpp index d16d68e9d..5db89d5a0 100644 --- a/apps/sequence/graph/graph_controller.cpp +++ b/apps/sequence/graph/graph_controller.cpp @@ -25,18 +25,6 @@ I18n::Message GraphController::emptyMessage() { return I18n::Message::NoActivatedSequence; } -TermSumController * GraphController::termSumController() { - return &m_termSumController; -} - -int GraphController::numberOfCurves() const { - return m_sequenceStore->numberOfModels(); -} - -BannerView * GraphController::bannerView() { - return &m_bannerView; -} - bool GraphController::handleEnter() { m_termSumController.setFunction(m_sequenceStore->activeFunctionAtIndex(indexFunctionSelectedByCursor())); return FunctionGraphController::handleEnter(); @@ -69,20 +57,4 @@ double GraphController::defaultCursorAbscissa() { return std::round(Shared::FunctionGraphController::defaultCursorAbscissa()); } -CurveViewRange * GraphController::interactiveCurveViewRange() { - return m_graphRange; -} - -SequenceStore * GraphController::functionStore() const { - return m_sequenceStore; -} - -GraphView * GraphController::functionGraphView() { - return &m_view; -} - -CurveParameterController * GraphController::curveParameterController() { - return &m_curveParameterController; -} - } diff --git a/apps/sequence/graph/graph_controller.h b/apps/sequence/graph/graph_controller.h index 40e7f70d8..b90942074 100644 --- a/apps/sequence/graph/graph_controller.h +++ b/apps/sequence/graph/graph_controller.h @@ -12,25 +12,25 @@ namespace Sequence { -class GraphController : public Shared::FunctionGraphController { +class GraphController final : public Shared::FunctionGraphController { public: GraphController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, SequenceStore * sequenceStore, CurveViewRange * graphRange, Shared::CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * rangeVersion, Poincare::Preferences::AngleUnit * angleUnitVersion, ButtonRowController * header); I18n::Message emptyMessage() override; - TermSumController * termSumController(); + TermSumController * termSumController() { return &m_termSumController; } protected: - int numberOfCurves() const override; + int numberOfCurves() const override { return m_sequenceStore->numberOfModels(); } private: - BannerView * bannerView() override; + BannerView * bannerView() override { return &m_bannerView; } bool handleEnter() override; bool moveCursorHorizontally(int direction) override; double defaultCursorAbscissa() override; - CurveViewRange * interactiveCurveViewRange() override; - SequenceStore * functionStore() const override; - GraphView * functionGraphView() override; + CurveViewRange * interactiveCurveViewRange() override { return m_graphRange; } + SequenceStore * functionStore() const override { return m_sequenceStore; } + GraphView * functionGraphView() override { return &m_view; } View * cursorView() override { return &m_cursorView; } - CurveParameterController * curveParameterController() override; + CurveParameterController * curveParameterController() override { return &m_curveParameterController; } Shared::CursorView m_cursorView; BannerView m_bannerView; GraphView m_view; From 6720ad7b389b2c55b6748f7490814c0e0a8f9a41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 4 Jan 2019 11:09:20 +0100 Subject: [PATCH 201/373] [apps] Rename interestingXRange as interestingXHalfRange --- apps/graph/graph/graph_controller.cpp | 4 ++-- apps/graph/graph/graph_controller.h | 2 +- apps/sequence/graph/curve_view_range.cpp | 2 +- apps/shared/interactive_curve_view_range.cpp | 2 +- apps/shared/interactive_curve_view_range_delegate.cpp | 4 ---- apps/shared/interactive_curve_view_range_delegate.h | 2 +- 6 files changed, 6 insertions(+), 10 deletions(-) diff --git a/apps/graph/graph/graph_controller.cpp b/apps/graph/graph/graph_controller.cpp index c0bb4e0fc..08c4ca80b 100644 --- a/apps/graph/graph/graph_controller.cpp +++ b/apps/graph/graph/graph_controller.cpp @@ -39,7 +39,7 @@ void GraphController::setDisplayDerivativeInBanner(bool displayDerivative) { m_displayDerivativeInBanner = displayDerivative; } -float GraphController::interestingXRange() { +float GraphController::interestingXHalfRange() { float characteristicRange = 0.0f; TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app(); for (int i = 0; i < functionStore()->numberOfActiveFunctions(); i++) { @@ -49,7 +49,7 @@ float GraphController::interestingXRange() { characteristicRange = max(fRange, characteristicRange); } } - return (characteristicRange > 0.0f ? 1.6f*characteristicRange : InteractiveCurveViewRangeDelegate::interestingXRange()); + return (characteristicRange > 0.0f ? 1.6f*characteristicRange : InteractiveCurveViewRangeDelegate::interestingXHalfRange()); } int GraphController::estimatedBannerNumberOfLines() const { diff --git a/apps/graph/graph/graph_controller.h b/apps/graph/graph/graph_controller.h index d14ee8741..bdf5ad861 100644 --- a/apps/graph/graph/graph_controller.h +++ b/apps/graph/graph/graph_controller.h @@ -20,7 +20,7 @@ public: void viewWillAppear() override; bool displayDerivativeInBanner() const; void setDisplayDerivativeInBanner(bool displayDerivative); - float interestingXRange() override; + float interestingXHalfRange() override; private: int estimatedBannerNumberOfLines() const override; void selectFunctionWithCursor(int functionIndex) override; diff --git a/apps/sequence/graph/curve_view_range.cpp b/apps/sequence/graph/curve_view_range.cpp index 9bfa613c0..ff13a3f38 100644 --- a/apps/sequence/graph/curve_view_range.cpp +++ b/apps/sequence/graph/curve_view_range.cpp @@ -78,7 +78,7 @@ void CurveViewRange::setDefault() { if (m_delegate == nullptr) { return; } - m_xMax = m_delegate->interestingXRange(); + m_xMax = m_delegate->interestingXHalfRange(); m_xMin = -k_displayLeftMarginRatio*m_xMax; m_xGridUnit = computeGridUnit(Axis::X, m_xMax - m_xMin); setYAuto(true); diff --git a/apps/shared/interactive_curve_view_range.cpp b/apps/shared/interactive_curve_view_range.cpp index 82e1642f5..41eee5e59 100644 --- a/apps/shared/interactive_curve_view_range.cpp +++ b/apps/shared/interactive_curve_view_range.cpp @@ -154,7 +154,7 @@ void InteractiveCurveViewRange::setDefault() { if (m_delegate == nullptr) { return; } - m_xMax = m_delegate->interestingXRange(); + m_xMax = m_delegate->interestingXHalfRange(); MemoizedCurveViewRange::setXMin(-m_xMax); setYAuto(true); } diff --git a/apps/shared/interactive_curve_view_range_delegate.cpp b/apps/shared/interactive_curve_view_range_delegate.cpp index 6f8742c7e..271b7237c 100644 --- a/apps/shared/interactive_curve_view_range_delegate.cpp +++ b/apps/shared/interactive_curve_view_range_delegate.cpp @@ -52,8 +52,4 @@ bool InteractiveCurveViewRangeDelegate::didChangeRange(InteractiveCurveViewRange return true; } -float InteractiveCurveViewRangeDelegate::interestingXRange() { - return 10.0f; -} - } diff --git a/apps/shared/interactive_curve_view_range_delegate.h b/apps/shared/interactive_curve_view_range_delegate.h index 841e8f43c..09950016c 100644 --- a/apps/shared/interactive_curve_view_range_delegate.h +++ b/apps/shared/interactive_curve_view_range_delegate.h @@ -8,7 +8,7 @@ class InteractiveCurveViewRange; class InteractiveCurveViewRangeDelegate { public: bool didChangeRange(InteractiveCurveViewRange * interactiveCurveViewRange); - virtual float interestingXRange(); + virtual float interestingXHalfRange() { return 10.0f; } protected: struct Range { float min; From 5d1ef0f3f088612dedd8600b0a7f49bf4662ae78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 4 Jan 2019 12:09:25 +0100 Subject: [PATCH 202/373] [apps/sequence] Use first ranks when computing graph range Put two sequences u(n+1)=u(n) and v(n+1) = v(n), u(100) = 50, v(50) = 8. Basic settings computed the x range as [0,10] before, now it is [50,110]. --- apps/sequence/graph/curve_view_range.cpp | 62 ++++++++++--------- apps/sequence/graph/curve_view_range.h | 2 +- apps/sequence/graph/graph_controller.cpp | 32 ++++++++++ apps/sequence/graph/graph_controller.h | 3 + .../interactive_curve_view_range_delegate.h | 1 + 5 files changed, 71 insertions(+), 29 deletions(-) diff --git a/apps/sequence/graph/curve_view_range.cpp b/apps/sequence/graph/curve_view_range.cpp index ff13a3f38..444422906 100644 --- a/apps/sequence/graph/curve_view_range.cpp +++ b/apps/sequence/graph/curve_view_range.cpp @@ -11,22 +11,23 @@ namespace Sequence { CurveViewRange::CurveViewRange(CurveViewCursor * cursor, InteractiveCurveViewRangeDelegate * delegate) : InteractiveCurveViewRange(cursor, delegate) { - m_xMin = -k_displayLeftMarginRatio*m_xMax; + m_xMin = -k_displayLeftMarginRatio * m_xMax; } void CurveViewRange::roundAbscissa() { - float xMin = m_xMin; - float xMax = m_xMax; - float newXMin = clipped(std::round((xMin+xMax)/2) - (float)Ion::Display::Width/2.0f, false); - float newXMax = clipped(std::round((xMin+xMax)/2) + (float)Ion::Display::Width/2.0f-1.0f, true); + int roundedXMean = std::round((m_xMin+m_xMax)/2); + float halfScreenWidth = ((float)Ion::Display::Width)/2.0f; + float newXMin = clipped(roundedXMean - halfScreenWidth, false); + float newXMax = clipped(roundedXMean + halfScreenWidth - 1.0f, true); if (std::isnan(newXMin) || std::isnan(newXMax)) { return; } m_xMin = newXMin; m_xMax = newXMax; - if (m_xMin < 0.0f) { - m_xMin = -k_displayLeftMarginRatio*(float)Ion::Display::Width; - m_xMax = m_xMin+(float)Ion::Display::Width; + float interestingXMin = m_delegate->interestingXMin(); + if (m_xMin < interestingXMin) { + m_xMin = interestingXMin - k_displayLeftMarginRatio * (float)Ion::Display::Width; + m_xMax = m_xMin + (float)Ion::Display::Width; } m_xGridUnit = computeGridUnit(Axis::X, m_xMax - m_xMin); if (m_delegate) { @@ -35,24 +36,27 @@ void CurveViewRange::roundAbscissa() { } void CurveViewRange::normalize() { - float xMin = m_xMin; - float xMax = m_xMax; - float yMin = m_yMin; - float yMax = m_yMax; - float newXMin = clipped((xMin+xMax)/2 - NormalizedXHalfRange(), false); - float newXMax = clipped((xMin+xMax)/2 + NormalizedXHalfRange(), true); + float xMean = (m_xMin+m_xMax)/2; + float yMean = (m_yMin+m_yMax)/2; + + // Compute the X + float newXMin = clipped(xMean - NormalizedXHalfRange(), false); + float newXMax = clipped(xMean + NormalizedXHalfRange(), true); if (!std::isnan(newXMin) && !std::isnan(newXMax)) { m_xMin = newXMin; m_xMax = newXMax; m_xGridUnit = computeGridUnit(Axis::X, m_xMax - m_xMin); } - if (m_xMin < 0.0f) { - m_xMin = -k_displayLeftMarginRatio*2.0f*NormalizedXHalfRange(); + float interestingXMin = m_delegate->interestingXMin(); + if (m_xMin < interestingXMin) { + m_xMin = interestingXMin -k_displayLeftMarginRatio*2.0f*NormalizedXHalfRange(); m_xMax = m_xMin + 2.0f*NormalizedXHalfRange(); } + + // Compute the Y m_yAuto = false; - float newYMin = clipped((yMin+yMax)/2 - NormalizedYHalfRange(), false); - float newYMax = clipped((yMin+yMax)/2 + NormalizedYHalfRange(), true); + float newYMin = clipped(yMean - NormalizedYHalfRange(), false); + float newYMax = clipped(yMean + NormalizedYHalfRange(), true); if (!std::isnan(newYMin) && !std::isnan(newYMax)) { m_yMin = newYMin; m_yMax = newYMax; @@ -61,16 +65,16 @@ void CurveViewRange::normalize() { } void CurveViewRange::setTrigonometric() { - m_xMin = -k_displayLeftMarginRatio*21.0f; - m_xMax = 21.0f; - if (Preferences::sharedPreferences()->angleUnit() == Preferences::AngleUnit::Degree) { - m_xMin = -k_displayLeftMarginRatio*1200; - m_xMax = 1200; - } + float interestingXMin = m_delegate->interestingXMin(); + float interestingXRange = Preferences::sharedPreferences()->angleUnit() == Preferences::AngleUnit::Degree ? 1200.0f : 21.0f; + m_xMin = interestingXMin - k_displayLeftMarginRatio * interestingXRange; + m_xMax = interestingXMin + interestingXRange; m_xGridUnit = computeGridUnit(Axis::X, m_xMax - m_xMin); + m_yAuto = false; - m_yMin = -1.6f; - m_yMax = 1.6f; + constexpr float y = 1.6f; + m_yMin = -y; + m_yMax = y; m_yGridUnit = computeGridUnit(Axis::Y, m_yMax - m_yMin); } @@ -78,8 +82,10 @@ void CurveViewRange::setDefault() { if (m_delegate == nullptr) { return; } - m_xMax = m_delegate->interestingXHalfRange(); - m_xMin = -k_displayLeftMarginRatio*m_xMax; + float interestingXMin = m_delegate->interestingXMin(); + float interestingXRange = m_delegate->interestingXHalfRange(); + m_xMin = interestingXMin - k_displayLeftMarginRatio * interestingXRange; + m_xMax = interestingXMin + interestingXRange; m_xGridUnit = computeGridUnit(Axis::X, m_xMax - m_xMin); setYAuto(true); } diff --git a/apps/sequence/graph/curve_view_range.h b/apps/sequence/graph/curve_view_range.h index 480a49fc6..ac9316220 100644 --- a/apps/sequence/graph/curve_view_range.h +++ b/apps/sequence/graph/curve_view_range.h @@ -13,7 +13,7 @@ public: void setTrigonometric() override; void setDefault() override; private: - constexpr static float k_displayLeftMarginRatio = 0.05f; + constexpr static float k_displayLeftMarginRatio = 0.1f; }; } diff --git a/apps/sequence/graph/graph_controller.cpp b/apps/sequence/graph/graph_controller.cpp index 5db89d5a0..cd5e42c31 100644 --- a/apps/sequence/graph/graph_controller.cpp +++ b/apps/sequence/graph/graph_controller.cpp @@ -1,11 +1,15 @@ #include "graph_controller.h" #include +#include using namespace Shared; using namespace Poincare; namespace Sequence { +static inline int minInt(int x, int y) { return (x < y ? x : y); } +static inline int maxInt(int x, int y) { return (x > y ? x : y); } + GraphController::GraphController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, SequenceStore * sequenceStore, CurveViewRange * graphRange, CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * rangeVersion, Preferences::AngleUnit * angleUnitVersion, ButtonRowController * header) : FunctionGraphController(parentResponder, inputEventHandlerDelegate, header, graphRange, &m_view, cursor, indexFunctionSelectedByCursor, modelVersion, rangeVersion, angleUnitVersion), m_bannerView(), @@ -25,6 +29,34 @@ I18n::Message GraphController::emptyMessage() { return I18n::Message::NoActivatedSequence; } +float GraphController::interestingXMin() { + int nmin = INT_MAX; + for (int i = 0; i < m_sequenceStore->numberOfModels(); i++) { + Sequence * s = m_sequenceStore->modelAtIndex(i); + if (s->isDefined() && s->isActive()) { + nmin = minInt(nmin, s->initialRank()); + } + } + assert(nmin < INT_MAX); + return nmin; +} + +float GraphController::interestingXHalfRange() { + float standardRange = Shared::FunctionGraphController::interestingXHalfRange(); + int nmin = INT_MAX; + int nmax = 0; + for (int i = 0; i < m_sequenceStore->numberOfModels(); i++) { + Sequence * s = m_sequenceStore->modelAtIndex(i); + if (s->isDefined() && s->isActive()) { + int firstInterestingIndex = s->initialRank(); + nmin = minInt(nmin, firstInterestingIndex); + nmax = maxInt(nmax, firstInterestingIndex + standardRange); + } + } + assert(nmax - nmin >= standardRange); + return nmax - nmin; +} + bool GraphController::handleEnter() { m_termSumController.setFunction(m_sequenceStore->activeFunctionAtIndex(indexFunctionSelectedByCursor())); return FunctionGraphController::handleEnter(); diff --git a/apps/sequence/graph/graph_controller.h b/apps/sequence/graph/graph_controller.h index b90942074..52dedbaae 100644 --- a/apps/sequence/graph/graph_controller.h +++ b/apps/sequence/graph/graph_controller.h @@ -17,6 +17,9 @@ public: GraphController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, SequenceStore * sequenceStore, CurveViewRange * graphRange, Shared::CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * rangeVersion, Poincare::Preferences::AngleUnit * angleUnitVersion, ButtonRowController * header); I18n::Message emptyMessage() override; TermSumController * termSumController() { return &m_termSumController; } + // InteractiveCurveViewRangeDelegate + float interestingXMin() override; + float interestingXHalfRange() override; protected: int numberOfCurves() const override { return m_sequenceStore->numberOfModels(); } private: diff --git a/apps/shared/interactive_curve_view_range_delegate.h b/apps/shared/interactive_curve_view_range_delegate.h index 09950016c..62ae00a96 100644 --- a/apps/shared/interactive_curve_view_range_delegate.h +++ b/apps/shared/interactive_curve_view_range_delegate.h @@ -8,6 +8,7 @@ class InteractiveCurveViewRange; class InteractiveCurveViewRangeDelegate { public: bool didChangeRange(InteractiveCurveViewRange * interactiveCurveViewRange); + virtual float interestingXMin() { return -interestingXHalfRange(); } virtual float interestingXHalfRange() { return 10.0f; } protected: struct Range { From 869e534b4b64e8ef35d3d85556f38e97a3604a2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 4 Jan 2019 12:16:23 +0100 Subject: [PATCH 203/373] [apps] MAke some InteractiveCurveViewRangeDelegate methods const --- apps/graph/graph/graph_controller.cpp | 2 +- apps/graph/graph/graph_controller.h | 2 +- apps/sequence/graph/graph_controller.cpp | 4 ++-- apps/sequence/graph/graph_controller.h | 4 ++-- apps/shared/interactive_curve_view_range_delegate.h | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/graph/graph/graph_controller.cpp b/apps/graph/graph/graph_controller.cpp index 08c4ca80b..caf46381a 100644 --- a/apps/graph/graph/graph_controller.cpp +++ b/apps/graph/graph/graph_controller.cpp @@ -39,7 +39,7 @@ void GraphController::setDisplayDerivativeInBanner(bool displayDerivative) { m_displayDerivativeInBanner = displayDerivative; } -float GraphController::interestingXHalfRange() { +float GraphController::interestingXHalfRange() const { float characteristicRange = 0.0f; TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app(); for (int i = 0; i < functionStore()->numberOfActiveFunctions(); i++) { diff --git a/apps/graph/graph/graph_controller.h b/apps/graph/graph/graph_controller.h index bdf5ad861..58586d727 100644 --- a/apps/graph/graph/graph_controller.h +++ b/apps/graph/graph/graph_controller.h @@ -20,7 +20,7 @@ public: void viewWillAppear() override; bool displayDerivativeInBanner() const; void setDisplayDerivativeInBanner(bool displayDerivative); - float interestingXHalfRange() override; + float interestingXHalfRange() const override; private: int estimatedBannerNumberOfLines() const override; void selectFunctionWithCursor(int functionIndex) override; diff --git a/apps/sequence/graph/graph_controller.cpp b/apps/sequence/graph/graph_controller.cpp index cd5e42c31..92db25c1a 100644 --- a/apps/sequence/graph/graph_controller.cpp +++ b/apps/sequence/graph/graph_controller.cpp @@ -29,7 +29,7 @@ I18n::Message GraphController::emptyMessage() { return I18n::Message::NoActivatedSequence; } -float GraphController::interestingXMin() { +float GraphController::interestingXMin() const { int nmin = INT_MAX; for (int i = 0; i < m_sequenceStore->numberOfModels(); i++) { Sequence * s = m_sequenceStore->modelAtIndex(i); @@ -41,7 +41,7 @@ float GraphController::interestingXMin() { return nmin; } -float GraphController::interestingXHalfRange() { +float GraphController::interestingXHalfRange() const { float standardRange = Shared::FunctionGraphController::interestingXHalfRange(); int nmin = INT_MAX; int nmax = 0; diff --git a/apps/sequence/graph/graph_controller.h b/apps/sequence/graph/graph_controller.h index 52dedbaae..b8579a776 100644 --- a/apps/sequence/graph/graph_controller.h +++ b/apps/sequence/graph/graph_controller.h @@ -18,8 +18,8 @@ public: I18n::Message emptyMessage() override; TermSumController * termSumController() { return &m_termSumController; } // InteractiveCurveViewRangeDelegate - float interestingXMin() override; - float interestingXHalfRange() override; + float interestingXMin() const override; + float interestingXHalfRange() const override; protected: int numberOfCurves() const override { return m_sequenceStore->numberOfModels(); } private: diff --git a/apps/shared/interactive_curve_view_range_delegate.h b/apps/shared/interactive_curve_view_range_delegate.h index 62ae00a96..b7193ebd1 100644 --- a/apps/shared/interactive_curve_view_range_delegate.h +++ b/apps/shared/interactive_curve_view_range_delegate.h @@ -8,8 +8,8 @@ class InteractiveCurveViewRange; class InteractiveCurveViewRangeDelegate { public: bool didChangeRange(InteractiveCurveViewRange * interactiveCurveViewRange); - virtual float interestingXMin() { return -interestingXHalfRange(); } - virtual float interestingXHalfRange() { return 10.0f; } + virtual float interestingXMin() const { return -interestingXHalfRange(); } + virtual float interestingXHalfRange() const { return 10.0f; } protected: struct Range { float min; From 96394697618bd056debe5f6da0d8705ff3c69506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 7 Jan 2019 13:46:30 +0100 Subject: [PATCH 204/373] [apps/curve_view] Fix drawGridLines that drew the opposite axis --- apps/shared/curve_view.cpp | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index e37616915..80eb9e5b9 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -93,24 +93,22 @@ float CurveView::samplingRatio() const { } void CurveView::drawGridLines(KDContext * ctx, KDRect rect, Axis axis, float step, KDColor boldColor, KDColor lightColor) const { - float rectMin = pixelToFloat(Axis::Horizontal, rect.left()); - float rectMax = pixelToFloat(Axis::Horizontal, rect.right()); - if (axis == Axis::Vertical) { - rectMax = pixelToFloat(Axis::Vertical, rect.top()); - rectMin = pixelToFloat(Axis::Vertical, rect.bottom()); - } - float start = step * ((int)(min(axis)/step)); - float boldStart = 2*step * ((int)(min(axis)/(2*step))); - bool drawBold = std::fabs(start - boldStart) < FLT_EPSILON; Axis otherAxis = (axis == Axis::Horizontal) ? Axis::Vertical : Axis::Horizontal; - for (float x = start; x < max(axis); x+= step) { + + float otherAxisMin = pixelToFloat(otherAxis, otherAxis == Axis::Horizontal ? rect.left() : rect.bottom()); + float otherAxisMax = pixelToFloat(otherAxis, otherAxis == Axis::Horizontal ? rect.right() : rect.top()); + float start = step * ((int)(min(otherAxis)/step)); + float boldStart = 2*step * ((int)(min(otherAxis)/(2*step))); + bool drawBold = std::fabs(start - boldStart) < FLT_EPSILON; + + for (float x = start; x < max(otherAxis); x+= step) { /* When |start| >> step, start + step = start. In that case, quit the * infinite loop. */ if (x == x-step || x == x+step) { return; } - if (rectMin <= x && x <= rectMax) { - drawLine(ctx, rect, otherAxis, x, drawBold ? boldColor : lightColor); + if (otherAxisMin <= x && x <= otherAxisMax) { + drawLine(ctx, rect, axis, x, drawBold ? boldColor : lightColor); } drawBold = !drawBold; } @@ -428,8 +426,8 @@ void CurveView::drawDot(KDContext * ctx, KDRect rect, float x, float y, KDColor void CurveView::drawGrid(KDContext * ctx, KDRect rect) const { KDColor boldColor = Palette::GreyMiddle; KDColor lightColor = Palette::GreyWhite; - drawGridLines(ctx, rect, Axis::Horizontal, m_curveViewRange->xGridUnit(), boldColor, lightColor); - drawGridLines(ctx, rect, Axis::Vertical, m_curveViewRange->yGridUnit(), boldColor, lightColor); + drawGridLines(ctx, rect, Axis::Vertical, m_curveViewRange->xGridUnit(), boldColor, lightColor); + drawGridLines(ctx, rect, Axis::Horizontal, m_curveViewRange->yGridUnit(), boldColor, lightColor); } void CurveView::drawAxes(KDContext * ctx, KDRect rect) const { From e2ac56abc64690ebaee1f9855ab55bbe85541114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 7 Jan 2019 13:50:07 +0100 Subject: [PATCH 205/373] [apps/curve_view] Fix grid lines not drawn due to pixel to float error --- apps/shared/curve_view.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index 80eb9e5b9..692824078 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -94,9 +94,10 @@ float CurveView::samplingRatio() const { void CurveView::drawGridLines(KDContext * ctx, KDRect rect, Axis axis, float step, KDColor boldColor, KDColor lightColor) const { Axis otherAxis = (axis == Axis::Horizontal) ? Axis::Vertical : Axis::Horizontal; - - float otherAxisMin = pixelToFloat(otherAxis, otherAxis == Axis::Horizontal ? rect.left() : rect.bottom()); - float otherAxisMax = pixelToFloat(otherAxis, otherAxis == Axis::Horizontal ? rect.right() : rect.top()); + /* We translate the pixel coordinates into floats, adding/subtracting 1 to + * account for conversion errors. */ + float otherAxisMin = pixelToFloat(otherAxis, otherAxis == Axis::Horizontal ? rect.left() - 1 : rect.bottom() + 1); + float otherAxisMax = pixelToFloat(otherAxis, otherAxis == Axis::Horizontal ? rect.right() + 1 : rect.top() - 1); float start = step * ((int)(min(otherAxis)/step)); float boldStart = 2*step * ((int)(min(otherAxis)/(2*step))); bool drawBold = std::fabs(start - boldStart) < FLT_EPSILON; From 2d4d92090cb4b1d46ab020c928830bc545091135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 4 Jan 2019 16:53:47 +0100 Subject: [PATCH 206/373] [apps/code] Inline code in console_store --- apps/code/console_store.cpp | 11 ----------- apps/code/console_store.h | 5 +++-- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/apps/code/console_store.cpp b/apps/code/console_store.cpp index 186ead226..910ea0bb8 100644 --- a/apps/code/console_store.cpp +++ b/apps/code/console_store.cpp @@ -1,21 +1,10 @@ #include "console_store.h" -#include #include namespace Code { static inline int min(int x, int y) { return (x 0); - m_history[0] = 0; -} - void ConsoleStore::startNewSession() { if (k_historySize < 1) { return; diff --git a/apps/code/console_store.h b/apps/code/console_store.h index 245ecbcef..f5ae9c2b7 100644 --- a/apps/code/console_store.h +++ b/apps/code/console_store.h @@ -2,14 +2,15 @@ #define CODE_CONSOLE_STORE_H #include "console_line.h" +#include #include namespace Code { class ConsoleStore { public: - ConsoleStore(); - void clear(); + ConsoleStore() : m_history{0} {} + void clear() { assert(k_historySize > 0); m_history[0] = 0; } void startNewSession(); ConsoleLine lineAtIndex(int i) const; int numberOfLines() const; From 177373c5af0ae11b02a07bbbe5a871b910748b64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 4 Jan 2019 16:49:53 +0100 Subject: [PATCH 207/373] [apps/code] Handle carriage returns in the input text --- apps/code/console_controller.cpp | 37 +++++++++++++++++++++++++------- python/port/builtins.c | 10 ++------- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/apps/code/console_controller.cpp b/apps/code/console_controller.cpp index 13acc6965..81c7c2b67 100644 --- a/apps/code/console_controller.cpp +++ b/apps/code/console_controller.cpp @@ -91,25 +91,46 @@ const char * ConsoleController::inputText(const char * prompt) { AppsContainer * a = (AppsContainer *)(app()->container()); m_inputRunLoopActive = true; - // Set the prompt text - m_selectableTableView.reloadData(); - m_selectableTableView.selectCellAtLocation(0, m_consoleStore.numberOfLines()); - m_editCell.setPrompt(prompt); + const char * promptText = prompt; + /* Set the prompt text. If the prompt text has a '\n', put the prompt text in + * the history until the last '\n', and put the remaining prompt text in the + * edit cell's prompt. */ + char * lastCarriageReturn = nullptr; + char * s = const_cast(prompt); + while (*s != 0) { + if (*s == '\n') { + lastCarriageReturn = s; + } + s++; + } + if (lastCarriageReturn != nullptr) { + printText(prompt, lastCarriageReturn-prompt+1); + promptText = lastCarriageReturn+1; + } + + m_editCell.setPrompt(promptText); m_editCell.setText(""); - // Run new input loop + // Reload the history + m_selectableTableView.reloadData(); + m_selectableTableView.selectCellAtLocation(0, m_consoleStore.numberOfLines()); a->redrawWindow(); + + // Launch a new input loop a->runWhile([](void * a){ ConsoleController * c = static_cast(a); return c->inputRunLoopActive(); }, this); - // Reset the prompt line + // Handle the input text + printText(promptText, s - promptText); + const char * text = m_editCell.text(); + printText(text, strlen(text)); flushOutputAccumulationBufferToStore(); - m_consoleStore.deleteLastLineIfEmpty(); + m_editCell.setPrompt(sStandardPromptText); - return m_editCell.text(); + return text; } void ConsoleController::viewWillAppear() { diff --git a/python/port/builtins.c b/python/port/builtins.c index a04ad75c6..fa0e1f3be 100644 --- a/python/port/builtins.c +++ b/python/port/builtins.c @@ -15,17 +15,11 @@ mp_obj_t mp_builtin_input(size_t n_args, const mp_obj_t *args) { prompt = mp_obj_str_get_str(args[0]); } - // 2 - Perform the HAL input command + // 2 - Perform the HAL input command. This logs the prompt and the result const char * result = mp_hal_input(prompt); - // 3 - Log the prompt, result and flush a new line + // 3 - Return the input mp_obj_t resultStr = mp_obj_new_str(result, strlen(result)); - if (n_args == 1) { - mp_obj_print(args[0], PRINT_STR); - } - mp_obj_print(resultStr, PRINT_STR); - mp_print_str(MP_PYTHON_PRINTER, "\n"); - return resultStr; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_input_obj, 0, 1, mp_builtin_input); From c4bd55ef08954d7b867c653e360f1608ea706c65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 4 Jan 2019 17:15:57 +0100 Subject: [PATCH 208/373] [apps/code] Clean ConsoleController::printText --- apps/code/console_controller.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/apps/code/console_controller.cpp b/apps/code/console_controller.cpp index 81c7c2b67..14b1152c8 100644 --- a/apps/code/console_controller.cpp +++ b/apps/code/console_controller.cpp @@ -334,25 +334,24 @@ void ConsoleController::resetSandbox() { * The text argument is not always null-terminated. */ void ConsoleController::printText(const char * text, size_t length) { size_t textCutIndex = firstNewLineCharIndex(text, length); - // If there is no new line in text, just append it to the output accumulation - // buffer. if (textCutIndex >= length) { + /* If there is no new line in text, just append it to the output + * accumulation buffer. */ appendTextToOutputAccumulationBuffer(text, length); return; } - // If there is a new line in the middle of the text, we have to store at least - // two new console lines in the console store. if (textCutIndex < length - 1) { + /* If there is a new line in the middle of the text, we have to store at + * least two new console lines in the console store. */ printText(text, textCutIndex + 1); printText(&text[textCutIndex+1], length - (textCutIndex + 1)); return; } - // If there is a new line at the end of the text, we have to store the line in - // the console store. - if (textCutIndex == length - 1) { - appendTextToOutputAccumulationBuffer(text, length-1); - flushOutputAccumulationBufferToStore(); - } + /* There is a new line at the end of the text, we have to store the line in + * the console store. */ + assert(textCutIndex == length - 1); + appendTextToOutputAccumulationBuffer(text, length-1); + flushOutputAccumulationBufferToStore(); } void ConsoleController::autoImportScript(Script script, bool force) { From 4283eb7e32729782cddea70973824562acaaedfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 7 Jan 2019 13:48:04 +0100 Subject: [PATCH 209/373] [poincare] Power: fix approximation 0^0 should be equal to undef --- poincare/src/power.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index e3a397372..6b3c37a4b 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -100,7 +100,7 @@ bool PowerNode::isReal(Context & context) const { template Complex PowerNode::compute(const std::complex c, const std::complex d) { std::complex result; - if (c.imag() == 0.0 && d.imag() == 0.0 && (c.real() > 0.0 || std::round(d.real()) == d.real())) { + if (c.imag() == 0.0 && d.imag() == 0.0 && c.real() != 0.0 && (c.real() > 0.0 || std::round(d.real()) == d.real())) { /* pow: (R+, R) -> R+ (2^1.3 ~ 2.46) * pow: (R-, N) -> R+ ((-2)^3 = -8) * In these cases we rather use std::pow(double, double) because: From f7f77ef9f7c9bd88be44350a4441cb12b71b8539 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 7 Jan 2019 14:12:49 +0100 Subject: [PATCH 210/373] [apps/code] When OK or EXE on empty python input loop, stop the input --- apps/code/console_controller.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/code/console_controller.cpp b/apps/code/console_controller.cpp index 14b1152c8..5ba4dc506 100644 --- a/apps/code/console_controller.cpp +++ b/apps/code/console_controller.cpp @@ -263,7 +263,11 @@ bool ConsoleController::textFieldShouldFinishEditing(TextField * textField, Ion: } bool ConsoleController::textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) { - if (event == Ion::Events::Up && m_inputRunLoopActive) { + if (m_inputRunLoopActive + && (event == Ion::Events::Up + || event == Ion::Events::OK + || event == Ion::Events::EXE)) + { m_inputRunLoopActive = false; /* We need to return true here because we want to actually exit from the * input run loop, which requires ending a dispatchEvent cycle. */ From b30c197d36e03bf6bc60b529ae70531a42a93b0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 7 Jan 2019 16:35:32 +0100 Subject: [PATCH 211/373] [test/poincare] Tests on expression order --- poincare/Makefile | 1 + poincare/test/expression_order.cpp | 109 +++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 poincare/test/expression_order.cpp diff --git a/poincare/Makefile b/poincare/Makefile index e8bef072d..59e1826f0 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -149,6 +149,7 @@ tests += $(addprefix poincare/test/,\ decimal.cpp\ division.cpp\ expression.cpp\ + expression_order.cpp\ factorial.cpp\ float.cpp\ fraction_layout.cpp\ diff --git a/poincare/test/expression_order.cpp b/poincare/test/expression_order.cpp new file mode 100644 index 000000000..9db677bb9 --- /dev/null +++ b/poincare/test/expression_order.cpp @@ -0,0 +1,109 @@ +#include +#include +#include +#include +#include "helper.h" + +using namespace Poincare; + +void assert_multiplication_or_addition_is_ordered_as(Expression e1, Expression e2) { + if (e1.type() == ExpressionNode::Type::Multiplication) { + static_cast(e1).sortChildrenInPlace( + [](const ExpressionNode * e1, const ExpressionNode * e2, bool canBeInterrupted) { return ExpressionNode::SimplificationOrder(e1, e2, true, canBeInterrupted); }, + true); + } else { + assert(e1.type() == ExpressionNode::Type::Addition); + static_cast(e1).sortChildrenInPlace( + [](const ExpressionNode * e1, const ExpressionNode * e2, bool canBeInterrupted) { return ExpressionNode::SimplificationOrder(e1, e2, false, canBeInterrupted); }, + true); + } + quiz_assert(e1.isIdenticalTo(e2)); +} + +QUIZ_CASE(poincare_expression_order) { + { + // 2 * 5 + Expression e1 = Multiplication(Rational(5), Rational(2)); + Expression e2 = Multiplication(Rational(2), Rational(5)); + assert_multiplication_or_addition_is_ordered_as(e1, e2); + } + { + // 2 + 1 + 0 + constexpr int numberOfChildren = 3; + Expression children[numberOfChildren] = {Rational(1), Rational(2), Rational(0)}; + Expression childrenSorted[numberOfChildren] = {Rational(2), Rational(1), Rational(0)}; + Expression e1 = Addition(children, numberOfChildren); + Expression e2 = Addition(childrenSorted, numberOfChildren); + assert_multiplication_or_addition_is_ordered_as(e1, e2); + } + { + // e + pi + i + Expression pi = Constant(Ion::Charset::SmallPi); + Expression i = Constant(Ion::Charset::IComplex); + Expression e = Constant(Ion::Charset::Exponential); + constexpr int numberOfChildren = 3; + Expression children[numberOfChildren] = {pi.clone(), i.clone(), e.clone()}; + Expression childrenSorted[numberOfChildren] = {e, pi, i}; + Expression e1 = Addition(children, numberOfChildren); + Expression e2 = Addition(childrenSorted, numberOfChildren); + assert_multiplication_or_addition_is_ordered_as(e1, e2); + } + { + // 2 * root(3) + Expression e1 = Multiplication(SquareRoot::Builder(Rational(3)), Rational(2)); + Expression e2 = Multiplication(Rational(2), SquareRoot::Builder(Rational(3))); + assert_multiplication_or_addition_is_ordered_as(e1, e2); + } + { + constexpr int numberOfChildren = 4; + Expression children[numberOfChildren] = { + Symbol('c'), + Power(Symbol('b'), Rational(2)), + Power(Symbol('a'), Rational(2)), + Symbol('a') + }; + Expression childrenSorted[numberOfChildren] = { + Power(Symbol('a'), Rational(2)), + Symbol('a'), + Power(Symbol('b'), Rational(2)), + Symbol('c') + }; + // a^2 + a + b^2 + c + Expression e1 = Addition(children, numberOfChildren); + Expression e2 = Addition(childrenSorted, numberOfChildren); + assert_multiplication_or_addition_is_ordered_as(e1, e2); + } + { + // 2*x^3 + 3*x^2 + Expression child1 = Multiplication(Rational(2), Power(Symbol('x'), Rational(3))); + Expression child2 = Multiplication(Rational(3), Power(Symbol('x'), Rational(2))); + Expression e1 = Addition(child2.clone(), child1.clone()); + Expression e2 = Addition(child1, child2); + assert_multiplication_or_addition_is_ordered_as(e1, e2); + } + { + // 3*x + 2*x + Expression child1 = Multiplication(Rational(3), Symbol('x')); + Expression child2 = Multiplication(Rational(2), Symbol('x')); + Expression e1 = Addition(child2.clone(), child1.clone()); + Expression e2 = Addition(child1, child2); + assert_multiplication_or_addition_is_ordered_as(e1, e2); + } + { + // pi^a * pi^b + Expression child1 = Power(Constant(Ion::Charset::SmallPi), Symbol('a')); + Expression child2 = Power(Constant(Ion::Charset::SmallPi), Symbol('b')); + Expression e1 = Multiplication(child2.clone(), child1.clone()); + Expression e2 = Multiplication(child1, child2); + assert_multiplication_or_addition_is_ordered_as(e1, e2); + } + { + // pi^2 * pi^3 + Expression child1 = Power(Constant(Ion::Charset::SmallPi), Rational(2)); + Expression child2 = Power(Constant(Ion::Charset::SmallPi), Rational(3)); + Expression e1 = Multiplication(child2.clone(), child1.clone()); + Expression e2 = Multiplication(child1, child2); + assert_multiplication_or_addition_is_ordered_as(e1, e2); + } + +} From 48415427504d7d0bdc6bf573a9f5cbd4738ac870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 7 Jan 2019 17:22:01 +0100 Subject: [PATCH 212/373] [poincare] Add ComplexFormat argument to the approximation routine --- poincare/include/poincare/absolute_value.h | 10 ++-- poincare/include/poincare/addition.h | 22 ++++----- .../include/poincare/approximation_helper.h | 18 ++++---- poincare/include/poincare/arc_cosine.h | 10 ++-- poincare/include/poincare/arc_sine.h | 10 ++-- poincare/include/poincare/arc_tangent.h | 10 ++-- .../include/poincare/binomial_coefficient.h | 6 +-- poincare/include/poincare/ceiling.h | 10 ++-- poincare/include/poincare/complex_argument.h | 10 ++-- poincare/include/poincare/complex_cartesian.h | 6 +-- .../include/poincare/confidence_interval.h | 6 +-- poincare/include/poincare/conjugate.h | 10 ++-- poincare/include/poincare/constant.h | 6 +-- poincare/include/poincare/cosine.h | 10 ++-- poincare/include/poincare/decimal.h | 4 +- poincare/include/poincare/derivative.h | 12 ++--- poincare/include/poincare/determinant.h | 6 +-- poincare/include/poincare/division.h | 18 ++++---- poincare/include/poincare/division_quotient.h | 6 +-- .../include/poincare/division_remainder.h | 6 +-- poincare/include/poincare/empty_expression.h | 6 +-- poincare/include/poincare/equal.h | 6 +-- poincare/include/poincare/expression_node.h | 4 +- poincare/include/poincare/factor.h | 8 ++-- poincare/include/poincare/factorial.h | 10 ++-- poincare/include/poincare/float.h | 6 +-- poincare/include/poincare/floor.h | 10 ++-- poincare/include/poincare/frac_part.h | 10 ++-- poincare/include/poincare/function.h | 6 +-- .../include/poincare/great_common_divisor.h | 6 +-- .../include/poincare/hyperbolic_arc_cosine.h | 10 ++-- .../include/poincare/hyperbolic_arc_sine.h | 10 ++-- .../include/poincare/hyperbolic_arc_tangent.h | 10 ++-- poincare/include/poincare/hyperbolic_cosine.h | 10 ++-- poincare/include/poincare/hyperbolic_sine.h | 10 ++-- .../include/poincare/hyperbolic_tangent.h | 10 ++-- poincare/include/poincare/imaginary_part.h | 10 ++-- poincare/include/poincare/infinity.h | 4 +- poincare/include/poincare/integral.h | 14 +++--- .../include/poincare/least_common_multiple.h | 6 +-- poincare/include/poincare/logarithm.h | 8 ++-- poincare/include/poincare/matrix.h | 10 ++-- poincare/include/poincare/matrix_dimension.h | 6 +-- poincare/include/poincare/matrix_inverse.h | 6 +-- poincare/include/poincare/matrix_trace.h | 6 +-- poincare/include/poincare/matrix_transpose.h | 6 +-- poincare/include/poincare/multiplication.h | 20 ++++---- .../include/poincare/naperian_logarithm.h | 10 ++-- poincare/include/poincare/nth_root.h | 6 +-- poincare/include/poincare/opposite.h | 10 ++-- poincare/include/poincare/parenthesis.h | 6 +-- .../include/poincare/permute_coefficient.h | 6 +-- poincare/include/poincare/power.h | 16 +++---- .../include/poincare/prediction_interval.h | 6 +-- poincare/include/poincare/product.h | 10 ++-- poincare/include/poincare/randint.h | 10 ++-- poincare/include/poincare/random.h | 4 +- poincare/include/poincare/rational.h | 4 +- poincare/include/poincare/real_part.h | 10 ++-- poincare/include/poincare/round.h | 6 +-- poincare/include/poincare/sequence.h | 10 ++-- poincare/include/poincare/sign_function.h | 10 ++-- poincare/include/poincare/sine.h | 10 ++-- poincare/include/poincare/square_root.h | 10 ++-- poincare/include/poincare/store.h | 6 +-- poincare/include/poincare/subtraction.h | 20 ++++---- poincare/include/poincare/sum.h | 10 ++-- poincare/include/poincare/symbol.h | 6 +-- poincare/include/poincare/tangent.h | 10 ++-- poincare/include/poincare/undefined.h | 4 +- poincare/include/poincare/unreal.h | 4 +- poincare/src/absolute_value.cpp | 2 +- poincare/src/addition.cpp | 12 ++--- poincare/src/approximation_helper.cpp | 46 +++++++++---------- poincare/src/arc_cosine.cpp | 2 +- poincare/src/arc_sine.cpp | 2 +- poincare/src/arc_tangent.cpp | 2 +- poincare/src/binomial_coefficient.cpp | 6 +-- poincare/src/ceiling.cpp | 2 +- poincare/src/complex_argument.cpp | 4 +- poincare/src/complex_cartesian.cpp | 6 +-- poincare/src/confidence_interval.cpp | 6 +-- poincare/src/conjugate.cpp | 2 +- poincare/src/constant.cpp | 6 +-- poincare/src/cosine.cpp | 2 +- poincare/src/derivative.cpp | 24 +++++----- poincare/src/determinant.cpp | 4 +- poincare/src/division.cpp | 10 ++-- poincare/src/division_quotient.cpp | 6 +-- poincare/src/division_remainder.cpp | 6 +-- poincare/src/empty_expression.cpp | 2 +- poincare/src/equal.cpp | 2 +- poincare/src/expression.cpp | 2 +- poincare/src/factorial.cpp | 2 +- poincare/src/floor.cpp | 2 +- poincare/src/frac_part.cpp | 2 +- poincare/src/function.cpp | 12 ++--- poincare/src/great_common_divisor.cpp | 6 +-- poincare/src/hyperbolic_arc_cosine.cpp | 6 +-- poincare/src/hyperbolic_arc_sine.cpp | 6 +-- poincare/src/hyperbolic_arc_tangent.cpp | 6 +-- poincare/src/hyperbolic_cosine.cpp | 6 +-- poincare/src/hyperbolic_sine.cpp | 6 +-- poincare/src/hyperbolic_tangent.cpp | 6 +-- poincare/src/integral.cpp | 34 +++++++------- poincare/src/least_common_multiple.cpp | 6 +-- poincare/src/logarithm.cpp | 22 ++++----- poincare/src/matrix.cpp | 4 +- poincare/src/matrix_dimension.cpp | 4 +- poincare/src/matrix_inverse.cpp | 4 +- poincare/src/matrix_trace.cpp | 4 +- poincare/src/matrix_transpose.cpp | 4 +- poincare/src/multiplication.cpp | 10 ++-- poincare/src/nth_root.cpp | 8 ++-- poincare/src/parenthesis.cpp | 4 +- poincare/src/permute_coefficient.cpp | 6 +-- poincare/src/power.cpp | 16 +++---- poincare/src/prediction_interval.cpp | 6 +-- poincare/src/product.cpp | 6 +-- poincare/src/randint.cpp | 6 +-- poincare/src/round.cpp | 6 +-- poincare/src/sequence.cpp | 12 ++--- poincare/src/sign_function.cpp | 4 +- poincare/src/sine.cpp | 2 +- poincare/src/square_root.cpp | 2 +- poincare/src/store.cpp | 4 +- poincare/src/subtraction.cpp | 6 +-- poincare/src/sum.cpp | 6 +-- poincare/src/symbol.cpp | 4 +- poincare/src/tangent.cpp | 2 +- poincare/src/trigonometry.cpp | 8 ++-- 131 files changed, 522 insertions(+), 522 deletions(-) diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index f58d45944..5a2b9ed98 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -27,14 +27,14 @@ public: bool isReal(Context & context) const override { return true; } // Approximation - template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { + template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { return Complex(std::abs(c)); } - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } // Layout diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 3b48de687..d34ef2e04 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -28,12 +28,12 @@ public: int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const override; // Evaluation - template static Complex compute(const std::complex c, const std::complex d) { return Complex(c+d); } - template static MatrixComplex computeOnMatrices(const MatrixComplex m, const MatrixComplex n) { - return ApproximationHelper::ElementWiseOnComplexMatrices(m, n, compute); + template static Complex compute(const std::complex c, const std::complex d, Preferences::ComplexFormat complexFormat) { return Complex(c+d); } + template static MatrixComplex computeOnMatrices(const MatrixComplex m, const MatrixComplex n, Preferences::ComplexFormat complexFormat) { + return ApproximationHelper::ElementWiseOnComplexMatrices(m, n, complexFormat, compute); } - template static MatrixComplex computeOnComplexAndMatrix(const std::complex c, const MatrixComplex m) { - return ApproximationHelper::ElementWiseOnMatrixComplexAndComplex(m, c, compute); + template static MatrixComplex computeOnComplexAndMatrix(const std::complex c, const MatrixComplex m, Preferences::ComplexFormat complexFormat) { + return ApproximationHelper::ElementWiseOnMatrixComplexAndComplex(m, c, complexFormat, compute); } private: // Layout @@ -46,14 +46,14 @@ private: Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) override; /* Evaluation */ - template static MatrixComplex computeOnMatrixAndComplex(const MatrixComplex m, const std::complex c) { - return ApproximationHelper::ElementWiseOnMatrixComplexAndComplex(m, c, compute); + template static MatrixComplex computeOnMatrixAndComplex(const MatrixComplex m, const std::complex c, Preferences::ComplexFormat complexFormat) { + return ApproximationHelper::ElementWiseOnMatrixComplexAndComplex(m, c, complexFormat, compute); } - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::MapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::MapReduce(this, context, complexFormat, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::MapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::MapReduce(this, context, complexFormat, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } }; diff --git a/poincare/include/poincare/approximation_helper.h b/poincare/include/poincare/approximation_helper.h index 59d22f3fd..7160bca38 100644 --- a/poincare/include/poincare/approximation_helper.h +++ b/poincare/include/poincare/approximation_helper.h @@ -11,17 +11,17 @@ namespace Poincare { namespace ApproximationHelper { template std::complex TruncateRealOrImaginaryPartAccordingToArgument(std::complex c); - template using ComplexCompute = Complex(*)(const std::complex, Preferences::AngleUnit angleUnit); - template Evaluation Map(const ExpressionNode * expression, Context& context, Preferences::AngleUnit angleUnit, ComplexCompute compute); + template using ComplexCompute = Complex(*)(const std::complex, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + template Evaluation Map(const ExpressionNode * expression, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ComplexCompute compute); - template using ComplexAndComplexReduction = Complex(*)(const std::complex, const std::complex); - template using ComplexAndMatrixReduction = MatrixComplex(*)(const std::complex c, const MatrixComplex m); - template using MatrixAndComplexReduction = MatrixComplex(*)(const MatrixComplex m, const std::complex c); - template using MatrixAndMatrixReduction = MatrixComplex(*)(const MatrixComplex m, const MatrixComplex n); - template Evaluation MapReduce(const ExpressionNode * expression, Context& context, Preferences::AngleUnit angleUnit, ComplexAndComplexReduction computeOnComplexes, ComplexAndMatrixReduction computeOnComplexAndMatrix, MatrixAndComplexReduction computeOnMatrixAndComplex, MatrixAndMatrixReduction computeOnMatrices); + template using ComplexAndComplexReduction = Complex(*)(const std::complex, const std::complex, Preferences::ComplexFormat complexFormat); + template using ComplexAndMatrixReduction = MatrixComplex(*)(const std::complex c, const MatrixComplex m, Preferences::ComplexFormat complexFormat); + template using MatrixAndComplexReduction = MatrixComplex(*)(const MatrixComplex m, const std::complex c, Preferences::ComplexFormat complexFormat); + template using MatrixAndMatrixReduction = MatrixComplex(*)(const MatrixComplex m, const MatrixComplex n, Preferences::ComplexFormat complexFormat); + template Evaluation MapReduce(const ExpressionNode * expression, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ComplexAndComplexReduction computeOnComplexes, ComplexAndMatrixReduction computeOnComplexAndMatrix, MatrixAndComplexReduction computeOnMatrixAndComplex, MatrixAndMatrixReduction computeOnMatrices); - template MatrixComplex ElementWiseOnMatrixComplexAndComplex(const MatrixComplex n, std::complex c, ComplexAndComplexReduction computeOnComplexes); - template MatrixComplex ElementWiseOnComplexMatrices(const MatrixComplex m, const MatrixComplex n, ComplexAndComplexReduction computeOnComplexes); + template MatrixComplex ElementWiseOnMatrixComplexAndComplex(const MatrixComplex n, std::complex c, Preferences::ComplexFormat complexFormat, ComplexAndComplexReduction computeOnComplexes); + template MatrixComplex ElementWiseOnComplexMatrices(const MatrixComplex m, const MatrixComplex n, Preferences::ComplexFormat complexFormat, ComplexAndComplexReduction computeOnComplexes); }; } diff --git a/poincare/include/poincare/arc_cosine.h b/poincare/include/poincare/arc_cosine.h index 0a73494a2..421bf8a9f 100644 --- a/poincare/include/poincare/arc_cosine.h +++ b/poincare/include/poincare/arc_cosine.h @@ -29,12 +29,12 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; //Evaluation - template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit,computeOnComplex); + template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit,computeOnComplex); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/arc_sine.h b/poincare/include/poincare/arc_sine.h index 77a2c9ab8..dd5f030cd 100644 --- a/poincare/include/poincare/arc_sine.h +++ b/poincare/include/poincare/arc_sine.h @@ -28,12 +28,12 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; //Evaluation - template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit,computeOnComplex); + template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit,computeOnComplex); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/arc_tangent.h b/poincare/include/poincare/arc_tangent.h index 71fff6a69..8569eed36 100644 --- a/poincare/include/poincare/arc_tangent.h +++ b/poincare/include/poincare/arc_tangent.h @@ -32,12 +32,12 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; //Evaluation - template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit,computeOnComplex); + template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit,computeOnComplex); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/binomial_coefficient.h b/poincare/include/poincare/binomial_coefficient.h index 0a890a921..1edf2b6ba 100644 --- a/poincare/include/poincare/binomial_coefficient.h +++ b/poincare/include/poincare/binomial_coefficient.h @@ -31,9 +31,9 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - template Complex templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + template Complex templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; }; class BinomialCoefficient final : public Expression { diff --git a/poincare/include/poincare/ceiling.h b/poincare/include/poincare/ceiling.h index 07fa9c7fd..a7880853b 100644 --- a/poincare/include/poincare/ceiling.h +++ b/poincare/include/poincare/ceiling.h @@ -30,12 +30,12 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/complex_argument.h b/poincare/include/poincare/complex_argument.h index dee7b6aed..c770ed433 100644 --- a/poincare/include/poincare/complex_argument.h +++ b/poincare/include/poincare/complex_argument.h @@ -29,12 +29,12 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit,computeOnComplex); + template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit,computeOnComplex); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/complex_cartesian.h b/poincare/include/poincare/complex_cartesian.h index c254083d5..a2d17bfb3 100644 --- a/poincare/include/poincare/complex_cartesian.h +++ b/poincare/include/poincare/complex_cartesian.h @@ -24,14 +24,14 @@ private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override { assert(false); return Layout(); } // Evaluation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) override; private: - template Complex templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + template Complex templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; }; class ComplexCartesian final : public Expression { diff --git a/poincare/include/poincare/confidence_interval.h b/poincare/include/poincare/confidence_interval.h index 9990c74d2..30eda3893 100644 --- a/poincare/include/poincare/confidence_interval.h +++ b/poincare/include/poincare/confidence_interval.h @@ -29,9 +29,9 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; }; class SimplePredictionIntervalNode final : public ConfidenceIntervalNode { diff --git a/poincare/include/poincare/conjugate.h b/poincare/include/poincare/conjugate.h index 8807657cf..ac465b4cc 100644 --- a/poincare/include/poincare/conjugate.h +++ b/poincare/include/poincare/conjugate.h @@ -29,12 +29,12 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit,computeOnComplex); + template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit,computeOnComplex); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/constant.h b/poincare/include/poincare/constant.h index 1945fe818..c5c529b87 100644 --- a/poincare/include/poincare/constant.h +++ b/poincare/include/poincare/constant.h @@ -29,8 +29,8 @@ public: int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; /* Approximation */ - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } /* Symbol properties */ bool isPi() const { return isConstantChar(Ion::Charset::SmallPi); } @@ -46,7 +46,7 @@ private: char m_name[0]; // MUST be the last member variable size_t nodeSize() const override { return sizeof(ConstantNode); } - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; bool isConstantChar(char c) const { const char constantName[2] = {c, 0}; return strcmp(m_name, constantName) == 0; } }; diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index bc9e69322..060384a0b 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -26,7 +26,7 @@ public: Type type() const override { return Type::Cosine; } float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override; - template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Radian); + template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Radian); private: // Layout @@ -35,11 +35,11 @@ private: // Simplication Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit,computeOnComplex); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit,computeOnComplex); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index adc0ecf31..446df5784 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -51,10 +51,10 @@ public: Expression setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Approximation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return Complex(templatedApproximate()); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return Complex(templatedApproximate()); } diff --git a/poincare/include/poincare/derivative.h b/poincare/include/poincare/derivative.h index 5eb690fac..4bb534b37 100644 --- a/poincare/include/poincare/derivative.h +++ b/poincare/include/poincare/derivative.h @@ -36,12 +36,12 @@ private: Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; - template T approximateWithArgument(T x, Context & context, Preferences::AngleUnit angleUnit) const; - template T growthRateAroundAbscissa(T x, T h, Context & context, Preferences::AngleUnit angleUnit) const; - template T riddersApproximation(Context & context, Preferences::AngleUnit angleUnit, T x, T h, T * error) const; + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; + template T approximateWithArgument(T x, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; + template T growthRateAroundAbscissa(T x, T h, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; + template T riddersApproximation(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, T x, T h, T * error) const; // TODO: Change coefficients? constexpr static double k_maxErrorRateOnApproximation = 0.001; constexpr static double k_minInitialRate = 0.01; diff --git a/poincare/include/poincare/determinant.h b/poincare/include/poincare/determinant.h index 2f8b4b0a4..8909acca7 100644 --- a/poincare/include/poincare/determinant.h +++ b/poincare/include/poincare/determinant.h @@ -26,9 +26,9 @@ private: /* Simplification */ Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; /* Approximation */ - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; }; diff --git a/poincare/include/poincare/division.h b/poincare/include/poincare/division.h index b14b45b4c..d330d34ec 100644 --- a/poincare/include/poincare/division.h +++ b/poincare/include/poincare/division.h @@ -27,15 +27,15 @@ public: int polynomialDegree(Context & context, const char * symbolName) const override; // Approximation - virtual Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { + virtual Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return ApproximationHelper::MapReduce( - this, context, angleUnit, compute, + this, context, complexFormat, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } - virtual Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { + virtual Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return ApproximationHelper::MapReduce( - this, context, angleUnit, compute, + this, context, complexFormat, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } @@ -50,12 +50,12 @@ public: private: // Approximation - template static Complex compute(const std::complex c, const std::complex d); - template static MatrixComplex computeOnMatrixAndComplex(const MatrixComplex m, const std::complex c) { - return ApproximationHelper::ElementWiseOnMatrixComplexAndComplex(m, c, compute); + template static Complex compute(const std::complex c, const std::complex d, Preferences::ComplexFormat complexFormat); + template static MatrixComplex computeOnMatrixAndComplex(const MatrixComplex m, const std::complex c, Preferences::ComplexFormat complexFormat) { + return ApproximationHelper::ElementWiseOnMatrixComplexAndComplex(m, c, complexFormat, compute); } - template static MatrixComplex computeOnComplexAndMatrix(const std::complex c, const MatrixComplex n); - template static MatrixComplex computeOnMatrices(const MatrixComplex m, const MatrixComplex n); + template static MatrixComplex computeOnComplexAndMatrix(const std::complex c, const MatrixComplex n, Preferences::ComplexFormat complexFormat); + template static MatrixComplex computeOnMatrices(const MatrixComplex m, const MatrixComplex n, Preferences::ComplexFormat complexFormat); }; class Division final : public Expression { diff --git a/poincare/include/poincare/division_quotient.h b/poincare/include/poincare/division_quotient.h index 2d98fec41..170eaf74a 100644 --- a/poincare/include/poincare/division_quotient.h +++ b/poincare/include/poincare/division_quotient.h @@ -30,9 +30,9 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; }; class DivisionQuotient final : public Expression { diff --git a/poincare/include/poincare/division_remainder.h b/poincare/include/poincare/division_remainder.h index 25c5ecc08..07443c5d2 100644 --- a/poincare/include/poincare/division_remainder.h +++ b/poincare/include/poincare/division_remainder.h @@ -31,9 +31,9 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; }; class DivisionRemainder final : public Expression { diff --git a/poincare/include/poincare/empty_expression.h b/poincare/include/poincare/empty_expression.h index 32557fd8b..0f67887b6 100644 --- a/poincare/include/poincare/empty_expression.h +++ b/poincare/include/poincare/empty_expression.h @@ -26,9 +26,9 @@ private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Evaluation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; }; class EmptyExpression final : public Expression { diff --git a/poincare/include/poincare/equal.h b/poincare/include/poincare/equal.h index 17b863c10..6b91f2d62 100644 --- a/poincare/include/poincare/equal.h +++ b/poincare/include/poincare/equal.h @@ -27,9 +27,9 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Evalutation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; }; class Equal final : public Expression { diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index 9544f1a3e..cc546edd4 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -157,8 +157,8 @@ public: typedef float SinglePrecision; typedef double DoublePrecision; constexpr static int k_maxNumberOfSteps = 10000; - virtual Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const = 0; - virtual Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const = 0; + virtual Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const = 0; + virtual Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const = 0; /* Simplification */ /*!*/ virtual void deepReduceChildren(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target); diff --git a/poincare/include/poincare/factor.h b/poincare/include/poincare/factor.h index 421c6744b..62d340374 100644 --- a/poincare/include/poincare/factor.h +++ b/poincare/include/poincare/factor.h @@ -27,10 +27,10 @@ private: /* Simplification */ Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) override; /* Evaluation */ - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { - return childAtIndex(0)->approximate(T(), context, angleUnit); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + return childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); } }; diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index ec0c1aa35..6b0819b76 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -35,12 +35,12 @@ private: Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) override; // Evaluation - template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit,computeOnComplex); + template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit,computeOnComplex); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } #if 0 diff --git a/poincare/include/poincare/float.h b/poincare/include/poincare/float.h index 059a70e01..039a967ad 100644 --- a/poincare/include/poincare/float.h +++ b/poincare/include/poincare/float.h @@ -48,10 +48,10 @@ public: /* Layout */ Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; /* Evaluation */ - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } private: - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { return Complex((U)m_value); } T m_value; diff --git a/poincare/include/poincare/floor.h b/poincare/include/poincare/floor.h index eb658e0ad..7a823747f 100644 --- a/poincare/include/poincare/floor.h +++ b/poincare/include/poincare/floor.h @@ -32,12 +32,12 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/frac_part.h b/poincare/include/poincare/frac_part.h index 83d0d30c4..9988621c1 100644 --- a/poincare/include/poincare/frac_part.h +++ b/poincare/include/poincare/frac_part.h @@ -32,12 +32,12 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/function.h b/poincare/include/poincare/function.h index bc4de3f24..c12bc6896 100644 --- a/poincare/include/poincare/function.h +++ b/poincare/include/poincare/function.h @@ -41,9 +41,9 @@ private: Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; Expression shallowReplaceReplaceableSymbols(Context & context) override; // Evaluation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override; - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override; - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override; + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override; + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; }; class Function : public SymbolAbstract { diff --git a/poincare/include/poincare/great_common_divisor.h b/poincare/include/poincare/great_common_divisor.h index a6db18e15..b392fede9 100644 --- a/poincare/include/poincare/great_common_divisor.h +++ b/poincare/include/poincare/great_common_divisor.h @@ -29,9 +29,9 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; }; class GreatCommonDivisor final : public Expression { diff --git a/poincare/include/poincare/hyperbolic_arc_cosine.h b/poincare/include/poincare/hyperbolic_arc_cosine.h index e1e86c1ed..aebd357ef 100644 --- a/poincare/include/poincare/hyperbolic_arc_cosine.h +++ b/poincare/include/poincare/hyperbolic_arc_cosine.h @@ -24,12 +24,12 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; //Evaluation - template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit,computeOnComplex); + template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit,computeOnComplex); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/hyperbolic_arc_sine.h b/poincare/include/poincare/hyperbolic_arc_sine.h index 57f0a4f1c..fd7ec2644 100644 --- a/poincare/include/poincare/hyperbolic_arc_sine.h +++ b/poincare/include/poincare/hyperbolic_arc_sine.h @@ -24,12 +24,12 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; //Evaluation - template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit,computeOnComplex); + template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit,computeOnComplex); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/hyperbolic_arc_tangent.h b/poincare/include/poincare/hyperbolic_arc_tangent.h index fa11c457a..01bfe38ab 100644 --- a/poincare/include/poincare/hyperbolic_arc_tangent.h +++ b/poincare/include/poincare/hyperbolic_arc_tangent.h @@ -24,12 +24,12 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; //Evaluation - template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit,computeOnComplex); + template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit,computeOnComplex); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/hyperbolic_cosine.h b/poincare/include/poincare/hyperbolic_cosine.h index c165ca1b2..6764d1948 100644 --- a/poincare/include/poincare/hyperbolic_cosine.h +++ b/poincare/include/poincare/hyperbolic_cosine.h @@ -24,12 +24,12 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; //Evaluation - template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit,computeOnComplex); + template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit,computeOnComplex); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/hyperbolic_sine.h b/poincare/include/poincare/hyperbolic_sine.h index 105163ba7..2acdc7dd7 100644 --- a/poincare/include/poincare/hyperbolic_sine.h +++ b/poincare/include/poincare/hyperbolic_sine.h @@ -24,12 +24,12 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; //Evaluation - template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit,computeOnComplex); + template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit,computeOnComplex); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/hyperbolic_tangent.h b/poincare/include/poincare/hyperbolic_tangent.h index faf011013..d6d887c2e 100644 --- a/poincare/include/poincare/hyperbolic_tangent.h +++ b/poincare/include/poincare/hyperbolic_tangent.h @@ -24,12 +24,12 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; //Evaluation - template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit,computeOnComplex); + template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit,computeOnComplex); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/imaginary_part.h b/poincare/include/poincare/imaginary_part.h index 4637cfac5..06956b66d 100644 --- a/poincare/include/poincare/imaginary_part.h +++ b/poincare/include/poincare/imaginary_part.h @@ -31,14 +31,14 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { + template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { return Complex(std::imag(c)); } - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit,computeOnComplex); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit,computeOnComplex); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/infinity.h b/poincare/include/poincare/infinity.h index 66e9a37c2..a88ecee04 100644 --- a/poincare/include/poincare/infinity.h +++ b/poincare/include/poincare/infinity.h @@ -27,10 +27,10 @@ public: Sign sign(Context * context) const override { return m_negative ? Sign::Negative : Sign::Positive; } // Approximation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(); } diff --git a/poincare/include/poincare/integral.h b/poincare/include/poincare/integral.h index d278ff366..195b7647a 100644 --- a/poincare/include/poincare/integral.h +++ b/poincare/include/poincare/integral.h @@ -33,9 +33,9 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; template struct DetailedResult { @@ -44,12 +44,12 @@ private: }; constexpr static int k_maxNumberOfIterations = 10; #ifdef LAGRANGE_METHOD - template T lagrangeGaussQuadrature(T a, T b, Context & context, Preferences::AngleUnit angleUnit) const; + template T lagrangeGaussQuadrature(T a, T b, Context Context & context, Preferences::AngleUnit angleUnit context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; #else - template DetailedResult kronrodGaussQuadrature(T a, T b, Context & context, Preferences::AngleUnit angleUnit) const; - template T adaptiveQuadrature(T a, T b, T eps, int numberOfIterations, Context & context, Preferences::AngleUnit angleUnit) const; + template DetailedResult kronrodGaussQuadrature(T a, T b, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; + template T adaptiveQuadrature(T a, T b, T eps, int numberOfIterations, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; #endif - template T functionValueAtAbscissa(T x, Context & xcontext, Preferences::AngleUnit angleUnit) const; + template T functionValueAtAbscissa(T x, Context & xcontext, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; }; class Integral final : public Expression { diff --git a/poincare/include/poincare/least_common_multiple.h b/poincare/include/poincare/least_common_multiple.h index 3bb103900..9dcd9e114 100644 --- a/poincare/include/poincare/least_common_multiple.h +++ b/poincare/include/poincare/least_common_multiple.h @@ -29,9 +29,9 @@ private: /* Simplification */ Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; /* Evaluation */ - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; }; class LeastCommonMultiple final : public Expression { diff --git a/poincare/include/poincare/logarithm.h b/poincare/include/poincare/logarithm.h index e77e46dfd..a92b59757 100644 --- a/poincare/include/poincare/logarithm.h +++ b/poincare/include/poincare/logarithm.h @@ -30,15 +30,15 @@ public: Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) override; // Evaluation - template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { + template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { /* log has a branch cut on ]-inf, 0]: it is then multivalued on this cut. We * followed the convention chosen by the lib c++ of llvm on ]-inf+0i, 0+0i] * (warning: log takes the other side of the cut values on ]-inf-0i, 0-0i]). */ return Complex(std::log10(c)); } - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; }; class Logarithm final : public Expression { diff --git a/poincare/include/poincare/matrix.h b/poincare/include/poincare/matrix.h index 270a6267f..cbe0a2c16 100644 --- a/poincare/include/poincare/matrix.h +++ b/poincare/include/poincare/matrix.h @@ -39,18 +39,18 @@ public: int polynomialDegree(Context & context, const char * symbolName) const override; // Approximation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return templatedApproximate(context, angleUnit); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return templatedApproximate(context, complexFormat, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return templatedApproximate(context, angleUnit); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return templatedApproximate(context, complexFormat, angleUnit); } // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = 0) const override; private: - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; /* We could store 2 uint8_t but multiplying m_numberOfRows and * m_numberOfColumns could then lead to overflow. As we are unlikely to use * greater matrix than 100*100, uint16_t is fine. */ diff --git a/poincare/include/poincare/matrix_dimension.h b/poincare/include/poincare/matrix_dimension.h index f1eb57a8d..412072edd 100644 --- a/poincare/include/poincare/matrix_dimension.h +++ b/poincare/include/poincare/matrix_dimension.h @@ -27,9 +27,9 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; }; class MatrixDimension final : public Expression { diff --git a/poincare/include/poincare/matrix_inverse.h b/poincare/include/poincare/matrix_inverse.h index d61bbf1e9..b4488c8c3 100644 --- a/poincare/include/poincare/matrix_inverse.h +++ b/poincare/include/poincare/matrix_inverse.h @@ -26,9 +26,9 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; }; class MatrixInverse final : public Expression { diff --git a/poincare/include/poincare/matrix_trace.h b/poincare/include/poincare/matrix_trace.h index 446022de7..3590ae444 100644 --- a/poincare/include/poincare/matrix_trace.h +++ b/poincare/include/poincare/matrix_trace.h @@ -26,9 +26,9 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; }; class MatrixTrace final : public Expression { diff --git a/poincare/include/poincare/matrix_transpose.h b/poincare/include/poincare/matrix_transpose.h index e6b8a4711..fe7e98ce1 100644 --- a/poincare/include/poincare/matrix_transpose.h +++ b/poincare/include/poincare/matrix_transpose.h @@ -26,9 +26,9 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; }; class MatrixTranspose final : public Expression { diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 2f861777f..dfdf10120 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -26,11 +26,11 @@ public: int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const override; // Approximation - template static Complex compute(const std::complex c, const std::complex d) { return Complex(c*d); } - template static MatrixComplex computeOnComplexAndMatrix(const std::complex c, const MatrixComplex m) { - return ApproximationHelper::ElementWiseOnMatrixComplexAndComplex(m, c, compute); + template static Complex compute(const std::complex c, const std::complex d, Preferences::ComplexFormat complexFormat) { return Complex(c*d); } + template static MatrixComplex computeOnComplexAndMatrix(const std::complex c, const MatrixComplex m, Preferences::ComplexFormat complexFormat) { + return ApproximationHelper::ElementWiseOnMatrixComplexAndComplex(m, c, complexFormat, compute); } - template static MatrixComplex computeOnMatrices(const MatrixComplex m, const MatrixComplex n); + template static MatrixComplex computeOnMatrices(const MatrixComplex m, const MatrixComplex n, Preferences::ComplexFormat complexFormat); private: // Property @@ -49,14 +49,14 @@ private: Expression denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override; /* Approximation */ - template static MatrixComplex computeOnMatrixAndComplex(const MatrixComplex m, const std::complex c) { - return ApproximationHelper::ElementWiseOnMatrixComplexAndComplex(m, c, compute); + template static MatrixComplex computeOnMatrixAndComplex(const MatrixComplex m, const std::complex c, Preferences::ComplexFormat complexFormat) { + return ApproximationHelper::ElementWiseOnMatrixComplexAndComplex(m, c, complexFormat, compute); } - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::MapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::MapReduce(this, context, complexFormat, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::MapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::MapReduce(this, context, complexFormat, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } }; diff --git a/poincare/include/poincare/naperian_logarithm.h b/poincare/include/poincare/naperian_logarithm.h index c8e4dca32..8e2409729 100644 --- a/poincare/include/poincare/naperian_logarithm.h +++ b/poincare/include/poincare/naperian_logarithm.h @@ -27,17 +27,17 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; /* Evaluation */ - template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { + template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { /* ln has a branch cut on ]-inf, 0]: it is then multivalued on this cut. We * followed the convention chosen by the lib c++ of llvm on ]-inf+0i, 0+0i] * (warning: ln takes the other side of the cut values on ]-inf-0i, 0-0i]). */ return Complex(std::log(c)); } - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit,computeOnComplex); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit,computeOnComplex); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/nth_root.h b/poincare/include/poincare/nth_root.h index 2b23add02..2e68e7466 100644 --- a/poincare/include/poincare/nth_root.h +++ b/poincare/include/poincare/nth_root.h @@ -26,9 +26,9 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; }; diff --git a/poincare/include/poincare/opposite.h b/poincare/include/poincare/opposite.h index 91722cff9..9db4dd53d 100644 --- a/poincare/include/poincare/opposite.h +++ b/poincare/include/poincare/opposite.h @@ -10,7 +10,7 @@ class Opposite; class OppositeNode /*final*/ : public ExpressionNode { public: - template static Complex compute(const std::complex c, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Degree) { return Complex(-c); } + template static Complex compute(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Degree) { return Complex(-c); } // TreeNode @@ -28,11 +28,11 @@ public: Sign sign(Context * context) const override; // Approximation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, compute); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, compute); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, compute); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, compute); } // Layout diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index 8974aab03..ed3fd93b0 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -29,10 +29,10 @@ public: Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Approximation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } private: - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; }; class Parenthesis final : public Expression { diff --git a/poincare/include/poincare/permute_coefficient.h b/poincare/include/poincare/permute_coefficient.h index f954da449..4c241bcf5 100644 --- a/poincare/include/poincare/permute_coefficient.h +++ b/poincare/include/poincare/permute_coefficient.h @@ -33,9 +33,9 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; }; class PermuteCoefficient final : public Expression { diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 6ae251a7c..802eb0569 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -32,7 +32,7 @@ public: int polynomialDegree(Context & context, const char * symbolName) const override; int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const override; - template static Complex compute(const std::complex c, const std::complex d); + template static Complex compute(const std::complex c, const std::complex d, Preferences::ComplexFormat complexFormat); private: constexpr static int k_maxApproximatePowerMatrix = 1000; @@ -51,14 +51,14 @@ private: int simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const override; Expression denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override; // Evaluation - template static MatrixComplex computeOnComplexAndMatrix(const std::complex c, const MatrixComplex n); - template static MatrixComplex computeOnMatrixAndComplex(const MatrixComplex m, const std::complex d); - template static MatrixComplex computeOnMatrices(const MatrixComplex m, const MatrixComplex n); - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::MapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); + template static MatrixComplex computeOnComplexAndMatrix(const std::complex c, const MatrixComplex n, Preferences::ComplexFormat complexFormat); + template static MatrixComplex computeOnMatrixAndComplex(const MatrixComplex m, const std::complex d, Preferences::ComplexFormat complexFormat); + template static MatrixComplex computeOnMatrices(const MatrixComplex m, const MatrixComplex n, Preferences::ComplexFormat complexFormat); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::MapReduce(this, context, complexFormat, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::MapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::MapReduce(this, context, complexFormat, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } }; diff --git a/poincare/include/poincare/prediction_interval.h b/poincare/include/poincare/prediction_interval.h index 0c79083ed..8ff5633f0 100644 --- a/poincare/include/poincare/prediction_interval.h +++ b/poincare/include/poincare/prediction_interval.h @@ -29,9 +29,9 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; }; class PredictionInterval final : public Expression { diff --git a/poincare/include/poincare/product.h b/poincare/include/poincare/product.h index fd98fa751..02701a19d 100644 --- a/poincare/include/poincare/product.h +++ b/poincare/include/poincare/product.h @@ -22,13 +22,13 @@ private: float emptySequenceValue() const override { return 1.0f; } Layout createSequenceLayout(Layout argumentLayout, Layout symbolLayout, Layout subscriptLayout, Layout superscriptLayout) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; - Evaluation evaluateWithNextTerm(DoublePrecision p, Evaluation a, Evaluation b) const override { - return templatedApproximateWithNextTerm(a, b); + Evaluation evaluateWithNextTerm(DoublePrecision p, Evaluation a, Evaluation b, Preferences::ComplexFormat complexFormat) const override { + return templatedApproximateWithNextTerm(a, b, complexFormat); } - Evaluation evaluateWithNextTerm(SinglePrecision p, Evaluation a, Evaluation b) const override { - return templatedApproximateWithNextTerm(a, b); + Evaluation evaluateWithNextTerm(SinglePrecision p, Evaluation a, Evaluation b, Preferences::ComplexFormat complexFormat) const override { + return templatedApproximateWithNextTerm(a, b, complexFormat); } - template Evaluation templatedApproximateWithNextTerm(Evaluation a, Evaluation b) const; + template Evaluation templatedApproximateWithNextTerm(Evaluation a, Evaluation b, Preferences::ComplexFormat complexFormat) const; }; class Product final : public Expression { diff --git a/poincare/include/poincare/randint.h b/poincare/include/poincare/randint.h index c1e7de0c0..5f549a75d 100644 --- a/poincare/include/poincare/randint.h +++ b/poincare/include/poincare/randint.h @@ -28,13 +28,13 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Evaluation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return templateApproximate(context, angleUnit); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return templateApproximate(context, complexFormat, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return templateApproximate(context, angleUnit); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return templateApproximate(context, complexFormat, angleUnit); } - template Evaluation templateApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + template Evaluation templateApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; }; class Randint final : public Expression { diff --git a/poincare/include/poincare/random.h b/poincare/include/poincare/random.h index 524da8c9c..30cc8dbb9 100644 --- a/poincare/include/poincare/random.h +++ b/poincare/include/poincare/random.h @@ -30,10 +30,10 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Evaluation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templateApproximate(); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templateApproximate(); } template Evaluation templateApproximate() const; diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index 4998873ab..99009e4f2 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -42,8 +42,8 @@ public: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Approximation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return Complex(templatedApproximate()); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return Complex(templatedApproximate()); } + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return Complex(templatedApproximate()); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return Complex(templatedApproximate()); } template T templatedApproximate() const; // Basic test diff --git a/poincare/include/poincare/real_part.h b/poincare/include/poincare/real_part.h index 28aa30832..e9107a486 100644 --- a/poincare/include/poincare/real_part.h +++ b/poincare/include/poincare/real_part.h @@ -31,14 +31,14 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { + template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { return Complex(std::real(c)); } - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit,computeOnComplex); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit,computeOnComplex); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/round.h b/poincare/include/poincare/round.h index b3e2ba47c..a219cc775 100644 --- a/poincare/include/poincare/round.h +++ b/poincare/include/poincare/round.h @@ -30,9 +30,9 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; }; class Round final : public Expression { diff --git a/poincare/include/poincare/sequence.h b/poincare/include/poincare/sequence.h index 36fe8eb7c..e732c744e 100644 --- a/poincare/include/poincare/sequence.h +++ b/poincare/include/poincare/sequence.h @@ -14,12 +14,12 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; virtual Layout createSequenceLayout(Layout argumentLayout, Layout symbolLayout, Layout subscriptLayout, Layout superscriptLayout) const = 0; /* Approximation */ - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; virtual float emptySequenceValue() const = 0; - virtual Evaluation evaluateWithNextTerm(SinglePrecision p, Evaluation a, Evaluation b) const = 0; - virtual Evaluation evaluateWithNextTerm(DoublePrecision p, Evaluation a, Evaluation b) const = 0; + virtual Evaluation evaluateWithNextTerm(SinglePrecision p, Evaluation a, Evaluation b, Preferences::ComplexFormat complexFormat) const = 0; + virtual Evaluation evaluateWithNextTerm(DoublePrecision p, Evaluation a, Evaluation b, Preferences::ComplexFormat complexFormat) const = 0; }; } diff --git a/poincare/include/poincare/sign_function.h b/poincare/include/poincare/sign_function.h index 464c79829..9bb83d47e 100644 --- a/poincare/include/poincare/sign_function.h +++ b/poincare/include/poincare/sign_function.h @@ -33,12 +33,12 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index a36f2b3e0..393ae365c 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -26,7 +26,7 @@ public: Type type() const override { return Type::Sine; } float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override; - template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Radian); + template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Radian); private: // Layout @@ -37,11 +37,11 @@ private: Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit,computeOnComplex); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit,computeOnComplex); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/square_root.h b/poincare/include/poincare/square_root.h index 7c692a0c2..4a1401c69 100644 --- a/poincare/include/poincare/square_root.h +++ b/poincare/include/poincare/square_root.h @@ -29,12 +29,12 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit); - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit,computeOnComplex); + template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit,computeOnComplex); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/store.h b/poincare/include/poincare/store.h index f46042765..2efa3013b 100644 --- a/poincare/include/poincare/store.h +++ b/poincare/include/poincare/store.h @@ -31,9 +31,9 @@ private: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Evalutation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; }; class Store final : public Expression { diff --git a/poincare/include/poincare/subtraction.h b/poincare/include/poincare/subtraction.h index 34df24d31..393c0e13a 100644 --- a/poincare/include/poincare/subtraction.h +++ b/poincare/include/poincare/subtraction.h @@ -25,12 +25,12 @@ public: int polynomialDegree(Context & context, const char * symbolName) const override; // Approximation - template static Complex compute(const std::complex c, const std::complex d) { return Complex(c - d); } - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::MapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); + template static Complex compute(const std::complex c, const std::complex d, Preferences::ComplexFormat complexFormat) { return Complex(c - d); } + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::MapReduce(this, context, complexFormat, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::MapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::MapReduce(this, context, complexFormat, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } /* Layout */ @@ -43,12 +43,12 @@ public: private: /* Evaluation */ - template static MatrixComplex computeOnMatrixAndComplex(const MatrixComplex m, const std::complex c) { - return ApproximationHelper::ElementWiseOnMatrixComplexAndComplex(m, c, compute); + template static MatrixComplex computeOnMatrixAndComplex(const MatrixComplex m, const std::complex c, Preferences::ComplexFormat complexFormat) { + return ApproximationHelper::ElementWiseOnMatrixComplexAndComplex(m, c, complexFormat, compute); } - template static MatrixComplex computeOnComplexAndMatrix(const std::complex c, const MatrixComplex n); - template static MatrixComplex computeOnMatrices(const MatrixComplex m, const MatrixComplex n) { - return ApproximationHelper::ElementWiseOnComplexMatrices(m, n, compute); + template static MatrixComplex computeOnComplexAndMatrix(const std::complex c, const MatrixComplex n, Preferences::ComplexFormat complexFormat); + template static MatrixComplex computeOnMatrices(const MatrixComplex m, const MatrixComplex n, Preferences::ComplexFormat complexFormat) { + return ApproximationHelper::ElementWiseOnComplexMatrices(m, n, complexFormat, compute); } }; diff --git a/poincare/include/poincare/sum.h b/poincare/include/poincare/sum.h index 0ac12d2b1..515290d56 100644 --- a/poincare/include/poincare/sum.h +++ b/poincare/include/poincare/sum.h @@ -22,13 +22,13 @@ private: float emptySequenceValue() const override { return 0.0f; } Layout createSequenceLayout(Layout argumentLayout, Layout symbolLayout, Layout subscriptLayout, Layout superscriptLayout) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; - Evaluation evaluateWithNextTerm(DoublePrecision p, Evaluation a, Evaluation b) const override { - return templatedApproximateWithNextTerm(a, b); + Evaluation evaluateWithNextTerm(DoublePrecision p, Evaluation a, Evaluation b, Preferences::ComplexFormat complexFormat) const override { + return templatedApproximateWithNextTerm(a, b, complexFormat); } - Evaluation evaluateWithNextTerm(SinglePrecision p, Evaluation a, Evaluation b) const override { - return templatedApproximateWithNextTerm(a, b); + Evaluation evaluateWithNextTerm(SinglePrecision p, Evaluation a, Evaluation b, Preferences::ComplexFormat complexFormat) const override { + return templatedApproximateWithNextTerm(a, b, complexFormat); } - template Evaluation templatedApproximateWithNextTerm(Evaluation a, Evaluation b) const; + template Evaluation templatedApproximateWithNextTerm(Evaluation a, Evaluation b, Preferences::ComplexFormat complexFormat) const; }; class Sum final : public Expression { diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index 027730740..e1fc8bf19 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -38,14 +38,14 @@ public: Expression shallowReplaceReplaceableSymbols(Context & context) override; /* Approximation */ - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } private: char m_name[0]; // MUST be the last member variable size_t nodeSize() const override { return sizeof(SymbolNode); } - template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; }; class Symbol final : public SymbolAbstract { diff --git a/poincare/include/poincare/tangent.h b/poincare/include/poincare/tangent.h index 53535af37..dc271379a 100644 --- a/poincare/include/poincare/tangent.h +++ b/poincare/include/poincare/tangent.h @@ -34,12 +34,12 @@ private: Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation - template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Radian); - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit,computeOnComplex); + template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Radian); + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit,computeOnComplex); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/undefined.h b/poincare/include/poincare/undefined.h index 25cffc411..1d76553bb 100644 --- a/poincare/include/poincare/undefined.h +++ b/poincare/include/poincare/undefined.h @@ -25,10 +25,10 @@ public: Expression setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Approximation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(); } diff --git a/poincare/include/poincare/unreal.h b/poincare/include/poincare/unreal.h index d004f8bc2..23e0f78b2 100644 --- a/poincare/include/poincare/unreal.h +++ b/poincare/include/poincare/unreal.h @@ -20,10 +20,10 @@ public: Type type() const override { return Type::Unreal; } // Approximation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(); } diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 9111efbec..6ad13fa66 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -49,7 +49,7 @@ Expression AbsoluteValue::shallowReduce(Context & context, Preferences::ComplexF #endif Expression c = childAtIndex(0); if (c.isReal(context)) { - float app = c.node()->approximate(float(), context, angleUnit).toScalar(); + float app = c.node()->approximate(float(), context, complexFormat, angleUnit).toScalar(); if (!std::isnan(app) && app >= Expression::Epsilon()) { // abs(a) = a with a > 0 replaceWithInPlace(c); diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index abaf601bf..6292b370a 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -418,13 +418,13 @@ void Addition::factorizeChildrenAtIndexesInPlace(int index1, int index2, Context m.shallowReduce(context, complexFormat, angleUnit, target); } -template Complex Poincare::AdditionNode::compute(std::complex, std::complex); -template Complex Poincare::AdditionNode::compute(std::complex, std::complex); +template Complex Poincare::AdditionNode::compute(std::complex, std::complex, Preferences::ComplexFormat); +template Complex Poincare::AdditionNode::compute(std::complex, std::complex, Preferences::ComplexFormat); -template MatrixComplex AdditionNode::computeOnMatrices(const MatrixComplex,const MatrixComplex); -template MatrixComplex AdditionNode::computeOnMatrices(const MatrixComplex,const MatrixComplex); +template MatrixComplex AdditionNode::computeOnMatrices(const MatrixComplex,const MatrixComplex, Preferences::ComplexFormat complexFormat); +template MatrixComplex AdditionNode::computeOnMatrices(const MatrixComplex,const MatrixComplex, Preferences::ComplexFormat complexFormat); -template MatrixComplex AdditionNode::computeOnComplexAndMatrix(std::complex const, const MatrixComplex); -template MatrixComplex AdditionNode::computeOnComplexAndMatrix(std::complex const, const MatrixComplex); +template MatrixComplex AdditionNode::computeOnComplexAndMatrix(std::complex const, const MatrixComplex, Preferences::ComplexFormat complexFormat); +template MatrixComplex AdditionNode::computeOnComplexAndMatrix(std::complex const, const MatrixComplex, Preferences::ComplexFormat complexFormat); } diff --git a/poincare/src/approximation_helper.cpp b/poincare/src/approximation_helper.cpp index e0dfb7387..e77e39c27 100644 --- a/poincare/src/approximation_helper.cpp +++ b/poincare/src/approximation_helper.cpp @@ -26,41 +26,41 @@ template std::complex ApproximationHelper::TruncateRealOrImagina return c; } -template Evaluation ApproximationHelper::Map(const ExpressionNode * expression, Context& context, Preferences::AngleUnit angleUnit, ComplexCompute compute) { +template Evaluation ApproximationHelper::Map(const ExpressionNode * expression, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ComplexCompute compute) { assert(expression->numberOfChildren() == 1); - Evaluation input = expression->childAtIndex(0)->approximate(T(), context, angleUnit); + Evaluation input = expression->childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); if (input.type() == EvaluationNode::Type::Complex) { - return compute(static_cast &>(input).stdComplex(), angleUnit); + return compute(static_cast &>(input).stdComplex(), complexFormat, angleUnit); } else { assert(input.type() == EvaluationNode::Type::MatrixComplex); MatrixComplex m = static_cast &>(input); MatrixComplex result; for (int i = 0; i < m.numberOfChildren(); i++) { - result.addChildAtIndexInPlace(compute(m.complexAtIndex(i), angleUnit), i, i); + result.addChildAtIndexInPlace(compute(m.complexAtIndex(i), complexFormat, angleUnit), i, i); } result.setDimensions(m.numberOfRows(), m.numberOfColumns()); return result; } } -template Evaluation ApproximationHelper::MapReduce(const ExpressionNode * expression, Context& context, Preferences::AngleUnit angleUnit, ComplexAndComplexReduction computeOnComplexes, ComplexAndMatrixReduction computeOnComplexAndMatrix, MatrixAndComplexReduction computeOnMatrixAndComplex, MatrixAndMatrixReduction computeOnMatrices) { +template Evaluation ApproximationHelper::MapReduce(const ExpressionNode * expression, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ComplexAndComplexReduction computeOnComplexes, ComplexAndMatrixReduction computeOnComplexAndMatrix, MatrixAndComplexReduction computeOnMatrixAndComplex, MatrixAndMatrixReduction computeOnMatrices) { assert(expression->numberOfChildren() > 0); - Evaluation result = expression->childAtIndex(0)->approximate(T(), context, angleUnit); + Evaluation result = expression->childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); for (int i = 1; i < expression->numberOfChildren(); i++) { Evaluation intermediateResult; - Evaluation nextOperandEvaluation = expression->childAtIndex(i)->approximate(T(), context, angleUnit); + Evaluation nextOperandEvaluation = expression->childAtIndex(i)->approximate(T(), context, complexFormat, angleUnit); if (result.type() == EvaluationNode::Type::Complex && nextOperandEvaluation.type() == EvaluationNode::Type::Complex) { - intermediateResult = computeOnComplexes(static_cast &>(result).stdComplex(), static_cast &>(nextOperandEvaluation).stdComplex()); + intermediateResult = computeOnComplexes(static_cast &>(result).stdComplex(), static_cast &>(nextOperandEvaluation).stdComplex(), complexFormat); } else if (result.type() == EvaluationNode::Type::Complex) { assert(nextOperandEvaluation.type() == EvaluationNode::Type::MatrixComplex); - intermediateResult = computeOnComplexAndMatrix(static_cast &>(result).stdComplex(), static_cast &>(nextOperandEvaluation)); + intermediateResult = computeOnComplexAndMatrix(static_cast &>(result).stdComplex(), static_cast &>(nextOperandEvaluation), complexFormat); } else if (nextOperandEvaluation.type() == EvaluationNode::Type::Complex) { assert(result.type() == EvaluationNode::Type::MatrixComplex); - intermediateResult = computeOnMatrixAndComplex(static_cast &>(result), static_cast &>(nextOperandEvaluation).stdComplex()); + intermediateResult = computeOnMatrixAndComplex(static_cast &>(result), static_cast &>(nextOperandEvaluation).stdComplex(), complexFormat); } else { assert(result.node()->type() == EvaluationNode::Type::MatrixComplex); assert(nextOperandEvaluation.node()->type() == EvaluationNode::Type::MatrixComplex); - intermediateResult = computeOnMatrices(static_cast &>(result), static_cast &>(nextOperandEvaluation)); + intermediateResult = computeOnMatrices(static_cast &>(result), static_cast &>(nextOperandEvaluation), complexFormat); } result = intermediateResult; if (result.isUndefined()) { @@ -70,22 +70,22 @@ template Evaluation ApproximationHelper::MapReduce(const Expressi return result; } -template MatrixComplex ApproximationHelper::ElementWiseOnMatrixComplexAndComplex(const MatrixComplex m, const std::complex c, ComplexAndComplexReduction computeOnComplexes) { +template MatrixComplex ApproximationHelper::ElementWiseOnMatrixComplexAndComplex(const MatrixComplex m, const std::complex c, Poincare::Preferences::ComplexFormat complexFormat, ComplexAndComplexReduction computeOnComplexes) { MatrixComplex matrix; for (int i = 0; i < m.numberOfChildren(); i++) { - matrix.addChildAtIndexInPlace(computeOnComplexes(m.complexAtIndex(i), c), i, i); + matrix.addChildAtIndexInPlace(computeOnComplexes(m.complexAtIndex(i), c, complexFormat), i, i); } matrix.setDimensions(m.numberOfRows(), m.numberOfColumns()); return matrix; } -template MatrixComplex ApproximationHelper::ElementWiseOnComplexMatrices(const MatrixComplex m, const MatrixComplex n, ComplexAndComplexReduction computeOnComplexes) { +template MatrixComplex ApproximationHelper::ElementWiseOnComplexMatrices(const MatrixComplex m, const MatrixComplex n, Poincare::Preferences::ComplexFormat complexFormat, ComplexAndComplexReduction computeOnComplexes) { if (m.numberOfRows() != n.numberOfRows() || m.numberOfColumns() != n.numberOfColumns()) { return MatrixComplex::Undefined(); } MatrixComplex matrix; for (int i = 0; i < m.numberOfChildren(); i++) { - matrix.addChildAtIndexInPlace(computeOnComplexes(m.complexAtIndex(i), n.complexAtIndex(i)), i, i); + matrix.addChildAtIndexInPlace(computeOnComplexes(m.complexAtIndex(i), n.complexAtIndex(i), complexFormat), i, i); } matrix.setDimensions(m.numberOfRows(), m.numberOfColumns()); return matrix; @@ -93,14 +93,14 @@ template MatrixComplex ApproximationHelper::ElementWiseOnComplexM template std::complex Poincare::ApproximationHelper::TruncateRealOrImaginaryPartAccordingToArgument(std::complex); template std::complex Poincare::ApproximationHelper::TruncateRealOrImaginaryPartAccordingToArgument(std::complex); -template Poincare::Evaluation Poincare::ApproximationHelper::Map(const Poincare::ExpressionNode * expression, Poincare::Context& context, Poincare::Preferences::AngleUnit angleUnit, Poincare::ApproximationHelper::ComplexCompute compute); -template Poincare::Evaluation Poincare::ApproximationHelper::Map(const Poincare::ExpressionNode * expression, Poincare::Context& context, Poincare::Preferences::AngleUnit angleUnit, Poincare::ApproximationHelper::ComplexCompute compute); -template Poincare::Evaluation Poincare::ApproximationHelper::MapReduce(const Poincare::ExpressionNode * expression, Poincare::Context& context, Poincare::Preferences::AngleUnit angleUnit, Poincare::ApproximationHelper::ComplexAndComplexReduction computeOnComplexes, Poincare::ApproximationHelper::ComplexAndMatrixReduction computeOnComplexAndMatrix, Poincare::ApproximationHelper::MatrixAndComplexReduction computeOnMatrixAndComplex, Poincare::ApproximationHelper::MatrixAndMatrixReduction computeOnMatrices); -template Poincare::Evaluation Poincare::ApproximationHelper::MapReduce(const Poincare::ExpressionNode * expression, Poincare::Context& context, Poincare::Preferences::AngleUnit angleUnit, Poincare::ApproximationHelper::ComplexAndComplexReduction computeOnComplexes, Poincare::ApproximationHelper::ComplexAndMatrixReduction computeOnComplexAndMatrix, Poincare::ApproximationHelper::MatrixAndComplexReduction computeOnMatrixAndComplex, Poincare::ApproximationHelper::MatrixAndMatrixReduction computeOnMatrices); -template Poincare::MatrixComplex Poincare::ApproximationHelper::ElementWiseOnMatrixComplexAndComplex(const Poincare::MatrixComplex, const std::complex, Poincare::Complex (*)(std::complex, std::complex)); -template Poincare::MatrixComplex Poincare::ApproximationHelper::ElementWiseOnMatrixComplexAndComplex(const Poincare::MatrixComplex, std::complex const, Poincare::Complex (*)(std::complex, std::complex)); -template Poincare::MatrixComplex Poincare::ApproximationHelper::ElementWiseOnComplexMatrices(const Poincare::MatrixComplex, const Poincare::MatrixComplex, Poincare::Complex (*)(std::complex, std::complex)); -template Poincare::MatrixComplex Poincare::ApproximationHelper::ElementWiseOnComplexMatrices(const Poincare::MatrixComplex, const Poincare::MatrixComplex, Poincare::Complex (*)(std::complex, std::complex)); +template Poincare::Evaluation Poincare::ApproximationHelper::Map(const Poincare::ExpressionNode * expression, Poincare::Context& context, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit angleUnit, Poincare::ApproximationHelper::ComplexCompute compute); +template Poincare::Evaluation Poincare::ApproximationHelper::Map(const Poincare::ExpressionNode * expression, Poincare::Context& context, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit angleUnit, Poincare::ApproximationHelper::ComplexCompute compute); +template Poincare::Evaluation Poincare::ApproximationHelper::MapReduce(const Poincare::ExpressionNode * expression, Poincare::Context& context, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit angleUnit, Poincare::ApproximationHelper::ComplexAndComplexReduction computeOnComplexes, Poincare::ApproximationHelper::ComplexAndMatrixReduction computeOnComplexAndMatrix, Poincare::ApproximationHelper::MatrixAndComplexReduction computeOnMatrixAndComplex, Poincare::ApproximationHelper::MatrixAndMatrixReduction computeOnMatrices); +template Poincare::Evaluation Poincare::ApproximationHelper::MapReduce(const Poincare::ExpressionNode * expression, Poincare::Context& context, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit angleUnit, Poincare::ApproximationHelper::ComplexAndComplexReduction computeOnComplexes, Poincare::ApproximationHelper::ComplexAndMatrixReduction computeOnComplexAndMatrix, Poincare::ApproximationHelper::MatrixAndComplexReduction computeOnMatrixAndComplex, Poincare::ApproximationHelper::MatrixAndMatrixReduction computeOnMatrices); +template Poincare::MatrixComplex Poincare::ApproximationHelper::ElementWiseOnMatrixComplexAndComplex(const Poincare::MatrixComplex, const std::complex, Poincare::Preferences::ComplexFormat, Poincare::Complex (*)(std::complex, std::complex, Poincare::Preferences::ComplexFormat)); +template Poincare::MatrixComplex Poincare::ApproximationHelper::ElementWiseOnMatrixComplexAndComplex(const Poincare::MatrixComplex, std::complex const, Poincare::Preferences::ComplexFormat, Poincare::Complex (*)(std::complex, std::complex, Poincare::Preferences::ComplexFormat)); +template Poincare::MatrixComplex Poincare::ApproximationHelper::ElementWiseOnComplexMatrices(const Poincare::MatrixComplex, const Poincare::MatrixComplex, Poincare::Preferences::ComplexFormat, Poincare::Complex (*)(std::complex, std::complex, Poincare::Preferences::ComplexFormat)); +template Poincare::MatrixComplex Poincare::ApproximationHelper::ElementWiseOnComplexMatrices(const Poincare::MatrixComplex, const Poincare::MatrixComplex, Poincare::Preferences::ComplexFormat, Poincare::Complex (*)(std::complex, std::complex, Poincare::Preferences::ComplexFormat)); } diff --git a/poincare/src/arc_cosine.cpp b/poincare/src/arc_cosine.cpp index 6e5538a2e..100e52963 100644 --- a/poincare/src/arc_cosine.cpp +++ b/poincare/src/arc_cosine.cpp @@ -24,7 +24,7 @@ Expression ArcCosineNode::shallowReduce(Context & context, Preferences::ComplexF } template -Complex ArcCosineNode::computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { +Complex ArcCosineNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { std::complex result; if (c.imag() == 0 && std::fabs(c.real()) <= 1.0) { /* acos: [-1;1] -> R diff --git a/poincare/src/arc_sine.cpp b/poincare/src/arc_sine.cpp index d117a404a..4493f0e2b 100644 --- a/poincare/src/arc_sine.cpp +++ b/poincare/src/arc_sine.cpp @@ -24,7 +24,7 @@ Expression ArcSineNode::shallowReduce(Context & context, Preferences::ComplexFor } template -Complex ArcSineNode::computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { +Complex ArcSineNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { std::complex result; if (c.imag() == 0 && std::fabs(c.real()) <= 1.0) { /* asin: [-1;1] -> R diff --git a/poincare/src/arc_tangent.cpp b/poincare/src/arc_tangent.cpp index e73346485..917b2bc55 100644 --- a/poincare/src/arc_tangent.cpp +++ b/poincare/src/arc_tangent.cpp @@ -20,7 +20,7 @@ int ArcTangentNode::serialize(char * buffer, int bufferSize, Preferences::PrintF } template -Complex ArcTangentNode::computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { +Complex ArcTangentNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { std::complex result; if (c.imag() == 0 && std::fabs(c.real()) <= 1.0) { /* atan: R -> R diff --git a/poincare/src/binomial_coefficient.cpp b/poincare/src/binomial_coefficient.cpp index cf9f9b3ac..84ad781fb 100644 --- a/poincare/src/binomial_coefficient.cpp +++ b/poincare/src/binomial_coefficient.cpp @@ -29,9 +29,9 @@ int BinomialCoefficientNode::serialize(char * buffer, int bufferSize, Preference } template -Complex BinomialCoefficientNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { - Evaluation nInput = childAtIndex(0)->approximate(T(), context, angleUnit); - Evaluation kInput = childAtIndex(1)->approximate(T(), context, angleUnit); +Complex BinomialCoefficientNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + Evaluation nInput = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); + Evaluation kInput = childAtIndex(1)->approximate(T(), context, complexFormat, angleUnit); T n = nInput.toScalar(); T k = kInput.toScalar(); return Complex(compute(k, n)); diff --git a/poincare/src/ceiling.cpp b/poincare/src/ceiling.cpp index 8d8139a25..7233b0af3 100644 --- a/poincare/src/ceiling.cpp +++ b/poincare/src/ceiling.cpp @@ -24,7 +24,7 @@ int CeilingNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloa } template -Complex CeilingNode::computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { +Complex CeilingNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { if (c.imag() != 0) { return Complex::Undefined(); } diff --git a/poincare/src/complex_argument.cpp b/poincare/src/complex_argument.cpp index 10ce8c9d3..679ec064b 100644 --- a/poincare/src/complex_argument.cpp +++ b/poincare/src/complex_argument.cpp @@ -29,7 +29,7 @@ Expression ComplexArgumentNode::shallowReduce(Context & context, Preferences::Co } template -Complex ComplexArgumentNode::computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { +Complex ComplexArgumentNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { return Complex(std::arg(c)); } @@ -48,7 +48,7 @@ Expression ComplexArgument::shallowReduce(Context & context, Preferences::Comple #endif bool real = c.isReal(context); if (real) { - float app = c.node()->approximate(float(), context, angleUnit).toScalar(); + float app = c.node()->approximate(float(), context, complexFormat, angleUnit).toScalar(); if (!std::isnan(app) && app >= Expression::Epsilon()) { // arg(x) = 0 if x > 0 Expression result = Rational(0); diff --git a/poincare/src/complex_cartesian.cpp b/poincare/src/complex_cartesian.cpp index 23de92eab..83b6725ce 100644 --- a/poincare/src/complex_cartesian.cpp +++ b/poincare/src/complex_cartesian.cpp @@ -28,9 +28,9 @@ Expression ComplexCartesianNode::shallowBeautify(Context & context, Preferences: } template -Complex ComplexCartesianNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { - Evaluation realEvaluation = childAtIndex(0)->approximate(T(), context, angleUnit); - Evaluation imagEvalution = childAtIndex(1)->approximate(T(), context, angleUnit); +Complex ComplexCartesianNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + Evaluation realEvaluation = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); + Evaluation imagEvalution = childAtIndex(1)->approximate(T(), context, complexFormat, angleUnit); assert(realEvaluation.type() == EvaluationNode::Type::Complex); assert(imagEvalution.type() == EvaluationNode::Type::Complex); std::complex a = static_cast &>(realEvaluation).stdComplex(); diff --git a/poincare/src/confidence_interval.cpp b/poincare/src/confidence_interval.cpp index f110f94a8..1bf839197 100644 --- a/poincare/src/confidence_interval.cpp +++ b/poincare/src/confidence_interval.cpp @@ -30,9 +30,9 @@ Expression ConfidenceIntervalNode::shallowReduce(Context & context, Preferences: } template -Evaluation ConfidenceIntervalNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { - Evaluation fInput = childAtIndex(0)->approximate(T(), context, angleUnit); - Evaluation nInput = childAtIndex(1)->approximate(T(), context, angleUnit); +Evaluation ConfidenceIntervalNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + Evaluation fInput = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); + Evaluation nInput = childAtIndex(1)->approximate(T(), context, complexFormat, angleUnit); T f = static_cast &>(fInput).toScalar(); T n = static_cast &>(nInput).toScalar(); if (std::isnan(f) || std::isnan(n) || n != (int)n || n < 0 || f < 0 || f > 1) { diff --git a/poincare/src/conjugate.cpp b/poincare/src/conjugate.cpp index 8593b1053..1b4467812 100644 --- a/poincare/src/conjugate.cpp +++ b/poincare/src/conjugate.cpp @@ -28,7 +28,7 @@ Expression ConjugateNode::shallowReduce(Context & context, Preferences::ComplexF } template -Complex ConjugateNode::computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { +Complex ConjugateNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { return Complex(std::conj(c)); } diff --git a/poincare/src/constant.cpp b/poincare/src/constant.cpp index b6e39cedb..a6df6544e 100644 --- a/poincare/src/constant.cpp +++ b/poincare/src/constant.cpp @@ -56,7 +56,7 @@ int ConstantNode::serialize(char * buffer, int bufferSize, Preferences::PrintFlo } template -Evaluation ConstantNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { +Evaluation ConstantNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { if (isIComplex()) { assert(m_name[1] == 0); return Complex(0.0, 1.0); @@ -90,6 +90,6 @@ Expression Constant::shallowReduce(Context & context, Preferences::ComplexFormat return *this; } -template Evaluation ConstantNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; -template Evaluation ConstantNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; +template Evaluation ConstantNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; +template Evaluation ConstantNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; } diff --git a/poincare/src/cosine.cpp b/poincare/src/cosine.cpp index 84c66fc5c..b0070ff20 100644 --- a/poincare/src/cosine.cpp +++ b/poincare/src/cosine.cpp @@ -16,7 +16,7 @@ float CosineNode::characteristicXRange(Context & context, Preferences::AngleUnit } template -Complex CosineNode::computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { +Complex CosineNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { std::complex angleInput = Trigonometry::ConvertToRadian(c, angleUnit); std::complex res = std::cos(angleInput); return Complex(Trigonometry::RoundToMeaningfulDigits(res, angleInput)); diff --git a/poincare/src/derivative.cpp b/poincare/src/derivative.cpp index a6675617f..fffecd1b1 100644 --- a/poincare/src/derivative.cpp +++ b/poincare/src/derivative.cpp @@ -44,12 +44,12 @@ Expression DerivativeNode::shallowReduce(Context & context, Preferences::Complex } template -Evaluation DerivativeNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { +Evaluation DerivativeNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { static T min = sizeof(T) == sizeof(double) ? DBL_MIN : FLT_MIN; static T epsilon = sizeof(T) == sizeof(double) ? DBL_EPSILON : FLT_EPSILON; - Evaluation evaluationArgumentInput = childAtIndex(2)->approximate(T(), context, angleUnit); + Evaluation evaluationArgumentInput = childAtIndex(2)->approximate(T(), context, complexFormat, angleUnit); T evaluationArgument = evaluationArgumentInput.toScalar(); - T functionValue = approximateWithArgument(evaluationArgument, context, angleUnit); + T functionValue = approximateWithArgument(evaluationArgument, context, complexFormat, angleUnit); // No complex/matrix version of Derivative if (std::isnan(evaluationArgument) || std::isnan(functionValue)) { return Complex::Undefined(); @@ -58,7 +58,7 @@ Evaluation DerivativeNode::templatedApproximate(Context& context, Preferences T error, result; T h = k_minInitialRate; do { - result = riddersApproximation(context, angleUnit, evaluationArgument, h, &error); + result = riddersApproximation(context, complexFormat, angleUnit, evaluationArgument, h, &error); h /= 10.0; } while ((std::fabs(error/result) > k_maxErrorRateOnApproximation || std::isnan(error)) && h >= epsilon); @@ -74,23 +74,23 @@ Evaluation DerivativeNode::templatedApproximate(Context& context, Preferences } template -T DerivativeNode::approximateWithArgument(T x, Context & context, Preferences::AngleUnit angleUnit) const { +T DerivativeNode::approximateWithArgument(T x, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { assert(childAtIndex(1)->type() == Type::Symbol); VariableContext variableContext = VariableContext(static_cast(childAtIndex(1))->name(), &context); variableContext.setApproximationForVariable(x); // Here we cannot use Expression::approximateWithValueForSymbol which would reset the sApproximationEncounteredComplex flag - return childAtIndex(0)->approximate(T(), variableContext, angleUnit).toScalar(); + return childAtIndex(0)->approximate(T(), variableContext, complexFormat, angleUnit).toScalar(); } template -T DerivativeNode::growthRateAroundAbscissa(T x, T h, Context & context, Preferences::AngleUnit angleUnit) const { - T expressionPlus = approximateWithArgument(x+h, context, angleUnit); - T expressionMinus = approximateWithArgument(x-h, context, angleUnit); +T DerivativeNode::growthRateAroundAbscissa(T x, T h, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + T expressionPlus = approximateWithArgument(x+h, context, complexFormat, angleUnit); + T expressionMinus = approximateWithArgument(x-h, context, complexFormat, angleUnit); return (expressionPlus - expressionMinus)/(2*h); } template -T DerivativeNode::riddersApproximation(Context & context, Preferences::AngleUnit angleUnit, T x, T h, T * error) const { +T DerivativeNode::riddersApproximation(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, T x, T h, T * error) const { /* Ridders' Algorithm * Blibliography: * - Ridders, C.J.F. 1982, Advances in Helperering Software, vol. 4, no. 2, @@ -109,7 +109,7 @@ T DerivativeNode::riddersApproximation(Context & context, Preferences::AngleUnit a[i][j] = 1; } } - a[0][0] = growthRateAroundAbscissa(x, hh, context, angleUnit); + a[0][0] = growthRateAroundAbscissa(x, hh, context, complexFormat, angleUnit); T ans = 0; T errt = 0; // Loop on i: change the step size @@ -118,7 +118,7 @@ T DerivativeNode::riddersApproximation(Context & context, Preferences::AngleUnit // Make hh an exactly representable number volatile T temp = x+hh; hh = temp - x; - a[0][i] = growthRateAroundAbscissa(x, hh, context, angleUnit); + a[0][i] = growthRateAroundAbscissa(x, hh, context, complexFormat, angleUnit); T fac = k_rateStepSize*k_rateStepSize; // Loop on j: compute extrapolation for several orders for (int j = 1; j < 10; j++) { diff --git a/poincare/src/determinant.cpp b/poincare/src/determinant.cpp index 2a01a7073..dae48be91 100644 --- a/poincare/src/determinant.cpp +++ b/poincare/src/determinant.cpp @@ -23,8 +23,8 @@ int DeterminantNode::serialize(char * buffer, int bufferSize, Preferences::Print // TODO: handle this exactly in shallowReduce for small dimensions. template -Evaluation DeterminantNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { - Evaluation input = childAtIndex(0)->approximate(T(), context, angleUnit); +Evaluation DeterminantNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + Evaluation input = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); return Complex(input.determinant()); } diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index d5a8f63ce..9f57e8286 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -46,25 +46,25 @@ Expression DivisionNode::shallowReduce(Context & context, Preferences::ComplexFo return Division(this).shallowReduce(context, complexFormat, angleUnit, target); } -template Complex DivisionNode::compute(const std::complex c, const std::complex d) { +template Complex DivisionNode::compute(const std::complex c, const std::complex d, Preferences::ComplexFormat complexFormat) { if (d.real() == 0.0 && d.imag() == 0.0) { return Complex::Undefined(); } return Complex(c/d); } -template MatrixComplex DivisionNode::computeOnComplexAndMatrix(const std::complex c, const MatrixComplex n) { +template MatrixComplex DivisionNode::computeOnComplexAndMatrix(const std::complex c, const MatrixComplex n, Preferences::ComplexFormat complexFormat) { MatrixComplex inverse = n.inverse(); - MatrixComplex result = MultiplicationNode::computeOnComplexAndMatrix(c, inverse); + MatrixComplex result = MultiplicationNode::computeOnComplexAndMatrix(c, inverse, complexFormat); return result; } -template MatrixComplex DivisionNode::computeOnMatrices(const MatrixComplex m, const MatrixComplex n) { +template MatrixComplex DivisionNode::computeOnMatrices(const MatrixComplex m, const MatrixComplex n, Preferences::ComplexFormat complexFormat) { if (m.numberOfColumns() != n.numberOfColumns()) { return MatrixComplex::Undefined(); } MatrixComplex inverse = n.inverse(); - MatrixComplex result = MultiplicationNode::computeOnMatrices(m, inverse); + MatrixComplex result = MultiplicationNode::computeOnMatrices(m, inverse, complexFormat); return result; } diff --git a/poincare/src/division_quotient.cpp b/poincare/src/division_quotient.cpp index 51dae949d..0a4d995ec 100644 --- a/poincare/src/division_quotient.cpp +++ b/poincare/src/division_quotient.cpp @@ -24,9 +24,9 @@ int DivisionQuotientNode::serialize(char * buffer, int bufferSize, Preferences:: } template -Evaluation DivisionQuotientNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { - Evaluation f1Input = childAtIndex(0)->approximate(T(), context, angleUnit); - Evaluation f2Input = childAtIndex(1)->approximate(T(), context, angleUnit); +Evaluation DivisionQuotientNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + Evaluation f1Input = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); + Evaluation f2Input = childAtIndex(1)->approximate(T(), context, complexFormat, angleUnit); T f1 = f1Input.toScalar(); T f2 = f2Input.toScalar(); if (std::isnan(f1) || std::isnan(f2) || f1 != (int)f1 || f2 != (int)f2) { diff --git a/poincare/src/division_remainder.cpp b/poincare/src/division_remainder.cpp index 095a5ee32..6afdfe8ca 100644 --- a/poincare/src/division_remainder.cpp +++ b/poincare/src/division_remainder.cpp @@ -25,9 +25,9 @@ Expression DivisionRemainderNode::shallowReduce(Context & context, Preferences:: } template -Evaluation DivisionRemainderNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { - Evaluation f1Input = childAtIndex(0)->approximate(T(), context, angleUnit); - Evaluation f2Input = childAtIndex(1)->approximate(T(), context, angleUnit); +Evaluation DivisionRemainderNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + Evaluation f1Input = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); + Evaluation f2Input = childAtIndex(1)->approximate(T(), context, complexFormat, angleUnit); T f1 = f1Input.toScalar(); T f2 = f2Input.toScalar(); if (std::isnan(f1) || std::isnan(f2) || f1 != (int)f1 || f2 != (int)f2) { diff --git a/poincare/src/empty_expression.cpp b/poincare/src/empty_expression.cpp index 538057093..4cb841349 100644 --- a/poincare/src/empty_expression.cpp +++ b/poincare/src/empty_expression.cpp @@ -14,7 +14,7 @@ Layout EmptyExpressionNode::createLayout(Preferences::PrintFloatMode floatDispla return EmptyLayout(); } -template Evaluation EmptyExpressionNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { +template Evaluation EmptyExpressionNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { return Complex::Undefined(); } diff --git a/poincare/src/equal.cpp b/poincare/src/equal.cpp index 0f3461bb9..ccb105e1a 100644 --- a/poincare/src/equal.cpp +++ b/poincare/src/equal.cpp @@ -37,7 +37,7 @@ int EqualNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatM } template -Evaluation EqualNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { +Evaluation EqualNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { return Complex::Undefined(); } diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index ed3801e07..155c84802 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -287,7 +287,7 @@ Evaluation Expression::approximateToEvaluation(Context& context, Preferences: sApproximationEncounteredComplex = false; // Reset interrupting flag because some evaluation methods use it sSimplificationHasBeenInterrupted = false; - Evaluation e = node()->approximate(U(), context, angleUnit); + Evaluation e = node()->approximate(U(), context, complexFormat, angleUnit); if (complexFormat == Preferences::ComplexFormat::Real && sApproximationEncounteredComplex) { e = Complex::Undefined(); } diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index 84354a0ba..65563a800 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -43,7 +43,7 @@ Expression FactorialNode::shallowBeautify(Context & context, Preferences::Comple } template -Complex FactorialNode::computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { +Complex FactorialNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { T n = c.real(); if (c.imag() != 0 || std::isnan(n) || n != (int)n || n < 0) { return Complex::Undefined(); diff --git a/poincare/src/floor.cpp b/poincare/src/floor.cpp index 6e1e3538c..052011fd6 100644 --- a/poincare/src/floor.cpp +++ b/poincare/src/floor.cpp @@ -24,7 +24,7 @@ int FloorNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatM } template -Complex FloorNode::computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { +Complex FloorNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { if (c.imag() != 0) { return Complex::Undefined(); } diff --git a/poincare/src/frac_part.cpp b/poincare/src/frac_part.cpp index ccd91ce0a..244a0384a 100644 --- a/poincare/src/frac_part.cpp +++ b/poincare/src/frac_part.cpp @@ -24,7 +24,7 @@ Expression FracPartNode::shallowReduce(Context & context, Preferences::ComplexFo } template -Complex FracPartNode::computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { +Complex FracPartNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { if (c.imag() != 0) { return Complex::Undefined(); } diff --git a/poincare/src/function.cpp b/poincare/src/function.cpp index 89d0a11a8..5ad9a6cbe 100644 --- a/poincare/src/function.cpp +++ b/poincare/src/function.cpp @@ -70,22 +70,22 @@ Expression FunctionNode::shallowReplaceReplaceableSymbols(Context & context) { return Function(this).shallowReplaceReplaceableSymbols(context); } -Evaluation FunctionNode::approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const { - return templatedApproximate(context, angleUnit); +Evaluation FunctionNode::approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + return templatedApproximate(context, complexFormat, angleUnit); } -Evaluation FunctionNode::approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const { - return templatedApproximate(context, angleUnit); +Evaluation FunctionNode::approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + return templatedApproximate(context, complexFormat, angleUnit); } template -Evaluation FunctionNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { +Evaluation FunctionNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { Function f(this); Expression e = SymbolAbstract::Expand(f, context, true); if (e.isUninitialized()) { return Complex::Undefined(); } - return e.node()->approximate(T(), context, angleUnit); + return e.node()->approximate(T(), context, complexFormat, angleUnit); } Function::Function(const char * name, size_t length) : diff --git a/poincare/src/great_common_divisor.cpp b/poincare/src/great_common_divisor.cpp index 6e1bf3216..073318946 100644 --- a/poincare/src/great_common_divisor.cpp +++ b/poincare/src/great_common_divisor.cpp @@ -25,9 +25,9 @@ Expression GreatCommonDivisorNode::shallowReduce(Context & context, Preferences: } template -Evaluation GreatCommonDivisorNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { - Evaluation f1Input = childAtIndex(0)->approximate(T(), context, angleUnit); - Evaluation f2Input = childAtIndex(1)->approximate(T(), context, angleUnit); +Evaluation GreatCommonDivisorNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + Evaluation f1Input = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); + Evaluation f2Input = childAtIndex(1)->approximate(T(), context, complexFormat, angleUnit); T f1 = f1Input.toScalar(); T f2 = f2Input.toScalar(); if (std::isnan(f1) || std::isnan(f2) || f1 != (int)f1 || f2 != (int)f2) { diff --git a/poincare/src/hyperbolic_arc_cosine.cpp b/poincare/src/hyperbolic_arc_cosine.cpp index 9930c7a51..189059533 100644 --- a/poincare/src/hyperbolic_arc_cosine.cpp +++ b/poincare/src/hyperbolic_arc_cosine.cpp @@ -17,7 +17,7 @@ int HyperbolicArcCosineNode::serialize(char * buffer, int bufferSize, Preference } template -Complex HyperbolicArcCosineNode::computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { +Complex HyperbolicArcCosineNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { std::complex result = std::acosh(c); /* asinh has a branch cut on ]-inf, 1]: it is then multivalued * on this cut. We followed the convention chosen by the lib c++ of llvm on @@ -26,7 +26,7 @@ Complex HyperbolicArcCosineNode::computeOnComplex(const std::complex c, Pr return Complex(Trigonometry::RoundToMeaningfulDigits(result, c)); } -template Complex Poincare::HyperbolicArcCosineNode::computeOnComplex(std::complex, Preferences::AngleUnit); -template Complex Poincare::HyperbolicArcCosineNode::computeOnComplex(std::complex, Preferences::AngleUnit); +template Complex Poincare::HyperbolicArcCosineNode::computeOnComplex(std::complex, Preferences::ComplexFormat, Preferences::AngleUnit); +template Complex Poincare::HyperbolicArcCosineNode::computeOnComplex(std::complex, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit); } diff --git a/poincare/src/hyperbolic_arc_sine.cpp b/poincare/src/hyperbolic_arc_sine.cpp index 86d9f7059..c736f6c97 100644 --- a/poincare/src/hyperbolic_arc_sine.cpp +++ b/poincare/src/hyperbolic_arc_sine.cpp @@ -16,7 +16,7 @@ int HyperbolicArcSineNode::serialize(char * buffer, int bufferSize, Preferences: } template -Complex HyperbolicArcSineNode::computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { +Complex HyperbolicArcSineNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { std::complex result = std::asinh(c); /* asinh has a branch cut on ]-inf*i, -i[U]i, +inf*i[: it is then multivalued * on this cut. We followed the convention chosen by the lib c++ of llvm on @@ -29,7 +29,7 @@ Complex HyperbolicArcSineNode::computeOnComplex(const std::complex c, Pref return Complex(Trigonometry::RoundToMeaningfulDigits(result, c)); } -template Complex Poincare::HyperbolicArcSineNode::computeOnComplex(std::complex, Preferences::AngleUnit); -template Complex Poincare::HyperbolicArcSineNode::computeOnComplex(std::complex, Preferences::AngleUnit); +template Complex Poincare::HyperbolicArcSineNode::computeOnComplex(std::complex, Preferences::ComplexFormat, Preferences::AngleUnit); +template Complex Poincare::HyperbolicArcSineNode::computeOnComplex(std::complex, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit); } diff --git a/poincare/src/hyperbolic_arc_tangent.cpp b/poincare/src/hyperbolic_arc_tangent.cpp index 8c700670c..11a72ddcf 100644 --- a/poincare/src/hyperbolic_arc_tangent.cpp +++ b/poincare/src/hyperbolic_arc_tangent.cpp @@ -17,7 +17,7 @@ int HyperbolicArcTangentNode::serialize(char * buffer, int bufferSize, Preferenc } template -Complex HyperbolicArcTangentNode::computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { +Complex HyperbolicArcTangentNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { std::complex result = std::atanh(c); /* atanh has a branch cut on ]-inf, -1[U]1, +inf[: it is then multivalued on * this cut. We followed the convention chosen by the lib c++ of llvm on @@ -30,7 +30,7 @@ Complex HyperbolicArcTangentNode::computeOnComplex(const std::complex c, P return Complex(Trigonometry::RoundToMeaningfulDigits(result, c)); } -template Complex Poincare::HyperbolicArcTangentNode::computeOnComplex(std::complex, Preferences::AngleUnit); -template Complex Poincare::HyperbolicArcTangentNode::computeOnComplex(std::complex, Preferences::AngleUnit); +template Complex Poincare::HyperbolicArcTangentNode::computeOnComplex(std::complex, Preferences::ComplexFormat, Preferences::AngleUnit); +template Complex Poincare::HyperbolicArcTangentNode::computeOnComplex(std::complex, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit); } diff --git a/poincare/src/hyperbolic_cosine.cpp b/poincare/src/hyperbolic_cosine.cpp index 0f8fc841d..bbd76e355 100644 --- a/poincare/src/hyperbolic_cosine.cpp +++ b/poincare/src/hyperbolic_cosine.cpp @@ -14,11 +14,11 @@ int HyperbolicCosineNode::serialize(char * buffer, int bufferSize, Preferences:: } template -Complex HyperbolicCosineNode::computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { +Complex HyperbolicCosineNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { return Complex(Trigonometry::RoundToMeaningfulDigits(std::cosh(c), c)); } -template Complex Poincare::HyperbolicCosineNode::computeOnComplex(std::complex, Preferences::AngleUnit); -template Complex Poincare::HyperbolicCosineNode::computeOnComplex(std::complex, Preferences::AngleUnit); +template Complex Poincare::HyperbolicCosineNode::computeOnComplex(std::complex, Preferences::ComplexFormat, Preferences::AngleUnit); +template Complex Poincare::HyperbolicCosineNode::computeOnComplex(std::complex, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit); } diff --git a/poincare/src/hyperbolic_sine.cpp b/poincare/src/hyperbolic_sine.cpp index cbbf67ca1..5b1534c73 100644 --- a/poincare/src/hyperbolic_sine.cpp +++ b/poincare/src/hyperbolic_sine.cpp @@ -14,11 +14,11 @@ int HyperbolicSineNode::serialize(char * buffer, int bufferSize, Preferences::Pr } template -Complex HyperbolicSineNode::computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { +Complex HyperbolicSineNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { return Complex(Trigonometry::RoundToMeaningfulDigits(std::sinh(c), c)); } -template Complex Poincare::HyperbolicSineNode::computeOnComplex(std::complex, Preferences::AngleUnit); -template Complex Poincare::HyperbolicSineNode::computeOnComplex(std::complex, Preferences::AngleUnit); +template Complex Poincare::HyperbolicSineNode::computeOnComplex(std::complex, Preferences::ComplexFormat, Preferences::AngleUnit); +template Complex Poincare::HyperbolicSineNode::computeOnComplex(std::complex, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit); } diff --git a/poincare/src/hyperbolic_tangent.cpp b/poincare/src/hyperbolic_tangent.cpp index f5557587f..89f0bab4b 100644 --- a/poincare/src/hyperbolic_tangent.cpp +++ b/poincare/src/hyperbolic_tangent.cpp @@ -14,11 +14,11 @@ int HyperbolicTangentNode::serialize(char * buffer, int bufferSize, Preferences: } template -Complex HyperbolicTangentNode::computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { +Complex HyperbolicTangentNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { return Complex(Trigonometry::RoundToMeaningfulDigits(std::tanh(c), c)); } -template Complex Poincare::HyperbolicTangentNode::computeOnComplex(std::complex, Preferences::AngleUnit); -template Complex Poincare::HyperbolicTangentNode::computeOnComplex(std::complex, Preferences::AngleUnit); +template Complex Poincare::HyperbolicTangentNode::computeOnComplex(std::complex, Preferences::ComplexFormat, Preferences::AngleUnit); +template Complex Poincare::HyperbolicTangentNode::computeOnComplex(std::complex, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit); } diff --git a/poincare/src/integral.cpp b/poincare/src/integral.cpp index bb5be5305..299eccf44 100644 --- a/poincare/src/integral.cpp +++ b/poincare/src/integral.cpp @@ -49,35 +49,35 @@ Expression IntegralNode::shallowReduce(Context & context, Preferences::ComplexFo } template -Evaluation IntegralNode::templatedApproximate(Context & context, Preferences::AngleUnit angleUnit) const { - Evaluation aInput = childAtIndex(2)->approximate(T(), context, angleUnit); - Evaluation bInput = childAtIndex(3)->approximate(T(), context, angleUnit); +Evaluation IntegralNode::templatedApproximate(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + Evaluation aInput = childAtIndex(2)->approximate(T(), context, complexFormat, angleUnit); + Evaluation bInput = childAtIndex(3)->approximate(T(), context, complexFormat, angleUnit); T a = aInput.toScalar(); T b = bInput.toScalar(); if (std::isnan(a) || std::isnan(b)) { return Complex::Undefined(); } #ifdef LAGRANGE_METHOD - T result = lagrangeGaussQuadrature(a, b, context, angleUnit); + T result = lagrangeGaussQuadrature(a, b, context, complexFormat, angleUnit); #else - T result = adaptiveQuadrature(a, b, 0.1, k_maxNumberOfIterations, context, angleUnit); + T result = adaptiveQuadrature(a, b, 0.1, k_maxNumberOfIterations, context, complexFormat, angleUnit); #endif return Complex(result); } template -T IntegralNode::functionValueAtAbscissa(T x, Context & context, Preferences::AngleUnit angleUnit) const { +T IntegralNode::functionValueAtAbscissa(T x, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { // Here we cannot use Expression::approximateWithValueForSymbol which would reset the sApproximationEncounteredComplex flag assert(childAtIndex(1)->type() == Type::Symbol); VariableContext variableContext = VariableContext(static_cast(childAtIndex(1))->name(), &context); variableContext.setApproximationForVariable(x); - return childAtIndex(0)->approximate(T(), variableContext, angleUnit).toScalar(); + return childAtIndex(0)->approximate(T(), variableContext, complexFormat, angleUnit).toScalar(); } #ifdef LAGRANGE_METHOD template -T IntegralNode::lagrangeGaussQuadrature(T a, T b, Context & context, Preferences::AngleUnit angleUnit) const { +T IntegralNode::lagrangeGaussQuadrature(T a, T b, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { /* We here use Gauss-Legendre quadrature with n = 5 * Gauss-Legendre abscissae and weights can be found in * C/C++ library source code. */ @@ -91,11 +91,11 @@ T IntegralNode::lagrangeGaussQuadrature(T a, T b, Context & context, Preferences T result = 0; for (int j = 0; j < 10; j++) { T dx = xr * x[j]; - T evaluationAfterX = functionValueAtAbscissa(xm+dx, context, angleUnit); + T evaluationAfterX = functionValueAtAbscissa(xm+dx, context, complexFormat, angleUnit); if (std::isnan(evaluationAfterX)) { return NAN; } - T evaluationBeforeX = functionValueAtAbscissa(xm-dx, context, angleUnit); + T evaluationBeforeX = functionValueAtAbscissa(xm-dx, context, complexFormat, angleUnit); if (std::isnan(evaluationBeforeX)) { return NAN; } @@ -108,7 +108,7 @@ T IntegralNode::lagrangeGaussQuadrature(T a, T b, Context & context, Preferences #else template -IntegralNode::DetailedResult IntegralNode::kronrodGaussQuadrature(T a, T b, Context & context, Preferences::AngleUnit angleUnit) const { +IntegralNode::DetailedResult IntegralNode::kronrodGaussQuadrature(T a, T b, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { static T epsilon = sizeof(T) == sizeof(double) ? DBL_EPSILON : FLT_EPSILON; static T max = sizeof(T) == sizeof(double) ? DBL_MAX : FLT_MAX; /* We here use Kronrod-Legendre quadrature with n = 21 @@ -135,7 +135,7 @@ IntegralNode::DetailedResult IntegralNode::kronrodGaussQuadrature(T a, T b, C errorResult.absoluteError = 0; T resg = 0; - T fc = functionValueAtAbscissa(centr, context, angleUnit); + T fc = functionValueAtAbscissa(centr, context, complexFormat, angleUnit); if (std::isnan(fc)) { return errorResult; } @@ -143,11 +143,11 @@ IntegralNode::DetailedResult IntegralNode::kronrodGaussQuadrature(T a, T b, C T resabs = std::fabs(resk); for (int j = 0; j < 10; j++) { T absc = hlgth*xgk[j]; - T fval1 = functionValueAtAbscissa(centr-absc, context, angleUnit); + T fval1 = functionValueAtAbscissa(centr-absc, context, complexFormat, angleUnit); if (std::isnan(fval1)) { return errorResult; } - T fval2 = functionValueAtAbscissa(centr+absc, context, angleUnit); + T fval2 = functionValueAtAbscissa(centr+absc, context, complexFormat, angleUnit); if (std::isnan(fval2)) { return errorResult; } @@ -183,17 +183,17 @@ IntegralNode::DetailedResult IntegralNode::kronrodGaussQuadrature(T a, T b, C } template -T IntegralNode::adaptiveQuadrature(T a, T b, T eps, int numberOfIterations, Context & context, Preferences::AngleUnit angleUnit) const { +T IntegralNode::adaptiveQuadrature(T a, T b, T eps, int numberOfIterations, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { if (Expression::ShouldStopProcessing()) { return NAN; } - DetailedResult quadKG = kronrodGaussQuadrature(a, b, context, angleUnit); + DetailedResult quadKG = kronrodGaussQuadrature(a, b, context, complexFormat, angleUnit); T result = quadKG.integral; if (quadKG.absoluteError <= eps) { return result; } else if (--numberOfIterations > 0) { T m = (a+b)/2; - return adaptiveQuadrature(a, m, eps/2, numberOfIterations, context, angleUnit) + adaptiveQuadrature(m, b, eps/2, numberOfIterations, context, angleUnit); + return adaptiveQuadrature(a, m, eps/2, numberOfIterations, context, complexFormat, angleUnit) + adaptiveQuadrature(m, b, eps/2, numberOfIterations, context, complexFormat, angleUnit); } else { return NAN; } diff --git a/poincare/src/least_common_multiple.cpp b/poincare/src/least_common_multiple.cpp index 81aa319c2..a0679c494 100644 --- a/poincare/src/least_common_multiple.cpp +++ b/poincare/src/least_common_multiple.cpp @@ -26,9 +26,9 @@ Expression LeastCommonMultipleNode::shallowReduce(Context & context, Preferences } template -Evaluation LeastCommonMultipleNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { - Evaluation f1Input = childAtIndex(0)->approximate(T(), context, angleUnit); - Evaluation f2Input = childAtIndex(1)->approximate(T(), context, angleUnit); +Evaluation LeastCommonMultipleNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + Evaluation f1Input = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); + Evaluation f2Input = childAtIndex(1)->approximate(T(), context, complexFormat, angleUnit); T f1 = f1Input.toScalar(); T f2 = f2Input.toScalar(); if (std::isnan(f1) || std::isnan(f2) || f1 != (int)f1 || f2 != (int)f2) { diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index ccef5b82a..3b00882d2 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -68,19 +68,19 @@ Expression LogarithmNode<2>::shallowBeautify(Context & context, Preferences::Com } template<> -template Evaluation LogarithmNode<1>::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { - return ApproximationHelper::Map(this, context, angleUnit, computeOnComplex); +template Evaluation LogarithmNode<1>::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } template<> -template Evaluation LogarithmNode<2>::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { - Evaluation x = childAtIndex(0)->approximate(U(), context, angleUnit); - Evaluation n = childAtIndex(1)->approximate(U(), context, angleUnit); +template Evaluation LogarithmNode<2>::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + Evaluation x = childAtIndex(0)->approximate(U(), context, complexFormat, angleUnit); + Evaluation n = childAtIndex(1)->approximate(U(), context, complexFormat, angleUnit); std::complex result = std::complex(NAN, NAN); if (x.type() == EvaluationNode::Type::Complex && n.type() == EvaluationNode::Type::Complex) { std::complex xc = (static_cast&>(x)).stdComplex(); std::complex nc = (static_cast&>(n)).stdComplex(); - result = DivisionNode::compute(computeOnComplex(xc, angleUnit).stdComplex(), computeOnComplex(nc, angleUnit).stdComplex()).stdComplex(); + result = DivisionNode::compute(computeOnComplex(xc, complexFormat, angleUnit).stdComplex(), computeOnComplex(nc, complexFormat, angleUnit).stdComplex(), complexFormat).stdComplex(); } return Complex(result); } @@ -220,7 +220,7 @@ Expression Logarithm::simpleShallowReduce(Context & context, Preferences::Comple if (r.isZero()) { bool isNegative = true; Expression result; - Evaluation baseApproximation = childAtIndex(1).node()->approximate(1.0f, context, angleUnit); + Evaluation baseApproximation = childAtIndex(1).node()->approximate(1.0f, context, complexFormat, angleUnit); std::complex logDenominator = std::log10(static_cast&>(baseApproximation).stdComplex()); if (logDenominator.imag() != 0.0f || logDenominator.real() == 0.0f) { result = Undefined(); @@ -326,10 +326,10 @@ Expression Logarithm::shallowBeautify(Context & context, Preferences::ComplexFor return *this; } -template Evaluation LogarithmNode<1>::templatedApproximate(Poincare::Context&, Poincare::Preferences::AngleUnit) const; -template Evaluation LogarithmNode<1>::templatedApproximate(Poincare::Context&, Poincare::Preferences::AngleUnit) const; -template Evaluation LogarithmNode<2>::templatedApproximate(Poincare::Context&, Poincare::Preferences::AngleUnit) const; -template Evaluation LogarithmNode<2>::templatedApproximate(Poincare::Context&, Poincare::Preferences::AngleUnit) const; +template Evaluation LogarithmNode<1>::templatedApproximate(Poincare::Context&, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit) const; +template Evaluation LogarithmNode<1>::templatedApproximate(Poincare::Context&, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit) const; +template Evaluation LogarithmNode<2>::templatedApproximate(Poincare::Context&, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit) const; +template Evaluation LogarithmNode<2>::templatedApproximate(Poincare::Context&, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit) const; template int LogarithmNode<1>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; template int LogarithmNode<2>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; diff --git a/poincare/src/matrix.cpp b/poincare/src/matrix.cpp index 6a88201cf..ff7807e19 100644 --- a/poincare/src/matrix.cpp +++ b/poincare/src/matrix.cpp @@ -78,10 +78,10 @@ int MatrixNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloat } template -Evaluation MatrixNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { +Evaluation MatrixNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { MatrixComplex matrix; for (ExpressionNode * c : children()) { - matrix.addChildAtIndexInPlace(c->approximate(T(), context, angleUnit), matrix.numberOfChildren(), matrix.numberOfChildren()); + matrix.addChildAtIndexInPlace(c->approximate(T(), context, complexFormat, angleUnit), matrix.numberOfChildren(), matrix.numberOfChildren()); } matrix.setDimensions(numberOfRows(), numberOfColumns()); return matrix; diff --git a/poincare/src/matrix_dimension.cpp b/poincare/src/matrix_dimension.cpp index cab61c470..cf33a7c03 100644 --- a/poincare/src/matrix_dimension.cpp +++ b/poincare/src/matrix_dimension.cpp @@ -24,8 +24,8 @@ int MatrixDimensionNode::serialize(char * buffer, int bufferSize, Preferences::P } template -Evaluation MatrixDimensionNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { - Evaluation input = childAtIndex(0)->approximate(T(), context, angleUnit); +Evaluation MatrixDimensionNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + Evaluation input = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); std::complex operands[2]; if (input.type() == EvaluationNode::Type::MatrixComplex) { operands[0] = std::complex(static_cast&>(input).numberOfRows()); diff --git a/poincare/src/matrix_inverse.cpp b/poincare/src/matrix_inverse.cpp index eca3f9a69..e00cb9f56 100644 --- a/poincare/src/matrix_inverse.cpp +++ b/poincare/src/matrix_inverse.cpp @@ -28,8 +28,8 @@ int MatrixInverseNode::serialize(char * buffer, int bufferSize, Preferences::Pri // TODO: handle this exactly in shallowReduce for small dimensions. template -Evaluation MatrixInverseNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { - Evaluation input = childAtIndex(0)->approximate(T(), context, angleUnit); +Evaluation MatrixInverseNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + Evaluation input = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); Evaluation inverse; if (input.type() == EvaluationNode::Type::MatrixComplex) { inverse = static_cast&>(input).inverse(); diff --git a/poincare/src/matrix_trace.cpp b/poincare/src/matrix_trace.cpp index 83acc54f2..6fcf1a326 100644 --- a/poincare/src/matrix_trace.cpp +++ b/poincare/src/matrix_trace.cpp @@ -26,8 +26,8 @@ int MatrixTraceNode::serialize(char * buffer, int bufferSize, Preferences::Print } template -Evaluation MatrixTraceNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { - Evaluation input = childAtIndex(0)->approximate(T(), context, angleUnit); +Evaluation MatrixTraceNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + Evaluation input = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); Complex result = Complex(input.trace()); return result; } diff --git a/poincare/src/matrix_transpose.cpp b/poincare/src/matrix_transpose.cpp index 2f1c6ec29..b85a71918 100644 --- a/poincare/src/matrix_transpose.cpp +++ b/poincare/src/matrix_transpose.cpp @@ -25,8 +25,8 @@ int MatrixTransposeNode::serialize(char * buffer, int bufferSize, Preferences::P } template -Evaluation MatrixTransposeNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { - Evaluation input = childAtIndex(0)->approximate(T(), context, angleUnit); +Evaluation MatrixTransposeNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + Evaluation input = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); Evaluation transpose; if (input.type() == EvaluationNode::Type::MatrixComplex) { transpose = static_cast&>(input).transpose(); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index e2c13a4a7..8314071ec 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -48,7 +48,7 @@ int MultiplicationNode::getPolynomialCoefficients(Context & context, const char } template -MatrixComplex MultiplicationNode::computeOnMatrices(const MatrixComplex m, const MatrixComplex n) { +MatrixComplex MultiplicationNode::computeOnMatrices(const MatrixComplex m, const MatrixComplex n, Preferences::ComplexFormat complexFormat) { if (m.numberOfColumns() != n.numberOfRows()) { return MatrixComplex::Undefined(); } @@ -781,10 +781,10 @@ const Expression Multiplication::Base(const Expression e) { return e; } -template MatrixComplex MultiplicationNode::computeOnComplexAndMatrix(std::complex const, const MatrixComplex); -template MatrixComplex MultiplicationNode::computeOnComplexAndMatrix(std::complex const, const MatrixComplex); -template Complex MultiplicationNode::compute(const std::complex, const std::complex); -template Complex MultiplicationNode::compute(const std::complex, const std::complex); +template MatrixComplex MultiplicationNode::computeOnComplexAndMatrix(std::complex const, const MatrixComplex, Preferences::ComplexFormat); +template MatrixComplex MultiplicationNode::computeOnComplexAndMatrix(std::complex const, const MatrixComplex, Preferences::ComplexFormat); +template Complex MultiplicationNode::compute(const std::complex, const std::complex, Preferences::ComplexFormat); +template Complex MultiplicationNode::compute(const std::complex, const std::complex, Preferences::ComplexFormat); template void Multiplication::computeOnArrays(double * m, double * n, double * result, int mNumberOfColumns, int mNumberOfRows, int nNumberOfColumns); } diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index 303dadd48..4e7c56e6b 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -33,16 +33,16 @@ Expression NthRootNode::shallowReduce(Context & context, Preferences::ComplexFor } template -Evaluation NthRootNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { - Evaluation base = childAtIndex(0)->approximate(T(), context, angleUnit); - Evaluation index = childAtIndex(1)->approximate(T(), context, angleUnit); +Evaluation NthRootNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + Evaluation base = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); + Evaluation index = childAtIndex(1)->approximate(T(), context, complexFormat, angleUnit); Complex result = Complex::Undefined(); if (base.type() == EvaluationNode::Type::Complex && index.type() == EvaluationNode::Type::Complex) { Complex basec = static_cast &>(base); Complex indexc = static_cast &>(index); - result = PowerNode::compute(basec.stdComplex(), std::complex(1)/(indexc.stdComplex())); + result = PowerNode::compute(basec.stdComplex(), std::complex(1.0)/(indexc.stdComplex()), complexFormat); } return result; } diff --git a/poincare/src/parenthesis.cpp b/poincare/src/parenthesis.cpp index 437b7fc78..4fd94f1b8 100644 --- a/poincare/src/parenthesis.cpp +++ b/poincare/src/parenthesis.cpp @@ -21,8 +21,8 @@ Expression ParenthesisNode::shallowReduce(Context & context, Preferences::Comple } template -Evaluation ParenthesisNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { - return childAtIndex(0)->approximate(T(), context, angleUnit); +Evaluation ParenthesisNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + return childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); } Expression Parenthesis::shallowReduce() { diff --git a/poincare/src/permute_coefficient.cpp b/poincare/src/permute_coefficient.cpp index 5a330d708..b54bb81e2 100644 --- a/poincare/src/permute_coefficient.cpp +++ b/poincare/src/permute_coefficient.cpp @@ -28,9 +28,9 @@ Expression PermuteCoefficientNode::shallowReduce(Context & context, Preferences: } template -Evaluation PermuteCoefficientNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { - Evaluation nInput = childAtIndex(0)->approximate(T(), context, angleUnit); - Evaluation kInput = childAtIndex(1)->approximate(T(), context, angleUnit); +Evaluation PermuteCoefficientNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + Evaluation nInput = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); + Evaluation kInput = childAtIndex(1)->approximate(T(), context, complexFormat, angleUnit); T n = nInput.toScalar(); T k = kInput.toScalar(); if (std::isnan(n) || std::isnan(k) || n != std::round(n) || k != std::round(k) || n < 0.0f || k < 0.0f) { diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 6b3c37a4b..803f4889d 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -98,7 +98,7 @@ bool PowerNode::isReal(Context & context) const { // Private template -Complex PowerNode::compute(const std::complex c, const std::complex d) { +Complex PowerNode::compute(const std::complex c, const std::complex d, Preferences::ComplexFormat complexFormat) { std::complex result; if (c.imag() == 0.0 && d.imag() == 0.0 && c.real() != 0.0 && (c.real() > 0.0 || std::round(d.real()) == d.real())) { /* pow: (R+, R) -> R+ (2^1.3 ~ 2.46) @@ -197,11 +197,11 @@ Expression PowerNode::denominator(Context & context, Preferences::ComplexFormat } // Evaluation -template MatrixComplex PowerNode::computeOnComplexAndMatrix(const std::complex c, const MatrixComplex n) { +template MatrixComplex PowerNode::computeOnComplexAndMatrix(const std::complex c, const MatrixComplex n, Preferences::ComplexFormat complexFormat) { return MatrixComplex::Undefined(); } -template MatrixComplex PowerNode::computeOnMatrixAndComplex(const MatrixComplex m, const std::complex d) { +template MatrixComplex PowerNode::computeOnMatrixAndComplex(const MatrixComplex m, const std::complex d, Preferences::ComplexFormat complexFormat) { if (m.numberOfRows() != m.numberOfColumns()) { return MatrixComplex::Undefined(); } @@ -215,7 +215,7 @@ template MatrixComplex PowerNode::computeOnMatrixAndComplex(const return MatrixComplex::Undefined(); } Complex minusC = Complex(-d); - MatrixComplex result = PowerNode::computeOnMatrixAndComplex(inverse, minusC.stdComplex()); + MatrixComplex result = PowerNode::computeOnMatrixAndComplex(inverse, minusC.stdComplex(), complexFormat); return result; } MatrixComplex result = MatrixComplex::createIdentity(m.numberOfRows()); @@ -224,12 +224,12 @@ template MatrixComplex PowerNode::computeOnMatrixAndComplex(const if (Expression::ShouldStopProcessing()) { return MatrixComplex::Undefined(); } - result = MultiplicationNode::computeOnMatrices(result, m); + result = MultiplicationNode::computeOnMatrices(result, m, complexFormat); } return result; } -template MatrixComplex PowerNode::computeOnMatrices(const MatrixComplex m, const MatrixComplex n) { +template MatrixComplex PowerNode::computeOnMatrices(const MatrixComplex m, const MatrixComplex n, Preferences::ComplexFormat complexFormat) { return MatrixComplex::Undefined(); } @@ -1209,7 +1209,7 @@ bool Power::RationalExponentShouldNotBeReduced(const Rational & b, const Rationa } -template Complex PowerNode::compute(std::complex, std::complex); -template Complex PowerNode::compute(std::complex, std::complex); +template Complex PowerNode::compute(std::complex, std::complex, Preferences::ComplexFormat); +template Complex PowerNode::compute(std::complex, std::complex, Preferences::ComplexFormat); } diff --git a/poincare/src/prediction_interval.cpp b/poincare/src/prediction_interval.cpp index a294a5640..12b438031 100644 --- a/poincare/src/prediction_interval.cpp +++ b/poincare/src/prediction_interval.cpp @@ -32,9 +32,9 @@ Expression PredictionIntervalNode::shallowReduce(Context & context, Preferences: } template -Evaluation PredictionIntervalNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { - Evaluation pInput = childAtIndex(0)->approximate(T(), context, angleUnit); - Evaluation nInput = childAtIndex(1)->approximate(T(), context, angleUnit); +Evaluation PredictionIntervalNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + Evaluation pInput = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); + Evaluation nInput = childAtIndex(1)->approximate(T(), context, complexFormat, angleUnit); T p = static_cast &>(pInput).toScalar(); T n = static_cast &>(nInput).toScalar(); if (std::isnan(p) || std::isnan(n) || n != (int)n || n < 0 || p < 0 || p > 1) { diff --git a/poincare/src/product.cpp b/poincare/src/product.cpp index 721c64648..caa9be26c 100644 --- a/poincare/src/product.cpp +++ b/poincare/src/product.cpp @@ -27,7 +27,7 @@ int ProductNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloa } template -Evaluation ProductNode::templatedApproximateWithNextTerm(Evaluation a, Evaluation b) const { +Evaluation ProductNode::templatedApproximateWithNextTerm(Evaluation a, Evaluation b, Preferences::ComplexFormat complexFormat) const { if (a.type() == EvaluationNode::Type::Complex && b.type() == EvaluationNode::Type::Complex) { Complex c = static_cast&>(a); Complex d = static_cast&>(b); @@ -37,13 +37,13 @@ Evaluation ProductNode::templatedApproximateWithNextTerm(Evaluation a, Eva Complex c = static_cast &>(a); assert(b.type() == EvaluationNode::Type::MatrixComplex); MatrixComplex m = static_cast &>(b); - return MultiplicationNode::computeOnComplexAndMatrix(c.stdComplex(), m); + return MultiplicationNode::computeOnComplexAndMatrix(c.stdComplex(), m, complexFormat); } assert(a.type() == EvaluationNode::Type::MatrixComplex); assert(b.type() == EvaluationNode::Type::MatrixComplex); MatrixComplex m = static_cast&>(a); MatrixComplex n = static_cast&>(b); - return MultiplicationNode::computeOnMatrices(m, n); + return MultiplicationNode::computeOnMatrices(m, n, complexFormat); } } diff --git a/poincare/src/randint.cpp b/poincare/src/randint.cpp index cd826e725..269e0a1a4 100644 --- a/poincare/src/randint.cpp +++ b/poincare/src/randint.cpp @@ -24,9 +24,9 @@ int RandintNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloa return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, Randint::s_functionHelper.name()); } -template Evaluation RandintNode::templateApproximate(Context & context, Preferences::AngleUnit angleUnit) const { - Evaluation aInput = childAtIndex(0)->approximate(T(), context, angleUnit); - Evaluation bInput = childAtIndex(1)->approximate(T(), context, angleUnit); +template Evaluation RandintNode::templateApproximate(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + Evaluation aInput = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); + Evaluation bInput = childAtIndex(1)->approximate(T(), context, complexFormat, angleUnit); T a = aInput.toScalar(); T b = bInput.toScalar(); if (std::isnan(a) || std::isnan(b) || a != std::round(a) || b != std::round(b) || a > b) { diff --git a/poincare/src/round.cpp b/poincare/src/round.cpp index 2ddf81cb4..f0205ef19 100644 --- a/poincare/src/round.cpp +++ b/poincare/src/round.cpp @@ -26,9 +26,9 @@ Expression RoundNode::shallowReduce(Context & context, Preferences::ComplexForma } template -Evaluation RoundNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { - Evaluation f1Input = childAtIndex(0)->approximate(T(), context, angleUnit); - Evaluation f2Input = childAtIndex(1)->approximate(T(), context, angleUnit); +Evaluation RoundNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + Evaluation f1Input = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); + Evaluation f2Input = childAtIndex(1)->approximate(T(), context, complexFormat, angleUnit); T f1 = f1Input.toScalar(); T f2 = f2Input.toScalar(); if (std::isnan(f2) || f2 != std::round(f2)) { diff --git a/poincare/src/sequence.cpp b/poincare/src/sequence.cpp index 33eebc3d6..336a164b4 100644 --- a/poincare/src/sequence.cpp +++ b/poincare/src/sequence.cpp @@ -20,9 +20,9 @@ Layout SequenceNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, } template -Evaluation SequenceNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { - Evaluation aInput = childAtIndex(2)->approximate(T(), context, angleUnit); - Evaluation bInput = childAtIndex(3)->approximate(T(), context, angleUnit); +Evaluation SequenceNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + Evaluation aInput = childAtIndex(2)->approximate(T(), context, complexFormat, angleUnit); + Evaluation bInput = childAtIndex(3)->approximate(T(), context, complexFormat, angleUnit); T start = aInput.toScalar(); T end = bInput.toScalar(); if (std::isnan(start) || std::isnan(end) || start != (int)start || end != (int)end || end - start > k_maxNumberOfSteps) { @@ -35,7 +35,7 @@ Evaluation SequenceNode::templatedApproximate(Context& context, Preferences:: return Complex::Undefined(); } nContext.setApproximationForVariable((T)i); - result = evaluateWithNextTerm(T(), result, childAtIndex(0)->approximate(T(), nContext, angleUnit)); + result = evaluateWithNextTerm(T(), result, childAtIndex(0)->approximate(T(), nContext, complexFormat, angleUnit), complexFormat); if (result.isUndefined()) { return Complex::Undefined(); } @@ -43,7 +43,7 @@ Evaluation SequenceNode::templatedApproximate(Context& context, Preferences:: return result; } -template Evaluation SequenceNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; -template Evaluation SequenceNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; +template Evaluation SequenceNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; +template Evaluation SequenceNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; } diff --git a/poincare/src/sign_function.cpp b/poincare/src/sign_function.cpp index 329f62134..493e68248 100644 --- a/poincare/src/sign_function.cpp +++ b/poincare/src/sign_function.cpp @@ -37,7 +37,7 @@ Expression SignFunctionNode::shallowReduce(Context & context, Preferences::Compl } template -Complex SignFunctionNode::computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { +Complex SignFunctionNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { if (c.imag() != 0) { return Complex::Undefined(); } @@ -67,7 +67,7 @@ Expression SignFunction::shallowReduce(Context & context, Preferences::ComplexFo one = Rational(-1); } } else { - Evaluation childApproximated = child.node()->approximate(1.0f, context, angleUnit); + Evaluation childApproximated = child.node()->approximate(1.0f, context, complexFormat, angleUnit); assert(childApproximated.type() == EvaluationNode::Type::Complex); Complex c = static_cast&>(childApproximated); // c has no sign (c is complex or NAN) diff --git a/poincare/src/sine.cpp b/poincare/src/sine.cpp index a04bd527f..9ecf57eaa 100644 --- a/poincare/src/sine.cpp +++ b/poincare/src/sine.cpp @@ -16,7 +16,7 @@ float SineNode::characteristicXRange(Context & context, Preferences::AngleUnit a } template -Complex SineNode::computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { +Complex SineNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { std::complex angleInput = Trigonometry::ConvertToRadian(c, angleUnit); std::complex res = std::sin(angleInput); return Complex(Trigonometry::RoundToMeaningfulDigits(res, angleInput)); diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index 253f473b4..438dab169 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -27,7 +27,7 @@ int SquareRootNode::serialize(char * buffer, int bufferSize, Preferences::PrintF } template -Complex SquareRootNode::computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { +Complex SquareRootNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { std::complex result = std::sqrt(c); /* Openbsd trigonometric functions are numerical implementation and thus are * approximative. diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index 35bb87b2c..a38327460 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -36,7 +36,7 @@ Layout StoreNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int } template -Evaluation StoreNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { +Evaluation StoreNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { /* If we are here, it means that the store node was not shallowReduced. * Otherwise, it would have been replaced by its symbol. We thus have to * setExpressionForSymbol. */ @@ -47,7 +47,7 @@ Evaluation StoreNode::templatedApproximate(Context& context, Preferences::Ang if (e.isUninitialized()) { return Complex::Undefined(); } - return e.node()->approximate(T(), context, angleUnit); + return e.node()->approximate(T(), context, complexFormat, angleUnit); } Expression Store::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index 3e410f31d..73daf456b 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -42,11 +42,11 @@ int SubtractionNode::serialize(char * buffer, int bufferSize, Preferences::Print return SerializationHelper::Infix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, "-"); } -template MatrixComplex SubtractionNode::computeOnComplexAndMatrix(const std::complex c, const MatrixComplex m) { - MatrixComplex opposite = computeOnMatrixAndComplex(m, c); +template MatrixComplex SubtractionNode::computeOnComplexAndMatrix(const std::complex c, const MatrixComplex m, Preferences::ComplexFormat complexFormat) { + MatrixComplex opposite = computeOnMatrixAndComplex(m, c, complexFormat); MatrixComplex result; for (int i = 0; i < opposite.numberOfChildren(); i++) { - result.addChildAtIndexInPlace(OppositeNode::compute(opposite.complexAtIndex(i)), i, i); + result.addChildAtIndexInPlace(OppositeNode::compute(opposite.complexAtIndex(i), complexFormat), i, i); } result.setDimensions(opposite.numberOfRows(), opposite.numberOfColumns()); return result; diff --git a/poincare/src/sum.cpp b/poincare/src/sum.cpp index 9f35641bd..9c7a5305b 100644 --- a/poincare/src/sum.cpp +++ b/poincare/src/sum.cpp @@ -27,7 +27,7 @@ int SumNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMod } template -Evaluation SumNode::templatedApproximateWithNextTerm(Evaluation a, Evaluation b) const { +Evaluation SumNode::templatedApproximateWithNextTerm(Evaluation a, Evaluation b, Preferences::ComplexFormat complexFormat) const { if (a.type() == EvaluationNode::Type::Complex && b.type() == EvaluationNode::Type::Complex) { Complex c = static_cast&>(a); Complex d = static_cast&>(b); @@ -37,13 +37,13 @@ Evaluation SumNode::templatedApproximateWithNextTerm(Evaluation a, Evaluat Complex c = static_cast &>(a); assert(b.type() == EvaluationNode::Type::MatrixComplex); MatrixComplex m = static_cast &>(b); - return AdditionNode::computeOnComplexAndMatrix(c.stdComplex(), m); + return AdditionNode::computeOnComplexAndMatrix(c.stdComplex(), m, complexFormat); } assert(a.type() == EvaluationNode::Type::MatrixComplex); assert(b.type() == EvaluationNode::Type::MatrixComplex); MatrixComplex m = static_cast&>(a); MatrixComplex n = static_cast&>(b); - return AdditionNode::computeOnMatrices(m, n); + return AdditionNode::computeOnMatrices(m, n, complexFormat); } } diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 5ccccc661..97144e75e 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -126,13 +126,13 @@ Expression SymbolNode::shallowReplaceReplaceableSymbols(Context & context) { } template -Evaluation SymbolNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { +Evaluation SymbolNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { Symbol s(this); Expression e = SymbolAbstract::Expand(s, context, false); if (e.isUninitialized()) { return Complex::Undefined(); } - return e.node()->approximate(T(), context, angleUnit); + return e.node()->approximate(T(), context, complexFormat, angleUnit); } Symbol::Symbol(const char * name, int length) : SymbolAbstract(TreePool::sharedPool()->createTreeNode(SymbolAbstract::AlignedNodeSize(length, sizeof(SymbolNode)))) { diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp index 01e342b50..6d9e7dd1a 100644 --- a/poincare/src/tangent.cpp +++ b/poincare/src/tangent.cpp @@ -27,7 +27,7 @@ int TangentNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloa } template -Complex TangentNode::computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { +Complex TangentNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { std::complex angleInput = Trigonometry::ConvertToRadian(c, angleUnit); std::complex res = std::tan(angleInput); return Complex(Trigonometry::RoundToMeaningfulDigits(res, angleInput)); diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index d27aa2530..7f9e3b0f9 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -36,7 +36,7 @@ float Trigonometry::characteristicXRange(const Expression & e, Context & context /* To compute a, the slope of the expression child(0), we compute the * derivative of child(0) for any x value. */ Poincare::Derivative derivative = Poincare::Derivative::Builder(e.childAtIndex(0).clone(), Symbol(x, 1), Float(1.0f)); - float a = derivative.node()->approximate(float(), context, angleUnit).toScalar(); + float a = derivative.node()->approximate(float(), context, Preferences::ComplexFormat::Real, angleUnit).toScalar(); float pi = angleUnit == Preferences::AngleUnit::Radian ? M_PI : 180.0f; return 2.0f*pi/std::fabs(a); } @@ -248,7 +248,7 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& c // Step 1. Look for an expression of type "arccos(cos(x))", return x if (AreInverseFunctions(e.childAtIndex(0), e)) { - float trigoOp = e.childAtIndex(0).childAtIndex(0).node()->approximate(float(), context, angleUnit).toScalar(); + float trigoOp = e.childAtIndex(0).childAtIndex(0).node()->approximate(float(), context, complexFormat, angleUnit).toScalar(); if ((e.type() == ExpressionNode::Type::ArcCosine && trigoOp >= 0.0f && trigoOp <= pi) || (e.type() == ExpressionNode::Type::ArcSine && trigoOp >= -pi/2.0f && trigoOp <= pi/2.0f) || (e.type() == ExpressionNode::Type::ArcTangent && trigoOp >= -pi/2.0f && trigoOp <= pi/2.0f)) { @@ -260,7 +260,7 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& c // Step 2. Special case for arctan(sin(x)/cos(x)) if (e.type() == ExpressionNode::Type::ArcTangent && ExpressionIsEquivalentToTangent(e.childAtIndex(0))) { - float trigoOp = e.childAtIndex(0).childAtIndex(1).childAtIndex(0).node()->approximate(float(), context, angleUnit).toScalar(); + float trigoOp = e.childAtIndex(0).childAtIndex(1).childAtIndex(0).node()->approximate(float(), context, complexFormat, angleUnit).toScalar(); if (trigoOp >= -pi/2.0f && trigoOp <= pi/2.0f) { Expression result = e.childAtIndex(0).childAtIndex(1).childAtIndex(0); e.replaceWithInPlace(result); @@ -449,7 +449,7 @@ Expression Trigonometry::table(const Expression e, ExpressionNode::Type type, Co return Expression(); } // We approximate the given expression to quickly compare it to the cheat table entries. - float eValue = e.node()->approximate(float(), context, angleUnit).toScalar(); + float eValue = e.node()->approximate(float(), context, complexFormat, angleUnit).toScalar(); if (std::isnan(eValue) || std::isinf(eValue)) { return Expression(); } From c6cf0eb000e02cb3c985772b0756dffab0ff0ef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 8 Jan 2019 10:21:52 +0100 Subject: [PATCH 213/373] [poincare] Discard BottomUpComputation of ReductionTarget because it is never used --- poincare/include/poincare/expression_node.h | 3 +-- poincare/src/logarithm.cpp | 2 +- poincare/src/multiplication.cpp | 2 +- poincare/src/power.cpp | 10 +++------- poincare/src/trigonometry.cpp | 2 +- 5 files changed, 7 insertions(+), 12 deletions(-) diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index cc546edd4..227dad7ca 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -104,8 +104,7 @@ public: /* Properties */ enum class ReductionTarget { - BottomUpComputation = 0, - TopDownComputation = 1, + TopDownComputation = 0, User }; enum class Sign { diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 3b00882d2..6b7e79818 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -134,7 +134,7 @@ Expression Logarithm::shallowReduce(Context & context, Preferences::ComplexForma * - the reduction is being BottomUp. In this case, we do not yet have any * information on the parent which could later be a power of b. */ - bool letLogAtRoot = target == ExpressionNode::ReductionTarget::BottomUpComputation || parentIsAPowerOfSameBase(); + bool letLogAtRoot = parentIsAPowerOfSameBase(); // log(x^y, b)->y*log(x, b) if x>0 if (!letLogAtRoot && c.type() == ExpressionNode::Type::Power && c.childAtIndex(0).sign(&context) == ExpressionNode::Sign::Positive) { Power p = static_cast(c); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 8314071ec..860a6e5d3 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -453,7 +453,7 @@ Expression Multiplication::privateShallowReduce(Context & context, Preferences:: * Note: This step must be done after Step 4, otherwise we wouldn't be able to * reduce expressions such as (x+y)^(-1)*(x+y)(a+b). */ Expression p = parent(); - if (target != ExpressionNode::ReductionTarget::BottomUpComputation && shouldExpand && (p.isUninitialized() || p.type() != ExpressionNode::Type::Multiplication)) { + if (shouldExpand && (p.isUninitialized() || p.type() != ExpressionNode::Type::Multiplication)) { for (int i = 0; i < numberOfChildren(); i++) { if (childAtIndex(i).type() == ExpressionNode::Type::Addition) { return distributeOnOperandAtIndex(i, context, complexFormat, angleUnit, target); diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 803f4889d..95b52f1bd 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -394,14 +394,10 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co } } - /* We do not apply some rules to a^b if: - * - the parent node is a logarithm of same base a. In this case there is a - * simplication of form ln(e^(3^(1/2))->3^(1/2). - * - the reduction is being BottomUpComputation. In this case, we do not yet have any - * information on the parent which could later be a logarithm of the same - * base. + /* We do not apply some rules to a^b if the parent node is a logarithm of same + * base a. In this case there is a simplication of form ln(e^(3^(1/2))->3^(1/2). */ - bool letPowerAtRoot = target == ExpressionNode::ReductionTarget::BottomUpComputation || parentIsALogarithmOfSameBase(); + bool letPowerAtRoot = parentIsALogarithmOfSameBase(); /* Step 2: we now bubble up ComplexCartesian, we handle different cases: * At least, one child is a ComplexCartesian and the other is either a diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 7f9e3b0f9..786f79872 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -303,7 +303,7 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& c * information on the parent which could later be a cosine, a sine or a tangent. */ Expression p = e.parent(); - bool letArcFunctionAtRoot = target == ExpressionNode::ReductionTarget::BottomUpComputation || (!p.isUninitialized() && isDirectTrigonometryFunction(p)); + bool letArcFunctionAtRoot = !p.isUninitialized() && isDirectTrigonometryFunction(p); /* Step 5. Handle opposite argument: arccos(-x) = Pi-arcos(x), * arcsin(-x) = -arcsin(x), arctan(-x)= -arctan(x) * */ From 1251821d3eb4ad504f22f4c02e1eb9f4af506ea6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 8 Jan 2019 10:26:52 +0100 Subject: [PATCH 214/373] [poincare] Change name: ReductionTarget::TopDownComputation --> ReductionTarget::System --- poincare/include/poincare/expression_node.h | 2 +- poincare/src/expression.cpp | 6 +++--- poincare/src/matrix.cpp | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index 227dad7ca..2a64923b9 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -104,7 +104,7 @@ public: /* Properties */ enum class ReductionTarget { - TopDownComputation = 0, + System = 0, User }; enum class Sign { diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 155c84802..8c58fb08f 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -421,7 +421,7 @@ void Expression::ParseAndSimplifyAndApproximate(const char * text, Expression * Expression Expression::simplify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { sSimplificationHasBeenInterrupted = false; - Expression e = deepReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); + Expression e = deepReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::System); if (!sSimplificationHasBeenInterrupted) { e = e.deepBeautify(context, complexFormat, angleUnit); } @@ -442,7 +442,7 @@ void Expression::simplifyAndApproximate(Expression * simplifiedExpression, Expre Expression e = clone().deepReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); if (sSimplificationHasBeenInterrupted) { sSimplificationHasBeenInterrupted = false; - e = deepReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); + e = deepReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::System); } *simplifiedExpression = Expression(); if (!sSimplificationHasBeenInterrupted) { @@ -529,7 +529,7 @@ Expression Expression::degreeToRadian() { Expression Expression::reduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { sSimplificationHasBeenInterrupted = false; - return deepReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); + return deepReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::System); } Expression Expression::deepReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { diff --git a/poincare/src/matrix.cpp b/poincare/src/matrix.cpp index ff7807e19..181fc72a3 100644 --- a/poincare/src/matrix.cpp +++ b/poincare/src/matrix.cpp @@ -162,7 +162,7 @@ int Matrix::ArrayInverse(T * array, int numberOfRows, int numberOfColumns) { Matrix Matrix::rowCanonize(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, Multiplication determinant) { Expression::SetInterruption(false); // The matrix children have to be reduced to be able to spot 0 - deepReduceChildren(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); + deepReduceChildren(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::System); int m = numberOfRows(); int n = numberOfColumns(); @@ -198,7 +198,7 @@ Matrix Matrix::rowCanonize(Context & context, Preferences::ComplexFormat complex Expression opHJ = matrixChild(h, j); Expression newOpHJ = Division(opHJ, divisor.clone()); replaceChildAtIndexInPlace(h*n+j, newOpHJ); - newOpHJ = newOpHJ.shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); + newOpHJ = newOpHJ.shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::System); } replaceChildInPlace(divisor, Rational(1)); @@ -210,8 +210,8 @@ Matrix Matrix::rowCanonize(Context & context, Preferences::ComplexFormat complex Expression opIJ = matrixChild(i, j); Expression newOpIJ = Subtraction(opIJ, Multiplication(matrixChild(h, j).clone(), factor.clone())); replaceChildAtIndexInPlace(i*n+j, newOpIJ); - newOpIJ.childAtIndex(1).shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); - newOpIJ = newOpIJ.shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::TopDownComputation); + newOpIJ.childAtIndex(1).shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::System); + newOpIJ = newOpIJ.shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::System); } replaceChildAtIndexInPlace(i*n+k, Rational(0)); } From 9709fb66b1230b020e452ebdf0faf41e13b38f2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 8 Jan 2019 12:25:50 +0100 Subject: [PATCH 215/373] [poincare] When approximating, make a special case for x^(p/q) when the complex format is real. In this case, x^(p/q) might have a real result which is not the principale angle returned by the standard library --- poincare/include/poincare/expression.h | 1 + poincare/include/poincare/power.h | 9 ++---- poincare/src/nth_root.cpp | 17 ++++------- poincare/src/power.cpp | 42 ++++++++++++++++++++++++++ poincare/test/complex.cpp | 12 +++++++- poincare/test/helper.cpp | 12 ++++++++ poincare/test/helper.h | 3 ++ 7 files changed, 78 insertions(+), 18 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 4832cc711..82019889e 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -61,6 +61,7 @@ class Expression : public TreeHandle { friend class Multiplication; friend class NaperianLogarithm; friend class NthRoot; + friend class NthRootNode; friend class Number; friend class Opposite; friend class Parenthesis; diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 802eb0569..1c67ce839 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -54,12 +54,9 @@ private: template static MatrixComplex computeOnComplexAndMatrix(const std::complex c, const MatrixComplex n, Preferences::ComplexFormat complexFormat); template static MatrixComplex computeOnMatrixAndComplex(const MatrixComplex m, const std::complex d, Preferences::ComplexFormat complexFormat); template static MatrixComplex computeOnMatrices(const MatrixComplex m, const MatrixComplex n, Preferences::ComplexFormat complexFormat); - Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::MapReduce(this, context, complexFormat, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); - } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { - return ApproximationHelper::MapReduce(this, context, complexFormat, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); - } + template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } }; class Power final : public Expression { diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index 4e7c56e6b..aec8c3549 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -34,17 +34,12 @@ Expression NthRootNode::shallowReduce(Context & context, Preferences::ComplexFor template Evaluation NthRootNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { - Evaluation base = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); - Evaluation index = childAtIndex(1)->approximate(T(), context, complexFormat, angleUnit); - Complex result = Complex::Undefined(); - if (base.type() == EvaluationNode::Type::Complex - && index.type() == EvaluationNode::Type::Complex) - { - Complex basec = static_cast &>(base); - Complex indexc = static_cast &>(index); - result = PowerNode::compute(basec.stdComplex(), std::complex(1.0)/(indexc.stdComplex()), complexFormat); - } - return result; + NthRoot e(this); + /* Turn the root(x,n) into x^(1/n) to use the approximation on power (which + * takes into account the complex format to force to return the real + * approximation when it exists instead of returning the principale value). */ + Expression equivalence = Power(e.childAtIndex(0).clone(), Division(Rational(1), e.childAtIndex(1).clone())); + return equivalence.node()->approximate(T(), context, complexFormat, angleUnit); } Expression NthRoot::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 95b52f1bd..98ec2b09a 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -97,6 +97,48 @@ bool PowerNode::isReal(Context & context) const { // Private +template +Evaluation PowerNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + if (complexFormat == Preferences::ComplexFormat::Real) { + /* If the complexFormat is Real, we look for power of form x^(p/q) with x + * real and p, q integer because they might have a real form which does not + * correspond to the principale angle. */ + Expression index(childAtIndex(1)); + /* We simplify the index to turn its Expression in Rational if possible (ie, + * Decimal, Symbol, Division, Parenthesis can result in Rational). */ + index = index.clone().simplify(context, complexFormat, angleUnit); + if (index.type() == ExpressionNode::Type::Rational) { + Rational r = static_cast(index); + // Check that the base approximation is real + Evaluation baseEvaluation = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); + if (baseEvaluation.type() == EvaluationNode::Type::Complex && static_cast &>(baseEvaluation).imag() == 0.0) { + /* Now we now we the power has a form x^(p/q). We are going to approximate + * it doing x^(p/q) = |x|^(p/q)*sign(x)^(p/q). + * Indeed, |x|^(p/q) is real (since pow: (R+, R) -> R) and we know when + * (-1)^(p/q) is real (see next comment).*/ + std::complex baseEvaluationComplex = static_cast &>(baseEvaluation).stdComplex(); + int signBaseEvaluation = baseEvaluationComplex.real() >= 0.0 ? 1 : -1; + // Compute |x|^(p/q) + baseEvaluationComplex.real(std::fabs(baseEvaluationComplex.real())); + Evaluation indexEvaluation = r.node()->approximate(T(), context, complexFormat, angleUnit); + Complex absBasePowIndex = compute(baseEvaluationComplex, static_cast &>(indexEvaluation).stdComplex(), complexFormat); + assert(absBasePowIndex.imag() == 0.0); + /* (-1)^(p/q) is equal to: + * - 1 if p is even + * - (-1) if q is odd + * - is not real otherwise. */ + if (signBaseEvaluation > 0 || r.signedIntegerNumerator().isEven()) { + return absBasePowIndex; + } else if (!r.integerDenominator().isEven()) { + return Complex(-absBasePowIndex.stdComplex()); + } + } + } + } + // In any other case, we use the principale angle which is done via the standard library + return ApproximationHelper::MapReduce(this, context, complexFormat, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); +} + template Complex PowerNode::compute(const std::complex c, const std::complex d, Preferences::ComplexFormat complexFormat) { std::complex result; diff --git a/poincare/test/complex.cpp b/poincare/test/complex.cpp index 81739f1d4..ee5254c1d 100644 --- a/poincare/test/complex.cpp +++ b/poincare/test/complex.cpp @@ -12,17 +12,27 @@ QUIZ_CASE(poincare_complex_evaluate) { assert_parsed_expression_evaluates_to("R(-1)", "unreal", Radian, Real); assert_parsed_expression_evaluates_to("R(-1)*R(-1)", "unreal", Radian, Real); assert_parsed_expression_evaluates_to("ln(-2)", "unreal", Radian, Real); + assert_parsed_expression_evaluates_without_simplifying_to("(-8)^(1/3)", "-2", Radian, Real); + assert_parsed_expression_evaluates_without_simplifying_to("8^(1/3)", "2", Radian, Real); + assert_parsed_expression_evaluates_without_simplifying_to("(-8)^(2/3)", "4", Radian, Real); + assert_parsed_expression_evaluates_without_simplifying_to("root(-8,3)", "-2", Radian, Real); // Cartesian assert_parsed_expression_evaluates_to("I", "I", Radian, Cartesian); assert_parsed_expression_evaluates_to("R(-1)", "I", Radian, Cartesian); assert_parsed_expression_evaluates_to("R(-1)*R(-1)", "-1", Radian, Cartesian); assert_parsed_expression_evaluates_to("ln(-2)", "6.9314718055995E-1+3.1415926535898*I", Radian, Cartesian); + assert_parsed_expression_evaluates_without_simplifying_to("(-8)^(1/3)", "1+1.7320508075689*I", Radian, Cartesian); + assert_parsed_expression_evaluates_without_simplifying_to("(-8)^(2/3)", "-2+3.464102*I", Radian, Cartesian); + assert_parsed_expression_evaluates_without_simplifying_to("root(-8,3)", "1+1.7320508075689*I", Radian, Cartesian); - // Real + // Polar assert_parsed_expression_evaluates_to("I", "X^(1.570796*I)", Radian, Polar); assert_parsed_expression_evaluates_to("R(-1)", "X^(1.5707963267949*I)", Radian, Polar); assert_parsed_expression_evaluates_to("R(-1)*R(-1)", "X^(3.1415926535898*I)", Radian, Polar); + assert_parsed_expression_evaluates_without_simplifying_to("(-8)^(1/3)", "2*X^(1.0471975511966*I)", Radian, Polar); + assert_parsed_expression_evaluates_without_simplifying_to("(-8)^(2/3)", "4*X^(2.094395*I)", Radian, Polar); + assert_parsed_expression_evaluates_without_simplifying_to("root(-8,3)", "2*X^(1.0471975511966*I)", Radian, Polar); } QUIZ_CASE(poincare_complex_simplify) { diff --git a/poincare/test/helper.cpp b/poincare/test/helper.cpp index 5b8340e85..16051552c 100644 --- a/poincare/test/helper.cpp +++ b/poincare/test/helper.cpp @@ -162,6 +162,16 @@ void assert_parsed_expression_evaluates_to(const char * expression, const char * }, numberOfDigits); } +template +void assert_parsed_expression_evaluates_without_simplifying_to(const char * expression, const char * approximation, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat, int numberOfSignificantDigits) { + int numberOfDigits = sizeof(T) == sizeof(double) ? PrintFloat::k_numberOfStoredSignificantDigits : PrintFloat::k_numberOfPrintedSignificantDigits; + numberOfDigits = numberOfSignificantDigits > 0 ? numberOfSignificantDigits : numberOfDigits; + assert_parsed_expression_process_to(expression, approximation, complexFormat, angleUnit, [](Expression e, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { + return e.approximate(context, complexFormat, angleUnit); + }, numberOfDigits); +} + + template void assert_parsed_expression_approximates_with_value_for_symbol(Expression expression, const char * symbol, T value, T approximation, Poincare::Preferences::ComplexFormat complexFormat, Poincare::Preferences::AngleUnit angleUnit) { Shared::GlobalContext globalContext; @@ -223,5 +233,7 @@ void assert_expression_layout_serialize_to(Poincare::Layout layout, const char * template void assert_parsed_expression_evaluates_to(char const*, char const *, Poincare::Preferences::AngleUnit, Poincare::Preferences::ComplexFormat, int); template void assert_parsed_expression_evaluates_to(char const*, char const *, Poincare::Preferences::AngleUnit, Poincare::Preferences::ComplexFormat, int); +template void assert_parsed_expression_evaluates_without_simplifying_to(char const*, char const *, Poincare::Preferences::AngleUnit, Poincare::Preferences::ComplexFormat, int); +template void assert_parsed_expression_evaluates_without_simplifying_to(char const*, char const *, Poincare::Preferences::AngleUnit, Poincare::Preferences::ComplexFormat, int); template void assert_parsed_expression_approximates_with_value_for_symbol(Poincare::Expression, const char *, float, float, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit); template void assert_parsed_expression_approximates_with_value_for_symbol(Poincare::Expression, const char *, double, double, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit); diff --git a/poincare/test/helper.h b/poincare/test/helper.h index c6a3d1722..42fd24c92 100644 --- a/poincare/test/helper.h +++ b/poincare/test/helper.h @@ -31,6 +31,9 @@ void assert_simplify(const char * expression); template void assert_parsed_expression_evaluates_to(const char * expression, const char * approximation, Poincare::Preferences::AngleUnit angleUnit = Degree, Poincare::Preferences::ComplexFormat complexFormat = Cartesian, int numberOfSignificantDigits = -1); +template +void assert_parsed_expression_evaluates_without_simplifying_to(const char * expression, const char * approximation, Poincare::Preferences::AngleUnit angleUnit = Degree, Poincare::Preferences::ComplexFormat complexFormat = Cartesian, int numberOfSignificantDigits = -1); + template void assert_parsed_expression_approximates_with_value_for_symbol(Poincare::Expression expression, const char * symbol, T value, T approximation, Poincare::Preferences::ComplexFormat complexFormat = Cartesian, Poincare::Preferences::AngleUnit angleUnit = Degree); From 4788495d62beebde70ad5a8bcf29a4d37e9968b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 8 Jan 2019 12:24:11 +0100 Subject: [PATCH 216/373] [poincare/parser] -1/2 gives - 1/2 and not -(1) / 2 --- poincare/src/parsing/parser.cpp | 42 +++++++++++++++++---------------- poincare/src/parsing/parser.h | 34 +++++++++++++------------- poincare/test/parser.cpp | 4 ++-- 3 files changed, 41 insertions(+), 39 deletions(-) diff --git a/poincare/src/parsing/parser.cpp b/poincare/src/parsing/parser.cpp index 01a02b5a5..1b493dea2 100644 --- a/poincare/src/parsing/parser.cpp +++ b/poincare/src/parsing/parser.cpp @@ -2,6 +2,8 @@ namespace Poincare { +static inline Token::Type maxToken(Token::Type x, Token::Type y) { return ((int)x > (int) y ? x : y); } + constexpr const Expression::FunctionHelper * Parser::s_reservedFunctions[]; Expression Parser::parse() { @@ -50,7 +52,7 @@ bool Parser::IsSpecialIdentifierName(const char * name, size_t nameLength) { } Expression Parser::parseUntil(Token::Type stoppingType) { - typedef void (Parser::*TokenParser)(Expression & leftHandSide); + typedef void (Parser::*TokenParser)(Expression & leftHandSide, Token::Type stoppingType); static constexpr TokenParser tokenParsers[] = { &Parser::parseUnexpected, // Token::EndOfStream &Parser::parseStore, // Token::Store @@ -80,7 +82,7 @@ Expression Parser::parseUntil(Token::Type stoppingType) { Expression leftHandSide; do { popToken(); - (this->*(tokenParsers[m_currentToken.type()]))(leftHandSide); + (this->*(tokenParsers[m_currentToken.type()]))(leftHandSide, stoppingType); } while (m_status == Status::Progress && nextTokenHasPrecedenceOver(stoppingType)); return leftHandSide; } @@ -133,11 +135,11 @@ void Parser::isThereImplicitMultiplication() { ); } -void Parser::parseUnexpected(Expression & leftHandSide) { +void Parser::parseUnexpected(Expression & leftHandSide, Token::Type stoppingType) { m_status = Status::Error; // Unexpected Token } -void Parser::parseNumber(Expression & leftHandSide) { +void Parser::parseNumber(Expression & leftHandSide, Token::Type stoppingType) { if (!leftHandSide.isUninitialized()) { m_status = Status::Error; //FIXME return; @@ -150,14 +152,14 @@ void Parser::parseNumber(Expression & leftHandSide) { isThereImplicitMultiplication(); } -void Parser::parsePlus(Expression & leftHandSide) { +void Parser::parsePlus(Expression & leftHandSide, Token::Type stoppingType) { Expression rightHandSide; if (parseBinaryOperator(leftHandSide, rightHandSide, Token::Plus)) { leftHandSide = Addition(leftHandSide, rightHandSide); } } -void Parser::parseEmpty(Expression & leftHandSide) { +void Parser::parseEmpty(Expression & leftHandSide, Token::Type stoppingType) { if (!leftHandSide.isUninitialized()) { m_status = Status::Error; //FIXME return; @@ -165,9 +167,9 @@ void Parser::parseEmpty(Expression & leftHandSide) { leftHandSide = EmptyExpression(); } -void Parser::parseMinus(Expression & leftHandSide) { +void Parser::parseMinus(Expression & leftHandSide, Token::Type stoppingType) { if (leftHandSide.isUninitialized()) { - Expression rightHandSide = parseUntil(Token::Slash); + Expression rightHandSide = parseUntil(maxToken(stoppingType, Token::Minus)); if (m_status != Status::Progress) { return; } @@ -181,35 +183,35 @@ void Parser::parseMinus(Expression & leftHandSide) { } } -void Parser::parseTimes(Expression & leftHandSide) { +void Parser::parseTimes(Expression & leftHandSide, Token::Type stoppingType) { Expression rightHandSide; if (parseBinaryOperator(leftHandSide, rightHandSide, Token::Times)) { leftHandSide = Multiplication(leftHandSide, rightHandSide); } } -void Parser::parseSlash(Expression & leftHandSide) { +void Parser::parseSlash(Expression & leftHandSide, Token::Type stoppingType) { Expression rightHandSide; if (parseBinaryOperator(leftHandSide, rightHandSide, Token::Slash)) { leftHandSide = Division(leftHandSide, rightHandSide); } } -void Parser::parseImplicitTimes(Expression & leftHandSide) { +void Parser::parseImplicitTimes(Expression & leftHandSide, Token::Type stoppingType) { Expression rightHandSide; if (parseBinaryOperator(leftHandSide, rightHandSide, Token::Slash)) { leftHandSide = Multiplication(leftHandSide, rightHandSide); } } -void Parser::parseCaret(Expression & leftHandSide) { +void Parser::parseCaret(Expression & leftHandSide, Token::Type stoppingType) { Expression rightHandSide; if (parseBinaryOperator(leftHandSide, rightHandSide, Token::ImplicitTimes)) { leftHandSide = Power(leftHandSide, rightHandSide); } } -void Parser::parseEqual(Expression & leftHandSide) { +void Parser::parseEqual(Expression & leftHandSide, Token::Type stoppingType) { if (leftHandSide.isUninitialized()) { m_status = Status::Error; // Equal must have a left operand return; @@ -226,7 +228,7 @@ void Parser::parseEqual(Expression & leftHandSide) { } } -void Parser::parseStore(Expression & leftHandSide) { +void Parser::parseStore(Expression & leftHandSide, Token::Type stoppingType) { if (leftHandSide.isUninitialized()) { m_status = Status::Error; // Left-hand side missing. return; @@ -253,7 +255,7 @@ void Parser::parseStore(Expression & leftHandSide) { leftHandSide = Store(leftHandSide, static_cast(rightHandSide)); } -void Parser::parseLeftSuperscript(Expression & leftHandSide) { +void Parser::parseLeftSuperscript(Expression & leftHandSide, Token::Type stoppingType) { if (leftHandSide.isUninitialized()) { m_status = Status::Error; // Power must have a left operand return; @@ -286,7 +288,7 @@ bool Parser::parseBinaryOperator(const Expression & leftHandSide, Expression & r return true; } -void Parser::parseLeftParenthesis(Expression & leftHandSide) { +void Parser::parseLeftParenthesis(Expression & leftHandSide, Token::Type stoppingType) { if (!leftHandSide.isUninitialized()) { m_status = Status::Error; //FIXME return; @@ -303,7 +305,7 @@ void Parser::parseLeftParenthesis(Expression & leftHandSide) { isThereImplicitMultiplication(); } -void Parser::parseBang(Expression & leftHandSide) { +void Parser::parseBang(Expression & leftHandSide, Token::Type stoppingType) { if (leftHandSide.isUninitialized()) { m_status = Status::Error; // Left-hand side missing } else { @@ -320,7 +322,7 @@ bool Parser::currentTokenIsSpecialIdentifier() const { return IsSpecialIdentifierName(m_currentToken.text(), m_currentToken.length()); } -void Parser::parseConstant(Expression & leftHandSide) { +void Parser::parseConstant(Expression & leftHandSide, Token::Type stoppingType) { leftHandSide = Constant(m_currentToken.text()[0]); isThereImplicitMultiplication(); } @@ -432,7 +434,7 @@ void Parser::parseCustomIdentifier(Expression & leftHandSide, const char * name, } } -void Parser::parseIdentifier(Expression & leftHandSide) { +void Parser::parseIdentifier(Expression & leftHandSide, Token::Type stoppingType) { if (!leftHandSide.isUninitialized()) { m_status = Status::Error; //FIXME return; @@ -470,7 +472,7 @@ Expression Parser::parseFunctionParameters() { return commaSeparatedList; } -void Parser::parseMatrix(Expression & leftHandSide) { +void Parser::parseMatrix(Expression & leftHandSide, Token::Type stoppingType) { if (!leftHandSide.isUninitialized()) { m_status = Status::Error; //FIXME return; diff --git a/poincare/src/parsing/parser.h b/poincare/src/parsing/parser.h index ca3d28b05..bd591b4dc 100644 --- a/poincare/src/parsing/parser.h +++ b/poincare/src/parsing/parser.h @@ -45,23 +45,23 @@ private: void isThereImplicitMultiplication(); // Specific Token parsers - void parseUnexpected(Expression & leftHandSide); - void parseNumber(Expression & leftHandSide); - void parseConstant(Expression & leftHandSide); - void parseIdentifier(Expression & leftHandSide); - void parseEmpty(Expression & leftHandSide); - void parseMatrix(Expression & leftHandSide); - void parseLeftParenthesis(Expression & leftHandSide); - void parseBang(Expression & leftHandSide); - void parsePlus(Expression & leftHandSide); - void parseMinus(Expression & leftHandSide); - void parseTimes(Expression & leftHandSide); - void parseSlash(Expression & leftHandSide); - void parseImplicitTimes(Expression & leftHandSide); - void parseCaret(Expression & leftHandSide); - void parseEqual(Expression & leftHandSide); - void parseStore(Expression & leftHandSide); - void parseLeftSuperscript(Expression & leftHandSide); + void parseUnexpected(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); + void parseNumber(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); + void parseConstant(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); + void parseIdentifier(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); + void parseEmpty(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); + void parseMatrix(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); + void parseLeftParenthesis(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); + void parseBang(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); + void parsePlus(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); + void parseMinus(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); + void parseTimes(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); + void parseSlash(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); + void parseImplicitTimes(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); + void parseCaret(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); + void parseEqual(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); + void parseStore(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); + void parseLeftSuperscript(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); // Parsing helpers bool parseBinaryOperator(const Expression & leftHandSide, Expression & rightHandSide, Token::Type stoppingType); diff --git a/poincare/test/parser.cpp b/poincare/test/parser.cpp index 1bbfe27b5..53c1690db 100644 --- a/poincare/test/parser.cpp +++ b/poincare/test/parser.cpp @@ -161,11 +161,11 @@ QUIZ_CASE(poincare_parser_parse) { assert_parsed_expression_is("1^2-3", Subtraction(Power(Rational(1),Rational(2)),Rational(3))); assert_parsed_expression_is("2^-3", Power(Rational(2),Opposite(Rational(3)))); assert_parsed_expression_is("2--2+-1", Addition(Subtraction(Rational(2),Opposite(Rational(2))),Opposite(Rational(1)))); - assert_parsed_expression_is("2--2*-1", Subtraction(Rational(2),Multiplication(Opposite(Rational(2)),Opposite(Rational(1))))); + assert_parsed_expression_is("2--2*-1", Subtraction(Rational(2),Opposite(Multiplication(Rational(2),Opposite(Rational(1)))))); assert_parsed_expression_is("-1^2", Opposite(Power(Rational(1),Rational(2)))); assert_parsed_expression_is("2/-3/-4", Division(Division(Rational(2),Opposite(Rational(3))),Opposite(Rational(4)))); assert_parsed_expression_is("1*2-3*4", Subtraction(Multiplication(Rational(1),Rational(2)),Multiplication(Rational(3),Rational(4)))); - assert_parsed_expression_is("-1*2", Multiplication(Opposite(Rational(1)), Rational(2))); // Unary minus shall have precedence + assert_parsed_expression_is("-1*2", Opposite(Multiplication(Rational(1), Rational(2)))); assert_parsed_expression_is("1!", Factorial(Rational(1))); assert_parsed_expression_is("1+2!", Addition(Rational(1),Factorial(Rational(2)))); assert_parsed_expression_is("1!+2", Addition(Factorial(Rational(1)),Rational(2))); From 56aaea79cb01f1be465f493569d8bd45178c0f5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 8 Jan 2019 16:23:51 +0100 Subject: [PATCH 217/373] [poincare/rational] Fix template declaration --- poincare/src/rational.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index 78c591320..97af87d19 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -290,6 +290,7 @@ Expression Rational::setSign(ExpressionNode::Sign s) { return *this; } +template float RationalNode::templatedApproximate() const; template double RationalNode::templatedApproximate() const; } From a24f65bd46c801e3bd49f78cf0af5a6c15d4e50b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 8 Jan 2019 17:52:17 +0100 Subject: [PATCH 218/373] [poincare] Revert special case when approximating x^(p/q) with x real and p, q integer That hugely slows down the approximation routine --- poincare/include/poincare/expression.h | 1 - poincare/include/poincare/power.h | 9 ++++-- poincare/src/nth_root.cpp | 17 +++++++---- poincare/src/power.cpp | 42 -------------------------- 4 files changed, 17 insertions(+), 52 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 82019889e..4832cc711 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -61,7 +61,6 @@ class Expression : public TreeHandle { friend class Multiplication; friend class NaperianLogarithm; friend class NthRoot; - friend class NthRootNode; friend class Number; friend class Opposite; friend class Parenthesis; diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 1c67ce839..802eb0569 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -54,9 +54,12 @@ private: template static MatrixComplex computeOnComplexAndMatrix(const std::complex c, const MatrixComplex n, Preferences::ComplexFormat complexFormat); template static MatrixComplex computeOnMatrixAndComplex(const MatrixComplex m, const std::complex d, Preferences::ComplexFormat complexFormat); template static MatrixComplex computeOnMatrices(const MatrixComplex m, const MatrixComplex n, Preferences::ComplexFormat complexFormat); - template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; - Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::MapReduce(this, context, complexFormat, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); + } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { + return ApproximationHelper::MapReduce(this, context, complexFormat, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); + } }; class Power final : public Expression { diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index aec8c3549..4e7c56e6b 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -34,12 +34,17 @@ Expression NthRootNode::shallowReduce(Context & context, Preferences::ComplexFor template Evaluation NthRootNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { - NthRoot e(this); - /* Turn the root(x,n) into x^(1/n) to use the approximation on power (which - * takes into account the complex format to force to return the real - * approximation when it exists instead of returning the principale value). */ - Expression equivalence = Power(e.childAtIndex(0).clone(), Division(Rational(1), e.childAtIndex(1).clone())); - return equivalence.node()->approximate(T(), context, complexFormat, angleUnit); + Evaluation base = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); + Evaluation index = childAtIndex(1)->approximate(T(), context, complexFormat, angleUnit); + Complex result = Complex::Undefined(); + if (base.type() == EvaluationNode::Type::Complex + && index.type() == EvaluationNode::Type::Complex) + { + Complex basec = static_cast &>(base); + Complex indexc = static_cast &>(index); + result = PowerNode::compute(basec.stdComplex(), std::complex(1.0)/(indexc.stdComplex()), complexFormat); + } + return result; } Expression NthRoot::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 98ec2b09a..95b52f1bd 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -97,48 +97,6 @@ bool PowerNode::isReal(Context & context) const { // Private -template -Evaluation PowerNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { - if (complexFormat == Preferences::ComplexFormat::Real) { - /* If the complexFormat is Real, we look for power of form x^(p/q) with x - * real and p, q integer because they might have a real form which does not - * correspond to the principale angle. */ - Expression index(childAtIndex(1)); - /* We simplify the index to turn its Expression in Rational if possible (ie, - * Decimal, Symbol, Division, Parenthesis can result in Rational). */ - index = index.clone().simplify(context, complexFormat, angleUnit); - if (index.type() == ExpressionNode::Type::Rational) { - Rational r = static_cast(index); - // Check that the base approximation is real - Evaluation baseEvaluation = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); - if (baseEvaluation.type() == EvaluationNode::Type::Complex && static_cast &>(baseEvaluation).imag() == 0.0) { - /* Now we now we the power has a form x^(p/q). We are going to approximate - * it doing x^(p/q) = |x|^(p/q)*sign(x)^(p/q). - * Indeed, |x|^(p/q) is real (since pow: (R+, R) -> R) and we know when - * (-1)^(p/q) is real (see next comment).*/ - std::complex baseEvaluationComplex = static_cast &>(baseEvaluation).stdComplex(); - int signBaseEvaluation = baseEvaluationComplex.real() >= 0.0 ? 1 : -1; - // Compute |x|^(p/q) - baseEvaluationComplex.real(std::fabs(baseEvaluationComplex.real())); - Evaluation indexEvaluation = r.node()->approximate(T(), context, complexFormat, angleUnit); - Complex absBasePowIndex = compute(baseEvaluationComplex, static_cast &>(indexEvaluation).stdComplex(), complexFormat); - assert(absBasePowIndex.imag() == 0.0); - /* (-1)^(p/q) is equal to: - * - 1 if p is even - * - (-1) if q is odd - * - is not real otherwise. */ - if (signBaseEvaluation > 0 || r.signedIntegerNumerator().isEven()) { - return absBasePowIndex; - } else if (!r.integerDenominator().isEven()) { - return Complex(-absBasePowIndex.stdComplex()); - } - } - } - } - // In any other case, we use the principale angle which is done via the standard library - return ApproximationHelper::MapReduce(this, context, complexFormat, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); -} - template Complex PowerNode::compute(const std::complex c, const std::complex d, Preferences::ComplexFormat complexFormat) { std::complex result; From f6026254be2b712db412e08a35e56a56d688dd91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 8 Jan 2019 18:20:47 +0100 Subject: [PATCH 219/373] [poincare] Add an argument ReductionTarget to shallowBeautify --- poincare/include/poincare/addition.h | 4 ++-- poincare/include/poincare/complex_cartesian.h | 4 ++-- poincare/include/poincare/decimal.h | 4 ++-- poincare/include/poincare/expression.h | 4 ++-- poincare/include/poincare/expression_node.h | 2 +- poincare/include/poincare/factor.h | 2 +- poincare/include/poincare/factorial.h | 4 ++-- poincare/include/poincare/logarithm.h | 4 ++-- poincare/include/poincare/multiplication.h | 4 ++-- poincare/include/poincare/power.h | 4 ++-- poincare/include/poincare/rational.h | 4 ++-- poincare/src/addition.cpp | 8 ++++---- poincare/src/complex_cartesian.cpp | 10 +++++----- poincare/src/decimal.cpp | 6 +++--- poincare/src/expression.cpp | 18 +++++++++--------- poincare/src/expression_node.cpp | 2 +- poincare/src/factor.cpp | 2 +- poincare/src/factorial.cpp | 6 +++--- poincare/src/logarithm.cpp | 8 ++++---- poincare/src/multiplication.cpp | 14 +++++++------- poincare/src/power.cpp | 8 ++++---- poincare/src/rational.cpp | 6 +++--- 22 files changed, 64 insertions(+), 64 deletions(-) diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index d34ef2e04..fd6f95dba 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -43,7 +43,7 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; - Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) override; + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; /* Evaluation */ template static MatrixComplex computeOnMatrixAndComplex(const MatrixComplex m, const std::complex c, Preferences::ComplexFormat complexFormat) { @@ -75,7 +75,7 @@ public: } // Expression Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const; private: static const Number NumeralFactor(const Expression & e); diff --git a/poincare/include/poincare/complex_cartesian.h b/poincare/include/poincare/complex_cartesian.h index a2d17bfb3..e86835e64 100644 --- a/poincare/include/poincare/complex_cartesian.h +++ b/poincare/include/poincare/complex_cartesian.h @@ -28,7 +28,7 @@ private: Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; - Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) override; + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; private: template Complex templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; @@ -47,7 +47,7 @@ public: // Simplification Expression shallowReduce(); - Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); // Common operations (done in-place) Expression squareNorm(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index 446df5784..3c86ff89d 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -63,7 +63,7 @@ public: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; - Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) override; + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Serialization int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = 0) const override; @@ -105,7 +105,7 @@ private: Expression setSign(ExpressionNode::Sign s); // Simplification Expression shallowReduce(); - Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowBeautify(); }; } diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 4832cc711..4abcf337f 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -285,8 +285,8 @@ protected: Expression makePositiveAnyNegativeNumeralFactor(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); Expression denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { return node()->denominator(context, complexFormat, angleUnit); } Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { return node()->shallowReduce(context, complexFormat, angleUnit, target); } - Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { return node()->shallowBeautify(context, complexFormat, angleUnit); } - Expression deepBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { return node()->shallowBeautify(context, complexFormat, angleUnit, target); } + Expression deepBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index 2a64923b9..372da561c 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -162,7 +162,7 @@ public: /* Simplification */ /*!*/ virtual void deepReduceChildren(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target); /*!*/ virtual Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target); - /*!*/ virtual Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + /*!*/ virtual Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target); /* Return a clone of the denominator part of the expression */ /*!*/ virtual Expression denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; diff --git a/poincare/include/poincare/factor.h b/poincare/include/poincare/factor.h index 62d340374..401a90126 100644 --- a/poincare/include/poincare/factor.h +++ b/poincare/include/poincare/factor.h @@ -25,7 +25,7 @@ private: /* Serialization */ int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; /* Simplification */ - Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) override; + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; /* Evaluation */ Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index 6b0819b76..315010f42 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -33,7 +33,7 @@ private: int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplication Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; - Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) override; + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { @@ -58,7 +58,7 @@ public: } Expression shallowReduce(); - Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowBeautify(); private: constexpr static int k_maxOperandValue = 100; }; diff --git a/poincare/include/poincare/logarithm.h b/poincare/include/poincare/logarithm.h index a92b59757..9bc82b5dd 100644 --- a/poincare/include/poincare/logarithm.h +++ b/poincare/include/poincare/logarithm.h @@ -28,7 +28,7 @@ public: int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; - Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) override; + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { /* log has a branch cut on ]-inf, 0]: it is then multivalued on this cut. We @@ -49,7 +49,7 @@ public: static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("log", 2, &UntypedBuilder); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowBeautify(); private: Logarithm(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode >()) { diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index dfdf10120..fadc6780a 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -45,7 +45,7 @@ private: // Simplification Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; - Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) override; + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; Expression denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override; /* Approximation */ @@ -82,7 +82,7 @@ public: // Expression Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const; Expression denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; private: diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 802eb0569..b506cac49 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -46,7 +46,7 @@ private: // Simplify Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; - Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) override; + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; int simplificationOrderGreaterType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const override; int simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const override; Expression denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override; @@ -71,7 +71,7 @@ public: Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const; Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: constexpr static int k_maxExactPowerMatrix = 100; diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index 99009e4f2..d9c3c8612 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -58,7 +58,7 @@ public: private: int simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const override; Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; - Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) override; + Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; Expression setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; Expression denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override; bool m_negative; @@ -115,7 +115,7 @@ private: RationalNode * node() { return static_cast(Number::node()); } /* Simplification */ - Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + Expression shallowBeautify(); Expression denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; Expression setSign(ExpressionNode::Sign s); }; diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 6292b370a..6a34b2243 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -54,8 +54,8 @@ Expression AdditionNode::shallowReduce(Context & context, Preferences::ComplexFo return Addition(this).shallowReduce(context, complexFormat, angleUnit, target); } -Expression AdditionNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { - return Addition(this).shallowBeautify(context, complexFormat, angleUnit); +Expression AdditionNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Addition(this).shallowBeautify(context, complexFormat, angleUnit, target); } // Addition @@ -88,7 +88,7 @@ int Addition::getPolynomialCoefficients(Context & context, const char * symbolNa return deg; } -Expression Addition::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression Addition::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { /* Beautifying AdditionNode essentially consists in adding Subtractions if * needed. * In practice, we want to turn "a+(-1)*b" into "a-b". Or, more precisely, any @@ -106,7 +106,7 @@ Expression Addition::shallowBeautify(Context & context, Preferences::ComplexForm for (int i = 0; i < numberOfChildren(); i++) { // Try to make the child i positive if any negative numeral factor is found - Expression subtractant = childAtIndex(i).makePositiveAnyNegativeNumeralFactor(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); + Expression subtractant = childAtIndex(i).makePositiveAnyNegativeNumeralFactor(context, complexFormat, angleUnit, target); if (subtractant.isUninitialized()) { // if subtractant is not initialized, it means the child i had no negative numeral factor diff --git a/poincare/src/complex_cartesian.cpp b/poincare/src/complex_cartesian.cpp index 83b6725ce..b8682a89e 100644 --- a/poincare/src/complex_cartesian.cpp +++ b/poincare/src/complex_cartesian.cpp @@ -23,8 +23,8 @@ Expression ComplexCartesianNode::shallowReduce(Context & context, Preferences::C return ComplexCartesian(this).shallowReduce(); } -Expression ComplexCartesianNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { - return ComplexCartesian(this).shallowBeautify(context, complexFormat, angleUnit); +Expression ComplexCartesianNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return ComplexCartesian(this).shallowBeautify(context, complexFormat, angleUnit, target); } template @@ -49,11 +49,11 @@ Expression ComplexCartesian::shallowReduce() { return *this; } -Expression ComplexCartesian::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression ComplexCartesian::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { Expression a = real(); Expression b = imag(); - Expression oppositeA = a.makePositiveAnyNegativeNumeralFactor(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); - Expression oppositeB = b.makePositiveAnyNegativeNumeralFactor(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); + Expression oppositeA = a.makePositiveAnyNegativeNumeralFactor(context, complexFormat, angleUnit, target); + Expression oppositeB = b.makePositiveAnyNegativeNumeralFactor(context, complexFormat, angleUnit, target); a = oppositeA.isUninitialized() ? a : oppositeA; b = oppositeB.isUninitialized() ? b : oppositeB; Expression e = Expression::CreateComplexExpression(a, b, Preferences::ComplexFormat::Cartesian, diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index 8aa6cc094..56e3f208f 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -92,8 +92,8 @@ Expression DecimalNode::shallowReduce(Context & context, Preferences::ComplexFor return Decimal(this).shallowReduce(); } -Expression DecimalNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { - return Decimal(this).shallowBeautify(context, complexFormat, angleUnit); +Expression DecimalNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Decimal(this).shallowBeautify(); } Layout DecimalNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -373,7 +373,7 @@ Expression Decimal::shallowReduce() { return result; } -Expression Decimal::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression Decimal::shallowBeautify() { if (sign() == ExpressionNode::Sign::Negative) { Expression abs = setSign(ExpressionNode::Sign::Positive); Opposite o; diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 8c58fb08f..8e1808823 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -423,7 +423,7 @@ Expression Expression::simplify(Context & context, Preferences::ComplexFormat co sSimplificationHasBeenInterrupted = false; Expression e = deepReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::System); if (!sSimplificationHasBeenInterrupted) { - e = e.deepBeautify(context, complexFormat, angleUnit); + e = e.deepBeautify(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::System); } return sSimplificationHasBeenInterrupted ? Expression() : e; } @@ -461,15 +461,15 @@ void Expression::simplifyAndApproximate(Expression * simplifiedExpression, Expre // Clone the ComplexCartesian to use it to compute the approximation ComplexCartesian ecomplexClone = ecomplex.clone().convert(); // To minimize the error on the approximation, we reduce the number of nodes in the expression by beautifying - ecomplexClone.real().deepBeautify(context, complexFormat, angleUnit); - ecomplexClone.imag().deepBeautify(context, complexFormat, angleUnit); + ecomplexClone.real().deepBeautify(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); + ecomplexClone.imag().deepBeautify(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); *approximateExpression = ecomplexClone.approximate(context, complexFormat, angleUnit); } // Step 3: create the simplied expression with the required complex format Expression ra = complexFormat == Preferences::ComplexFormat::Polar ? ecomplex.clone().convert().norm(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User).shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User) : ecomplex.real(); Expression tb = complexFormat == Preferences::ComplexFormat::Polar ? ecomplex.argument(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User).shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User) : ecomplex.imag(); - ra = ra.deepBeautify(context, complexFormat, angleUnit); - tb = tb.deepBeautify(context, complexFormat, angleUnit); + ra = ra.deepBeautify(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); + tb = tb.deepBeautify(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); bool raIsNegative = false; bool tbIsNegative = false; makePositive(&ra, &raIsNegative); @@ -478,7 +478,7 @@ void Expression::simplifyAndApproximate(Expression * simplifiedExpression, Expre } else { /* Case 2: The reduced expression has a complex component that could not * be bubbled up. */ - *simplifiedExpression = e.deepBeautify(context, complexFormat, angleUnit); + *simplifiedExpression = e.deepBeautify(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); if (approximateExpression) { *approximateExpression = simplifiedExpression->approximate(context, complexFormat, angleUnit); } @@ -548,11 +548,11 @@ Expression Expression::deepReduce(Context & context, Preferences::ComplexFormat return shallowReduce(context, complexFormat, angleUnit, target); } -Expression Expression::deepBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { - Expression e = shallowBeautify(context, complexFormat, angleUnit); +Expression Expression::deepBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + Expression e = shallowBeautify(context, complexFormat, angleUnit, target); int nbChildren = e.numberOfChildren(); for (int i = 0; i < nbChildren; i++) { - e.childAtIndex(i).deepBeautify(context, complexFormat, angleUnit); + e.childAtIndex(i).deepBeautify(context, complexFormat, angleUnit, target); } return e; } diff --git a/poincare/src/expression_node.cpp b/poincare/src/expression_node.cpp index 476cc2e4f..b87fbf347 100644 --- a/poincare/src/expression_node.cpp +++ b/poincare/src/expression_node.cpp @@ -116,7 +116,7 @@ Expression ExpressionNode::shallowReduce(Context & context, Preferences::Complex return Expression(this).defaultShallowReduce(); } -Expression ExpressionNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression ExpressionNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { return Expression(this).defaultShallowBeautify(); } diff --git a/poincare/src/factor.cpp b/poincare/src/factor.cpp index e1da25442..0f9ae90a3 100644 --- a/poincare/src/factor.cpp +++ b/poincare/src/factor.cpp @@ -26,7 +26,7 @@ int FactorNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloat return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, Factor::s_functionHelper.name()); } -Expression FactorNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression FactorNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { return Factor(this).shallowBeautify(context, complexFormat, angleUnit); } diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index 65563a800..289c504ab 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -38,8 +38,8 @@ Expression FactorialNode::shallowReduce(Context & context, Preferences::ComplexF return Factorial(this).shallowReduce(); } -Expression FactorialNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { - return Factorial(this).shallowBeautify(context, complexFormat, angleUnit); +Expression FactorialNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Factorial(this).shallowBeautify(); } template @@ -127,7 +127,7 @@ Expression Factorial::shallowReduce() { return *this; } -Expression Factorial::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression Factorial::shallowBeautify() { // +(a,b)! ->(+(a,b))! if (childAtIndex(0).type() == ExpressionNode::Type::Addition || childAtIndex(0).type() == ExpressionNode::Type::Multiplication diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 6b7e79818..2f773a16a 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -58,13 +58,13 @@ Expression LogarithmNode<2>::shallowReduce(Context & context, Preferences::Compl } template<> -Expression LogarithmNode<1>::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression LogarithmNode<1>::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { return CommonLogarithm(this); } template<> -Expression LogarithmNode<2>::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { - return Logarithm(this).shallowBeautify(context, complexFormat, angleUnit); +Expression LogarithmNode<2>::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + return Logarithm(this).shallowBeautify(); } template<> @@ -309,7 +309,7 @@ Expression Logarithm::splitLogarithmInteger(Integer i, bool isDenominator, Conte return a; } -Expression Logarithm::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression Logarithm::shallowBeautify() { assert(numberOfChildren() == 2); Constant e = Constant(Ion::Charset::Exponential); if (childAtIndex(1).isIdenticalTo(e)) { diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 860a6e5d3..132f7b888 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -97,8 +97,8 @@ Expression MultiplicationNode::shallowReduce(Context & context, Preferences::Com return Multiplication(this).shallowReduce(context, complexFormat, angleUnit, target); } -Expression MultiplicationNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { - return Multiplication(this).shallowBeautify(context, complexFormat, angleUnit); +Expression MultiplicationNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Multiplication(this).shallowBeautify(context, complexFormat, angleUnit, target); } Expression MultiplicationNode::denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { @@ -136,7 +136,7 @@ Expression Multiplication::shallowReduce(Context & context, Preferences::Complex return privateShallowReduce(context, complexFormat, angleUnit, target, true, true); } -Expression Multiplication::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression Multiplication::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { /* Beautifying a Multiplication consists in several possible operations: * - Add Opposite ((-3)*x -> -(3*x), useful when printing fractions) * - Adding parenthesis if needed (a*(b+c) is not a*b+c) @@ -144,7 +144,7 @@ Expression Multiplication::shallowBeautify(Context & context, Preferences::Compl * shall become a/b) or a non-integer rational term (3/2*a -> (3*a)/2). */ // Step 1: Turn -n*A into -(n*A) - Expression noNegativeNumeral = makePositiveAnyNegativeNumeralFactor(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); + Expression noNegativeNumeral = makePositiveAnyNegativeNumeralFactor(context, complexFormat, angleUnit, target); // If one negative numeral factor was made positive, we turn the expression in an Opposite if (!noNegativeNumeral.isUninitialized()) { Opposite o = Opposite(); @@ -157,7 +157,7 @@ Expression Multiplication::shallowBeautify(Context & context, Preferences::Compl * This also turns 2/3*a into 2*a*3^(-1) */ Expression thisExp = mergeNegativePower(context, complexFormat, angleUnit); if (thisExp.type() == ExpressionNode::Type::Power) { - return thisExp.shallowBeautify(context, complexFormat, angleUnit); + return thisExp.shallowBeautify(context, complexFormat, angleUnit, target); } assert(thisExp.type() == ExpressionNode::Type::Multiplication); @@ -181,7 +181,7 @@ Expression Multiplication::shallowBeautify(Context & context, Preferences::Compl Expression denominatorOperand = childI.childAtIndex(0); removeChildInPlace(childI, childI.numberOfChildren()); - Expression numeratorOperand = shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); + Expression numeratorOperand = shallowReduce(context, complexFormat, angleUnit, target); // Delete unnecessary parentheses on numerator if (numeratorOperand.type() == ExpressionNode::Type::Parenthesis) { Expression numeratorChild0 = numeratorOperand.childAtIndex(0); @@ -193,7 +193,7 @@ Expression Multiplication::shallowBeautify(Context & context, Preferences::Compl numeratorOperand.replaceWithInPlace(d); d.replaceChildAtIndexInPlace(0, numeratorOperand); d.replaceChildAtIndexInPlace(1, denominatorOperand); - return d.shallowBeautify(context, complexFormat, angleUnit); + return d.shallowBeautify(context, complexFormat, angleUnit, target); } return thisExp; } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 95b52f1bd..babb69d31 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -169,8 +169,8 @@ Expression PowerNode::shallowReduce(Context & context, Preferences::ComplexForma return Power(this).shallowReduce(context, complexFormat, angleUnit, target); } -Expression PowerNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { - return Power(this).shallowBeautify(context, complexFormat, angleUnit); +Expression PowerNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + return Power(this).shallowBeautify(context, complexFormat, angleUnit, target); } int PowerNode::simplificationOrderGreaterType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const { @@ -757,7 +757,7 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co return *this; } -Expression Power::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression Power::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { // Step 1: X^-y -> 1/(X->shallowBeautify)^y Expression p = denominator(context, complexFormat, angleUnit); // If the denominator is initialized, the index of the power is of form -y @@ -765,7 +765,7 @@ Expression Power::shallowBeautify(Context & context, Preferences::ComplexFormat Division d = Division(Rational(1), p); p.shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); replaceWithInPlace(d); - return d.shallowBeautify(context, complexFormat, angleUnit); + return d.shallowBeautify(context, complexFormat, angleUnit, target); } // Step 2: Turn a^(1/n) into root(a, n) if (childAtIndex(1).type() == ExpressionNode::Type::Rational && childAtIndex(1).convert().signedIntegerNumerator().isOne()) { diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index 97af87d19..3e4ff391d 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -150,8 +150,8 @@ Expression RationalNode::shallowReduce(Context & context, Preferences::ComplexFo return Rational(this).shallowReduce(); } -Expression RationalNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { - return Rational(this).shallowBeautify(context, complexFormat, angleUnit); +Expression RationalNode::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + return Rational(this).shallowBeautify(); } Expression RationalNode::denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { @@ -262,7 +262,7 @@ Expression Rational::shallowReduce() { return *this; } -Expression Rational::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +Expression Rational::shallowBeautify() { if (sign() == ExpressionNode::Sign::Negative) { Expression abs = setSign(ExpressionNode::Sign::Positive); Opposite o; From 2a71f2bada03d5cc6d5e98767f5104b26767d20d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 8 Jan 2019 18:22:12 +0100 Subject: [PATCH 220/373] [poincare] NthRoot: special case for approximation of form root(x,p) with x real and p integer in Real complex format In this case, root(x,p) might have a real result which is not the principale angle returned by the standard library --- poincare/src/nth_root.cpp | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index 4e7c56e6b..e0d5360dc 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -40,9 +40,25 @@ Evaluation NthRootNode::templatedApproximate(Context& context, Preferences::C if (base.type() == EvaluationNode::Type::Complex && index.type() == EvaluationNode::Type::Complex) { - Complex basec = static_cast &>(base); - Complex indexc = static_cast &>(index); - result = PowerNode::compute(basec.stdComplex(), std::complex(1.0)/(indexc.stdComplex()), complexFormat); + std::complex basec = static_cast &>(base).stdComplex(); + std::complex indexc = static_cast &>(index).stdComplex(); + /* If the complexFormat is Real, we look for nthroot of form root(x,q) with + * x real and q integer because they might have a real form which does not + * correspond to the principale angle. */ + if (complexFormat == Preferences::ComplexFormat::Real) { + // root(x, q) with q integer and x real + if (basec.imag() == 0.0 && indexc.imag() == 0.0 && std::round(indexc.real()) == indexc.real()) { + std::complex absBasec = basec; + absBasec.real(std::fabs(absBasec.real())); + // compute root(|x|, q) + Complex absBasePowIndex = PowerNode::compute(absBasec, std::complex(1.0)/(indexc), complexFormat); + // q odd if (-1)^q = -1 + if (std::pow(-1.0, indexc.real()) < 0.0) { + return basec.real() < 0 ? Complex(-absBasePowIndex.stdComplex()) : absBasePowIndex; + } + } + } + result = PowerNode::compute(basec, std::complex(1.0)/(indexc), complexFormat); } return result; } From 43522d0dc95ce5bab23b3ac20c235b1c3f548269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 8 Jan 2019 18:23:16 +0100 Subject: [PATCH 221/373] [poincare] Power: shallowBeautify for ReductionTarget::System turn x^(p/q) into root(x,q)^p to use the special case of root(x, p) with x real and p integer might have a real solution in 'Real' complex format --- poincare/src/power.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index babb69d31..b88399fe2 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -781,7 +781,16 @@ Expression Power::shallowBeautify(Context & context, Preferences::ComplexFormat return result; } - // Step 3: +(a,b)^c ->(+(a,b))^c and *(a,b)^c ->(*(a,b))^c + // Optional Step 3: if the ReductionTarget is the System, turn a^(p/q) into (root(a, q))^p + if (target == ExpressionNode::ReductionTarget::System && childAtIndex(1).type() == ExpressionNode::Type::Rational) { + Integer p = childAtIndex(1).convert().signedIntegerNumerator(); + Integer q = childAtIndex(1).convert().integerDenominator(); + Expression result = Power(NthRoot::Builder(childAtIndex(0), Rational(q)), Rational(p)); + replaceWithInPlace(result); + return result; + } + + // Step 4: +(a,b)^c ->(+(a,b))^c and *(a,b)^c ->(*(a,b))^c if (childAtIndex(0).type() == ExpressionNode::Type::Addition || childAtIndex(0).type() == ExpressionNode::Type::Multiplication) { From 05bfbe83acdf248608addf35447c1c257adb1d2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 Jan 2019 10:00:13 +0100 Subject: [PATCH 222/373] [escher/pointer_text_view] Clean minimalSizeForOptimalDisplay It was unneedingly overriden + added escape case on nullptr text --- escher/include/escher/pointer_text_view.h | 1 - escher/src/pointer_text_view.cpp | 4 ---- escher/src/text_view.cpp | 3 +++ 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/escher/include/escher/pointer_text_view.h b/escher/include/escher/pointer_text_view.h index 432ee3147..bb2ec650d 100644 --- a/escher/include/escher/pointer_text_view.h +++ b/escher/include/escher/pointer_text_view.h @@ -10,7 +10,6 @@ public: KDColor textColor = KDColorBlack, KDColor backgroundColor = KDColorWhite); const char * text() const override { return m_text; } void setText(const char * text) override; - KDSize minimalSizeForOptimalDisplay() const override; private: const char * m_text; }; diff --git a/escher/src/pointer_text_view.cpp b/escher/src/pointer_text_view.cpp index 892311ee5..59d239050 100644 --- a/escher/src/pointer_text_view.cpp +++ b/escher/src/pointer_text_view.cpp @@ -14,7 +14,3 @@ void PointerTextView::setText(const char * text) { markRectAsDirty(bounds()); } } - -KDSize PointerTextView::minimalSizeForOptimalDisplay() const { - return m_font->stringSize(text()); -} diff --git a/escher/src/text_view.cpp b/escher/src/text_view.cpp index 610816b33..b799a8fe0 100644 --- a/escher/src/text_view.cpp +++ b/escher/src/text_view.cpp @@ -33,6 +33,9 @@ void TextView::setFont(const KDFont * font) { } KDSize TextView::minimalSizeForOptimalDisplay() const { + if (text() == nullptr) { + return KDSize(0,0); + } return m_font->stringSize(text()); } From fbb1fbd1388a915912b188ae2a5a2a846b7e894e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 Jan 2019 10:01:17 +0100 Subject: [PATCH 223/373] [apps/code] Handle nullptr prompt text in input --- apps/code/console_controller.cpp | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/apps/code/console_controller.cpp b/apps/code/console_controller.cpp index 5ba4dc506..a316aab68 100644 --- a/apps/code/console_controller.cpp +++ b/apps/code/console_controller.cpp @@ -92,20 +92,23 @@ const char * ConsoleController::inputText(const char * prompt) { m_inputRunLoopActive = true; const char * promptText = prompt; - /* Set the prompt text. If the prompt text has a '\n', put the prompt text in - * the history until the last '\n', and put the remaining prompt text in the - * edit cell's prompt. */ - char * lastCarriageReturn = nullptr; char * s = const_cast(prompt); - while (*s != 0) { - if (*s == '\n') { - lastCarriageReturn = s; + + if (promptText != nullptr) { + /* Set the prompt text. If the prompt text has a '\n', put the prompt text in + * the history until the last '\n', and put the remaining prompt text in the + * edit cell's prompt. */ + char * lastCarriageReturn = nullptr; + while (*s != 0) { + if (*s == '\n') { + lastCarriageReturn = s; + } + s++; + } + if (lastCarriageReturn != nullptr) { + printText(prompt, lastCarriageReturn-prompt+1); + promptText = lastCarriageReturn+1; } - s++; - } - if (lastCarriageReturn != nullptr) { - printText(prompt, lastCarriageReturn-prompt+1); - promptText = lastCarriageReturn+1; } m_editCell.setPrompt(promptText); @@ -123,7 +126,9 @@ const char * ConsoleController::inputText(const char * prompt) { }, this); // Handle the input text - printText(promptText, s - promptText); + if (promptText != nullptr) { + printText(promptText, s - promptText); + } const char * text = m_editCell.text(); printText(text, strlen(text)); flushOutputAccumulationBufferToStore(); From 4ccf1f08a9bcb5227200ccdb8ba0028c109864ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 9 Jan 2019 10:25:38 +0100 Subject: [PATCH 224/373] [solver] Delta discriminant is counted as a solution to clear the code --- apps/solver/equation_store.cpp | 22 ++++++++-------------- apps/solver/solutions_controller.cpp | 7 ++----- 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/apps/solver/equation_store.cpp b/apps/solver/equation_store.cpp index a5f654e22..bc146c371 100644 --- a/apps/solver/equation_store.cpp +++ b/apps/solver/equation_store.cpp @@ -43,7 +43,7 @@ void EquationStore::tidy() { } Poincare::Layout EquationStore::exactSolutionLayoutAtIndex(int i, bool exactLayout) { - assert(m_type != Type::Monovariable && i >= 0 && (i < m_numberOfSolutions || (i == m_numberOfSolutions && m_type == Type::PolynomialMonovariable))); + assert(m_type != Type::Monovariable && i >= 0 && (i < m_numberOfSolutions)); if (exactLayout) { return m_exactSolutionExactLayouts[i]; } else { @@ -177,20 +177,14 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) { // Create the results' layouts int solutionIndex = 0; int initialNumberOfSolutions = m_numberOfSolutions <= k_maxNumberOfExactSolutions ? m_numberOfSolutions : -1; - int maxNumberSolutions = initialNumberOfSolutions + (initialNumberOfSolutions >= k_maxNumberOfExactSolutions - 1 ? 0 : 1); // We iterate through the solutions and the potential delta - for (int i = 0; i < maxNumberSolutions; i++) { + for (int i = 0; i < initialNumberOfSolutions; i++) { if (!exactSolutions[i].isUninitialized()) { assert(!exactSolutionsApproximations[i].isUninitialized()); if (exactSolutionsApproximations[i].type() == ExpressionNode::Type::Unreal) { // Discard unreal solutions. - if (i < initialNumberOfSolutions) { - // Discard the solution - m_numberOfSolutions--; - continue; - } - // Delta is not real - assert(i == initialNumberOfSolutions); + m_numberOfSolutions--; + continue; } m_exactSolutionExactLayouts[solutionIndex] = PoincareHelpers::CreateLayout(exactSolutions[i]); m_exactSolutionApproximateLayouts[solutionIndex] = PoincareHelpers::CreateLayout(exactSolutionsApproximations[i]); @@ -271,16 +265,16 @@ EquationStore::Error EquationStore::oneDimensialPolynomialSolve(Expression exact if (delta.isRationalZero()) { // if delta = 0, x0=x1= -b/(2a) exactSolutions[0] = Division(Opposite(coefficients[1]), Multiplication(Rational(2), coefficients[2])); - m_numberOfSolutions = 1; + m_numberOfSolutions = 2; } else { // x0 = (-b-sqrt(delta))/(2a) exactSolutions[0] = Division(Subtraction(Opposite(coefficients[1].clone()), SquareRoot::Builder(delta.clone())), Multiplication(Rational(2), coefficients[2].clone())); // x1 = (-b+sqrt(delta))/(2a) exactSolutions[1] = Division(Addition(Opposite(coefficients[1]), SquareRoot::Builder(delta.clone())), Multiplication(Rational(2), coefficients[2])); - m_numberOfSolutions = 2; + m_numberOfSolutions = 3; } - exactSolutions[m_numberOfSolutions] = delta; - for (int i = 0; i <= m_numberOfSolutions; i++) { + exactSolutions[m_numberOfSolutions-1] = delta; + for (int i = 0; i < m_numberOfSolutions; i++) { exactSolutions[i].simplifyAndApproximate(&exactSolutions[i], &exactSolutionsApproximations[i], *context, updatedComplexFormat(), Poincare::Preferences::sharedPreferences()->angleUnit()); } return Error::NoError; diff --git a/apps/solver/solutions_controller.cpp b/apps/solver/solutions_controller.cpp index a655efefd..fce4baae5 100644 --- a/apps/solver/solutions_controller.cpp +++ b/apps/solver/solutions_controller.cpp @@ -136,9 +136,6 @@ Responder * SolutionsController::defaultController() { /* TableViewDataSource */ int SolutionsController::numberOfRows() { - if (m_equationStore->type() == EquationStore::Type::PolynomialMonovariable) { - return m_equationStore->numberOfSolutions() + 1; // add the delta row - } return m_equationStore->numberOfSolutions(); } @@ -149,7 +146,7 @@ int SolutionsController::numberOfColumns() { void SolutionsController::willDisplayCellAtLocation(HighlightCell * cell, int i, int j) { if (i == 0) { // Name of the variable or discriminant - if (m_equationStore->type() == EquationStore::Type::PolynomialMonovariable && j == m_equationStore->numberOfSolutions()) { + if (m_equationStore->type() == EquationStore::Type::PolynomialMonovariable && j == m_equationStore->numberOfSolutions()-1) { // Discriminant EvenOddExpressionCell * deltaCell = static_cast(cell); deltaCell->setLayout(m_delta2Layout); @@ -265,7 +262,7 @@ int SolutionsController::reusableCellCount(int type) { int SolutionsController::typeAtLocation(int i, int j) { if (i == 0) { - if (m_equationStore->type() == EquationStore::Type::PolynomialMonovariable && j == m_equationStore->numberOfSolutions()) { + if (m_equationStore->type() == EquationStore::Type::PolynomialMonovariable && j == m_equationStore->numberOfSolutions()-1) { return 1; } return 0; From 8cf6006a5874a2f6b50b37c6ca3a01642f1ea568 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 9 Jan 2019 11:00:22 +0100 Subject: [PATCH 225/373] [solver] I18n: add messages "The polynomial has no real root" --- apps/solver/base.de.i18n | 2 ++ apps/solver/base.en.i18n | 2 ++ apps/solver/base.es.i18n | 2 ++ apps/solver/base.fr.i18n | 2 ++ apps/solver/base.pt.i18n | 2 ++ 5 files changed, 10 insertions(+) diff --git a/apps/solver/base.de.i18n b/apps/solver/base.de.i18n index 47c1475e4..b5977d8b6 100644 --- a/apps/solver/base.de.i18n +++ b/apps/solver/base.de.i18n @@ -21,3 +21,5 @@ ApproximateSolutionIntervalInstruction0= "Geben Sie das Intervall fuer die Suche ApproximateSolutionIntervalInstruction1= "nach einer ungefaehren Loesung ein" OnlyFirstSolutionsDisplayed0 = "Es werden nur die ersten" OnlyFirstSolutionsDisplayed1 = "zehn Loesungen angezeigt." +PolynomeHasNoRealSolution0 = "Das Polynom hat" +PolynomeHasNoRealSolution1 = "keine reelle Nullstelle" diff --git a/apps/solver/base.en.i18n b/apps/solver/base.en.i18n index 728584bab..ebbb853e6 100644 --- a/apps/solver/base.en.i18n +++ b/apps/solver/base.en.i18n @@ -21,3 +21,5 @@ ApproximateSolutionIntervalInstruction0= "Enter the interval to search" ApproximateSolutionIntervalInstruction1= "for an approximate solution" OnlyFirstSolutionsDisplayed0 = "Only the first 10 solutions" OnlyFirstSolutionsDisplayed1 = "are displayed" +PolynomeHasNoRealSolution0 = "The polynomial has no" +PolynomeHasNoRealSolution1 = "real root" diff --git a/apps/solver/base.es.i18n b/apps/solver/base.es.i18n index 017826ef7..7702ad8ec 100644 --- a/apps/solver/base.es.i18n +++ b/apps/solver/base.es.i18n @@ -21,3 +21,5 @@ ApproximateSolutionIntervalInstruction0= "Introduzca el intervalo para" ApproximateSolutionIntervalInstruction1= "buscar una solución aproximada" OnlyFirstSolutionsDisplayed0 = "Sólo se muestran las" OnlyFirstSolutionsDisplayed1 = "10 primeras soluciones" +PolynomeHasNoRealSolution0 = "El polinomio no tiene" +PolynomeHasNoRealSolution1 = "ninguna raíz real" diff --git a/apps/solver/base.fr.i18n b/apps/solver/base.fr.i18n index 29a5c3b6d..def88cd86 100644 --- a/apps/solver/base.fr.i18n +++ b/apps/solver/base.fr.i18n @@ -21,3 +21,5 @@ ApproximateSolutionIntervalInstruction0= "Entrez l'intervalle dans lequel" ApproximateSolutionIntervalInstruction1= "rechercher une solution approchée" OnlyFirstSolutionsDisplayed0 = "Seulement les 10 premières" OnlyFirstSolutionsDisplayed1 = "solutions sont affichées" +PolynomeHasNoRealSolution0 = "Le polynôme n'admet pas" +PolynomeHasNoRealSolution1 = "de racine réelle" diff --git a/apps/solver/base.pt.i18n b/apps/solver/base.pt.i18n index 147cf2025..29c643aff 100644 --- a/apps/solver/base.pt.i18n +++ b/apps/solver/base.pt.i18n @@ -21,3 +21,5 @@ ApproximateSolutionIntervalInstruction0= "Digite o intervalo para procurar" ApproximateSolutionIntervalInstruction1= "uma solução aproximada" OnlyFirstSolutionsDisplayed0 = "Somente as 10 primeiras" OnlyFirstSolutionsDisplayed1 = "soluções são exibidas" +PolynomeHasNoRealSolution0 = "O polinômio não tem" +PolynomeHasNoRealSolution1 = "nenhuma raiz real" From c3b335212c26565c674ea7649119acf74c9f8882 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 9 Jan 2019 11:01:32 +0100 Subject: [PATCH 226/373] [solver] Add a warning message when a polynomial has no real root --- apps/solver/solutions_controller.cpp | 23 ++++++++++++++++++----- apps/solver/solutions_controller.h | 3 ++- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/apps/solver/solutions_controller.cpp b/apps/solver/solutions_controller.cpp index fce4baae5..90e780373 100644 --- a/apps/solver/solutions_controller.cpp +++ b/apps/solver/solutions_controller.cpp @@ -16,8 +16,8 @@ using namespace Shared; namespace Solver { SolutionsController::ContentView::ContentView(SolutionsController * controller) : - m_warningMessageView0(KDFont::SmallFont, I18n::Message::OnlyFirstSolutionsDisplayed0, 0.5f, 0.5f, KDColorBlack, Palette::WallScreenDark), - m_warningMessageView1(KDFont::SmallFont, I18n::Message::OnlyFirstSolutionsDisplayed1, 0.5f, 0.5f, KDColorBlack, Palette::WallScreenDark), + m_warningMessageView0(KDFont::SmallFont, I18n::Message::Default, 0.5f, 0.5f, KDColorBlack, Palette::WallScreenDark), + m_warningMessageView1(KDFont::SmallFont, I18n::Message::Default, 0.5f, 0.5f, KDColorBlack, Palette::WallScreenDark), m_selectableTableView(controller), m_displayWarningMoreSolutions(false) { @@ -31,11 +31,15 @@ void SolutionsController::ContentView::drawRect(KDContext * ctx, KDRect rect) co } } -void SolutionsController::ContentView::setWarningMoreSolutions(bool warning) { +void SolutionsController::ContentView::setWarning(bool warning) { m_displayWarningMoreSolutions = warning; m_selectableTableView.setTopMargin(m_displayWarningMoreSolutions ? 0 : Metric::CommonTopMargin); layoutSubviews(); - markRectAsDirty(bounds()); +} + +void SolutionsController::ContentView::setWarningMessages(I18n::Message message0, I18n::Message message1) { + m_warningMessageView0.setMessage(message0); + m_warningMessageView1.setMessage(message1); } int SolutionsController::ContentView::numberOfSubviews() const { @@ -100,7 +104,16 @@ View * SolutionsController::view() { void SolutionsController::viewWillAppear() { ViewController::viewWillAppear(); App * solverApp = static_cast(app()); - m_contentView.setWarningMoreSolutions(m_equationStore->haveMoreApproximationSolutions(solverApp->localContext())); + bool requireWarning = false; + if (m_equationStore->type() == EquationStore::Type::Monovariable) { + m_contentView.setWarningMessages(I18n::Message::OnlyFirstSolutionsDisplayed0, I18n::Message::OnlyFirstSolutionsDisplayed1); + requireWarning = m_equationStore->haveMoreApproximationSolutions(solverApp->localContext()); + } else if (m_equationStore->type() == EquationStore::Type::PolynomialMonovariable && m_equationStore->numberOfSolutions() == 1) { + assert(Preferences::sharedPreferences()->complexFormat() == Preferences::ComplexFormat::Real); + m_contentView.setWarningMessages(I18n::Message::PolynomeHasNoRealSolution0, I18n::Message::PolynomeHasNoRealSolution1); + requireWarning = true; + } + m_contentView.setWarning(requireWarning); m_contentView.selectableTableView()->reloadData(); if (selectedRow() < 0) { selectCellAtLocation(0, 0); diff --git a/apps/solver/solutions_controller.h b/apps/solver/solutions_controller.h index a136bb675..6ad68bceb 100644 --- a/apps/solver/solutions_controller.h +++ b/apps/solver/solutions_controller.h @@ -38,7 +38,8 @@ private: public: ContentView(SolutionsController * controller); void drawRect(KDContext * ctx, KDRect rect) const override; - void setWarningMoreSolutions(bool warning); + void setWarning(bool warning); + void setWarningMessages(I18n::Message message0, I18n::Message message1); SelectableTableView * selectableTableView() { return &m_selectableTableView; } From a539b2f061ef07e2144c6e1107c7d26962bbffa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 9 Jan 2019 14:26:13 +0100 Subject: [PATCH 227/373] [poincare] Test: fix tests on Complex Format --- poincare/test/complex.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/poincare/test/complex.cpp b/poincare/test/complex.cpp index ee5254c1d..469fce7d9 100644 --- a/poincare/test/complex.cpp +++ b/poincare/test/complex.cpp @@ -12,9 +12,9 @@ QUIZ_CASE(poincare_complex_evaluate) { assert_parsed_expression_evaluates_to("R(-1)", "unreal", Radian, Real); assert_parsed_expression_evaluates_to("R(-1)*R(-1)", "unreal", Radian, Real); assert_parsed_expression_evaluates_to("ln(-2)", "unreal", Radian, Real); - assert_parsed_expression_evaluates_without_simplifying_to("(-8)^(1/3)", "-2", Radian, Real); - assert_parsed_expression_evaluates_without_simplifying_to("8^(1/3)", "2", Radian, Real); - assert_parsed_expression_evaluates_without_simplifying_to("(-8)^(2/3)", "4", Radian, Real); + assert_parsed_expression_evaluates_to("(-8)^(1/3)", "-2", Radian, Real); + assert_parsed_expression_evaluates_to("8^(1/3)", "2", Radian, Real); + assert_parsed_expression_evaluates_to("(-8)^(2/3)", "4", Radian, Real); assert_parsed_expression_evaluates_without_simplifying_to("root(-8,3)", "-2", Radian, Real); // Cartesian @@ -22,16 +22,16 @@ QUIZ_CASE(poincare_complex_evaluate) { assert_parsed_expression_evaluates_to("R(-1)", "I", Radian, Cartesian); assert_parsed_expression_evaluates_to("R(-1)*R(-1)", "-1", Radian, Cartesian); assert_parsed_expression_evaluates_to("ln(-2)", "6.9314718055995E-1+3.1415926535898*I", Radian, Cartesian); - assert_parsed_expression_evaluates_without_simplifying_to("(-8)^(1/3)", "1+1.7320508075689*I", Radian, Cartesian); - assert_parsed_expression_evaluates_without_simplifying_to("(-8)^(2/3)", "-2+3.464102*I", Radian, Cartesian); + assert_parsed_expression_evaluates_to("(-8)^(1/3)", "1+1.7320508075689*I", Radian, Cartesian); + assert_parsed_expression_evaluates_to("(-8)^(2/3)", "-2+3.464102*I", Radian, Cartesian); assert_parsed_expression_evaluates_without_simplifying_to("root(-8,3)", "1+1.7320508075689*I", Radian, Cartesian); // Polar assert_parsed_expression_evaluates_to("I", "X^(1.570796*I)", Radian, Polar); assert_parsed_expression_evaluates_to("R(-1)", "X^(1.5707963267949*I)", Radian, Polar); assert_parsed_expression_evaluates_to("R(-1)*R(-1)", "X^(3.1415926535898*I)", Radian, Polar); - assert_parsed_expression_evaluates_without_simplifying_to("(-8)^(1/3)", "2*X^(1.0471975511966*I)", Radian, Polar); - assert_parsed_expression_evaluates_without_simplifying_to("(-8)^(2/3)", "4*X^(2.094395*I)", Radian, Polar); + assert_parsed_expression_evaluates_to("(-8)^(1/3)", "2*X^(1.0471975511966*I)", Radian, Polar); + assert_parsed_expression_evaluates_to("(-8)^(2/3)", "4*X^(2.094395*I)", Radian, Polar); assert_parsed_expression_evaluates_without_simplifying_to("root(-8,3)", "2*X^(1.0471975511966*I)", Radian, Polar); } From b3a8441289113b2f570d837f16fc1d5469f4895d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 9 Jan 2019 14:27:00 +0100 Subject: [PATCH 228/373] [solver] Fix tests on EquationStore: delta discriminant is counted as a solution --- apps/solver/test/equation_store.cpp | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/apps/solver/test/equation_store.cpp b/apps/solver/test/equation_store.cpp index 2c3745d1a..fd2e3e9c5 100644 --- a/apps/solver/test/equation_store.cpp +++ b/apps/solver/test/equation_store.cpp @@ -39,8 +39,7 @@ void assert_equation_system_exact_solve_to(const char * equations[], EquationSto } else { quiz_assert(strcmp(equationStore.variableAtIndex(0), variables[0]) == 0); } - int n = type == EquationStore::Type::PolynomialMonovariable ? numberOfSolutions+1 : numberOfSolutions; // Check Delta for PolynomialMonovariable - for (int i = 0; i < n; i++) { + for (int i = 0; i < numberOfSolutions; i++) { equationStore.exactSolutionLayoutAtIndex(i, true).serializeForParsing(buffer, 200); translate_in_ASCII_chars(buffer); quiz_assert(strcmp(buffer, solutions[i]) == 0); @@ -106,27 +105,27 @@ QUIZ_CASE(equation_solve) { // 3x^2-4x+4=2 const char * equations8[] = {"3*x^2-4x+4=2", 0}; const char * solutions8[] = {"(2)/(3)-(R(2))/(3)*I","(2)/(3)+(R(2))/(3)*I", "-8"}; - assert_equation_system_exact_solve_to(equations8, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions8, 2); + assert_equation_system_exact_solve_to(equations8, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions8, 3); // 2*x^2-4*x+4=3 const char * equations9[] = {"2*x^2-4*x+4=3", 0}; const char * solutions9[] = {"(-R(2)+2)/(2)","(R(2)+2)/(2)", "8"}; - assert_equation_system_exact_solve_to(equations9, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions9, 2); + assert_equation_system_exact_solve_to(equations9, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions9, 3); // 2*x^2-4*x+2=0 const char * equations10[] = {"2*x^2-4*x+2=0", 0}; const char * solutions10[] = {"1", "0"}; - assert_equation_system_exact_solve_to(equations10, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions10, 1); + assert_equation_system_exact_solve_to(equations10, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions10, 2); // x^2+x+1=3*x^2+pi*x-R(5) const char * equations11[] = {"x^2+x+1=3*x^2+P*x-R(5)", 0}; const char * solutions11[] = {"(R(P$2#-2*P+8*R(5)+9)-P+1)/(4)", "(-R(P$2#-2*P+8*R(5)+9)-P+1)/(4)", "P$2#-2*P+8*R(5)+9"}; - assert_equation_system_exact_solve_to(equations11, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions11, 2); + assert_equation_system_exact_solve_to(equations11, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions11, 3); // TODO // x^3 - 4x^2 + 6x - 24 = 0 //const char * equations10[] = {"2*x^2-4*x+4=3", 0}; - //assert_equation_system_exact_solve_to(equations10, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, {"x", ""}, {"4", "I*R(6)", "-I*R(6)", "-11616"}, 3); + //assert_equation_system_exact_solve_to(equations10, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, {"x", ""}, {"4", "I*R(6)", "-I*R(6)", "-11616"}, 4); //x^3+x^2+1=0 // x^3-3x-2=0 @@ -184,12 +183,11 @@ QUIZ_CASE(equation_solve_complex_format) { // x^2+x+1=0 --> No solution in R const char * equations2[] = {"x^2+x+1=0", 0}; const char * delta2[] = {"-3"}; - assert_equation_system_exact_solve_to(equations2, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, delta2, 0); + assert_equation_system_exact_solve_to(equations2, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, delta2, 1); // x^2-R(-1)=0 --> Not defined in R const char * equations3[] = {"x^2-R(-1)=0", 0}; - const char * delta3[] = {"unreal"}; - assert_equation_system_exact_solve_to(equations3, EquationStore::Error::EquationUnreal, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, delta3, 0); + assert_equation_system_exact_solve_to(equations3, EquationStore::Error::EquationUnreal, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, nullptr, 0); // x+R(-1)*R(-1) = 0 --> Not defined in R const char * equations4[] = {"x+R(-1)*R(-1)=0", 0}; @@ -204,11 +202,11 @@ QUIZ_CASE(equation_solve_complex_format) { // x^2+x+1=0 const char * solutions2[] = {"-(1)/(2)-(R(3))/(2)*I","-(1)/(2)+(R(3))/(2)*I", "-3"}; - assert_equation_system_exact_solve_to(equations2, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions2, 2); + assert_equation_system_exact_solve_to(equations2, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions2, 3); // x^2-R(-1)=0 const char * solutions3[] = {"-(R(2))/(2)-(R(2))/(2)*I", "(R(2))/(2)+(R(2))/(2)*I","4*I"}; - assert_equation_system_exact_solve_to(equations3, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions3, 2); + assert_equation_system_exact_solve_to(equations3, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions3, 3); // x+R(-1)*R(-1) = 0 const char * solutions4[] = {"1"}; @@ -224,11 +222,11 @@ QUIZ_CASE(equation_solve_complex_format) { // x^2+x+1=0 const char * solutions2Polar[] = {"X$-(2*P)/(3)*I#","X$(2*P)/(3)*I#", "3*X$P*I#"}; - assert_equation_system_exact_solve_to(equations2, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions2Polar, 2); + assert_equation_system_exact_solve_to(equations2, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions2Polar, 3); // x^2-R(-1)=0 const char * solutions3Polar[] = {"X$-(3*P)/(4)*I#", "X$(P)/(4)*I#", "4*X$(P)/(2)*I#"}; - assert_equation_system_exact_solve_to(equations3, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions3Polar, 2); + assert_equation_system_exact_solve_to(equations3, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions3Polar, 3); } From b5c19d37da4f7fa1aa4d56e8340e55d515d73309 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 Jan 2019 17:09:17 +0100 Subject: [PATCH 229/373] [poincare] By default, the complex mode is "Real" --- poincare/src/preferences.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/preferences.cpp b/poincare/src/preferences.cpp index 467f0065c..207dea71d 100644 --- a/poincare/src/preferences.cpp +++ b/poincare/src/preferences.cpp @@ -7,7 +7,7 @@ Preferences::Preferences() : m_angleUnit(AngleUnit::Degree), m_displayMode(Preferences::PrintFloatMode::Decimal), m_editionMode(EditionMode::Edition2D), - m_complexFormat(Preferences::ComplexFormat::Cartesian), + m_complexFormat(Preferences::ComplexFormat::Real), m_numberOfSignificantDigits(PrintFloat::k_numberOfPrintedSignificantDigits) { } From 027148f37627b0cb18ee4665a5c5853477db71b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 Jan 2019 17:37:37 +0100 Subject: [PATCH 230/373] [apps/calculation] Clean comments --- apps/calculation/calculation.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/calculation/calculation.cpp b/apps/calculation/calculation.cpp index 97bdfff95..7520f00f4 100644 --- a/apps/calculation/calculation.cpp +++ b/apps/calculation/calculation.cpp @@ -151,12 +151,12 @@ bool Calculation::shouldOnlyDisplayApproximateOutput(Context * context) { } if (strcmp(m_exactOutputText, m_approximateOutputText) == 0) { /* If the exact and approximate results' texts are equal and their layouts - * too, do not display the exact result. If, because of the number of - * significant digits, the two layouts are not equal, we display both. */ + * too, do not display the exact result. If the two layouts are not equal + * because of the number of significant digits, we display both. */ return exactAndApproximateDisplayedOutputsAreEqual(context) == Calculation::EqualSign::Equal; } if (strcmp(m_exactOutputText, Undefined::Name()) == 0 || strcmp(m_approximateOutputText, Unreal::Name()) == 0 ) { - /* if the approximate result is 'unreal' or the exact result is 'undef'*/ + // If the approximate result is 'unreal' or the exact result is 'undef' return true; } return input().isApproximate(*context) || exactOutput().isApproximate(*context); From be3ab70e670d3e41a58681f176b7afe65d11cf27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 Jan 2019 17:47:04 +0100 Subject: [PATCH 231/373] [apps/calculation] Do not display approximation if it is unreal Fixes: sqrt(-1) in real complex format, then change complex format, it then displays unreal = undef --- apps/calculation/calculation.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/calculation/calculation.cpp b/apps/calculation/calculation.cpp index 7520f00f4..5476cb861 100644 --- a/apps/calculation/calculation.cpp +++ b/apps/calculation/calculation.cpp @@ -163,11 +163,12 @@ bool Calculation::shouldOnlyDisplayApproximateOutput(Context * context) { } bool Calculation::shouldOnlyDisplayExactOutput() { - /* If the approximateOutput is undef, we not not want to display it. + /* If the approximateOutput is undef or unreal, we not not want to display it. * This prevents: * x->f(x) from displaying x = undef * x+x from displaying 2x = undef */ - return strcmp(m_approximateOutputText, Undefined::Name()) == 0; + return strcmp(m_approximateOutputText, Undefined::Name()) == 0 + || strcmp(m_approximateOutputText, Unreal::Name()) == 0; } Calculation::EqualSign Calculation::exactAndApproximateDisplayedOutputsAreEqual(Poincare::Context * context) { From 35cc26b68acefb74c518f112535a311071954e64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 10 Jan 2019 11:12:44 +0100 Subject: [PATCH 232/373] [apps/variable_box_controller] Shift memoization after deleting item --- apps/variable_box_controller.cpp | 14 ++++++++++++-- apps/variable_box_controller.h | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/apps/variable_box_controller.cpp b/apps/variable_box_controller.cpp index a9d8ac9a3..3c2b6abb9 100644 --- a/apps/variable_box_controller.cpp +++ b/apps/variable_box_controller.cpp @@ -59,8 +59,7 @@ bool VariableBoxController::handleEvent(Ion::Events::Event event) { if (event == Ion::Events::Backspace && m_currentPage != Page::RootMenu && m_lockPageDelete != m_currentPage && !isDisplayingEmptyController()) { int rowIndex = selectedRow(); m_selectableTableView.deselectTable(); - Storage::Record record = recordAtIndex(rowIndex); - record.destroy(); + destroyRecordAtRowIndex(rowIndex); int newSelectedRow = rowIndex >= numberOfRows() ? numberOfRows()-1 : rowIndex; selectCellAtLocation(selectedColumn(), newSelectedRow); m_selectableTableView.reloadData(); @@ -265,3 +264,14 @@ void VariableBoxController::resetMemoization() { } m_firstMemoizedLayoutIndex = 0; } + +void VariableBoxController::destroyRecordAtRowIndex(int rowIndex) { + // Destroy the record + recordAtIndex(rowIndex).destroy(); + // Shift the memoization + assert(rowIndex >= m_firstMemoizedLayoutIndex && rowIndex < m_firstMemoizedLayoutIndex + k_maxNumberOfDisplayedRows); + for (int i = rowIndex - m_firstMemoizedLayoutIndex; i < k_maxNumberOfDisplayedRows - 1; i++) { + m_layouts[i] = m_layouts[i+1]; + } + m_layouts[k_maxNumberOfDisplayedRows - 1] = Layout(); +} diff --git a/apps/variable_box_controller.h b/apps/variable_box_controller.h index 80fa9ede8..f4e986a97 100644 --- a/apps/variable_box_controller.h +++ b/apps/variable_box_controller.h @@ -51,6 +51,7 @@ private: bool displayEmptyController(); bool isDisplayingEmptyController() { return StackViewController::depth() == 2; } void resetMemoization(); + void destroyRecordAtRowIndex(int rowIndex); Page m_currentPage; Page m_lockPageDelete; ExpressionTableCellWithExpression m_leafCells[k_maxNumberOfDisplayedRows]; From 54b8d07ee33d88f8edabd78b65f6fb58ead79677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 10 Jan 2019 11:29:06 +0100 Subject: [PATCH 233/373] [apps/variable_box_controller] Fix layout memoization --- apps/variable_box_controller.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/variable_box_controller.cpp b/apps/variable_box_controller.cpp index 3c2b6abb9..adc6f61bd 100644 --- a/apps/variable_box_controller.cpp +++ b/apps/variable_box_controller.cpp @@ -220,16 +220,18 @@ I18n::Message VariableBoxController::nodeLabelAtIndex(int index) { Layout VariableBoxController::expressionLayoutForRecord(Storage::Record record, int index) { assert(m_currentPage != Page::RootMenu); + assert(index >= 0); if (index >= m_firstMemoizedLayoutIndex+k_maxNumberOfDisplayedRows || index < m_firstMemoizedLayoutIndex) { // Change range of layout memoization int deltaIndex = index >= m_firstMemoizedLayoutIndex + k_maxNumberOfDisplayedRows ? index - k_maxNumberOfDisplayedRows + 1 - m_firstMemoizedLayoutIndex : index - m_firstMemoizedLayoutIndex; - for (int i = 0; i < k_maxNumberOfDisplayedRows-1; i++) { + for (int i = 0; i < k_maxNumberOfDisplayedRows; i++) { int j = deltaIndex + i; - m_layouts[i] = j >= 0 && j < k_maxNumberOfDisplayedRows ? m_layouts[j] : Layout(); + m_layouts[i] = (j >= m_firstMemoizedLayoutIndex && j < k_maxNumberOfDisplayedRows) ? m_layouts[j] : Layout(); } m_firstMemoizedLayoutIndex += deltaIndex; + assert(m_firstMemoizedLayoutIndex >= 0); } - assert(index-m_firstMemoizedLayoutIndex < k_maxNumberOfDisplayedRows); + assert(index >= m_firstMemoizedLayoutIndex && index < m_firstMemoizedLayoutIndex + k_maxNumberOfDisplayedRows); if (m_layouts[index-m_firstMemoizedLayoutIndex].isUninitialized()) { m_layouts[index-m_firstMemoizedLayoutIndex] = GlobalContext::ExpressionFromRecord(record).createLayout(Poincare::Preferences::sharedPreferences()->displayMode(), Constant::ShortNumberOfSignificantDigits); } @@ -249,7 +251,7 @@ Storage::Record VariableBoxController::recordAtIndex(int rowIndex) { bool VariableBoxController::displayEmptyController() { assert(!isDisplayingEmptyController()); - /* If the content is empty, we push above an empty controller. */ + // If the content is empty, we push above an empty controller. if (numberOfRows() == 0) { m_emptyViewController.setType((VariableBoxEmptyController::Type)m_currentPage); push(&m_emptyViewController); From 6cc255c07e3f8183ed82023bf4257a7fbb6044d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 11 Jan 2019 10:04:47 +0100 Subject: [PATCH 234/373] build: Version 10.0.0 --- build/config.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/config.mak b/build/config.mak index 4181b8944..9aed19263 100644 --- a/build/config.mak +++ b/build/config.mak @@ -3,7 +3,7 @@ PLATFORM ?= device DEBUG ?= 0 -EPSILON_VERSION ?= 1.9.0 +EPSILON_VERSION ?= 10.0.0 EPSILON_ONBOARDING_APP ?= 1 # Valid values are "none", "update", "beta" EPSILON_BOOT_PROMPT ?= none From a28f67b3f89dfc7800d9a25813287222c8b0ff4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 15 Jan 2019 10:04:34 +0100 Subject: [PATCH 235/373] [poincare/sign_function] Do not use signbit Caused some Travis problems --- poincare/src/sign_function.cpp | 45 ++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/poincare/src/sign_function.cpp b/poincare/src/sign_function.cpp index 493e68248..c706070b4 100644 --- a/poincare/src/sign_function.cpp +++ b/poincare/src/sign_function.cpp @@ -38,10 +38,13 @@ Expression SignFunctionNode::shallowReduce(Context & context, Preferences::Compl template Complex SignFunctionNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { - if (c.imag() != 0) { + if (c.imag() != 0 || std::isnan(c.real())) { return Complex::Undefined(); } - if (signbit(c.real())) { + if (c.real() == 0) { + return Complex(0.0); + } + if (c.real() < 0) { return Complex(-1.0); } return Complex(1.0); @@ -59,39 +62,39 @@ Expression SignFunction::shallowReduce(Context & context, Preferences::ComplexFo return SimplificationHelper::Map(*this, context, angleUnit); } #endif - Rational one(1); + Rational resultSign(1); Expression child = childAtIndex(0); ExpressionNode::Sign s = child.sign(&context); - if (s != ExpressionNode::Sign::Unknown) { - if (s == ExpressionNode::Sign::Negative) { - one = Rational(-1); - } + if (s == ExpressionNode::Sign::Negative) { + resultSign = Rational(-1); } else { Evaluation childApproximated = child.node()->approximate(1.0f, context, complexFormat, angleUnit); assert(childApproximated.type() == EvaluationNode::Type::Complex); Complex c = static_cast&>(childApproximated); - // c has no sign (c is complex or NAN) if (std::isnan(c.imag()) || std::isnan(c.real()) || c.imag() != 0) { - // sign(-x) = -sign(x) - Expression oppChild = child.makePositiveAnyNegativeNumeralFactor(context, complexFormat, angleUnit, target); - if (oppChild.isUninitialized()) { - return *this; + // c's approximation has no sign (c is complex or NAN) + if (target == ExpressionNode::ReductionTarget::User && s == ExpressionNode::Sign::Positive) { + // For the user, we want sign(abs(x)) = 1 } else { + // sign(-x) = -sign(x) + Expression oppChild = child.makePositiveAnyNegativeNumeralFactor(context, complexFormat, angleUnit, target); + if (oppChild.isUninitialized()) { + return *this; + } Expression sign = *this; Multiplication m(Rational(-1)); replaceWithInPlace(m); - m.addChildAtIndexInPlace(sign, 1, 1); - // sign does not need to be shallowReduce because -x = NAN --> x = NAN - return m; - // m does not need to be shallowReduce, -1*sign cannot be reduce + m.addChildAtIndexInPlace(sign, 1, 1); // sign does not need to be shallowReduced because -x = NAN --> x = NAN + return m; // m does not need to be shallowReduced, -1*sign cannot be reduced } - } - if (c.real() < 0) { - one = Rational(-1); + } else if (c.real() < 0) { + resultSign = Rational(-1); + } else if (c.real() == 0) { + resultSign = Rational(0); } } - replaceWithInPlace(one); - return one; + replaceWithInPlace(resultSign); + return resultSign; } } From 614cfe83064a1158107685c045d0e8960c5e7ca5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 15 Jan 2019 16:41:19 +0100 Subject: [PATCH 236/373] [poincare] Add tests on SignFunction --- poincare/test/function.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/poincare/test/function.cpp b/poincare/test/function.cpp index 32c272f4f..257803e50 100644 --- a/poincare/test/function.cpp +++ b/poincare/test/function.cpp @@ -193,8 +193,13 @@ QUIZ_CASE(poincare_function_evaluate) { assert_parsed_expression_evaluates_to("R(3+I)", "1.7553173018244+2.8484878459314E-1*I"); assert_parsed_expression_evaluates_to("sign(-23+1)", "-1"); + assert_parsed_expression_evaluates_to("sign(inf)", "1"); + assert_parsed_expression_evaluates_to("sign(-inf)", "-1"); + assert_parsed_expression_evaluates_to("sign(0)", "0"); + assert_parsed_expression_evaluates_to("sign(-0)", "0"); assert_parsed_expression_evaluates_to("sign(x)", "undef"); assert_parsed_expression_evaluates_to("sign(2+I)", "undef"); + assert_parsed_expression_evaluates_to("sign(undef)", "undef"); assert_parsed_expression_evaluates_to("sum(2+n*I,n,1,5)", "10+15*I"); assert_parsed_expression_evaluates_to("sum(2+n*I,n,1,5)", "10+15*I"); @@ -274,6 +279,10 @@ QUIZ_CASE(poincare_function_simplify) { assert_parsed_expression_simplify_to("round(12.9,-2)", "0"); assert_parsed_expression_simplify_to("sign(-23)", "-1"); assert_parsed_expression_simplify_to("sign(-I)", "sign(-I)"); + assert_parsed_expression_simplify_to("sign(0)", "sign(0)"); + assert_parsed_expression_simplify_to("sign(inf)", "1)"); + assert_parsed_expression_simplify_to("sign(-inf)", "-1)"); + assert_parsed_expression_simplify_to("sign(undef)", "undef"); assert_parsed_expression_simplify_to("sign(23)", "1"); assert_parsed_expression_simplify_to("sign(log(18))", "1"); assert_parsed_expression_simplify_to("sign(-R(2))", "-1"); From 0bf3e678d93bd1565087b78ddf1ce9607ca1c7d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 16 Jan 2019 15:30:13 +0100 Subject: [PATCH 237/373] [poincare] Add tests and asserts about sign, such as sign(0)==0 --- poincare/include/poincare/number.h | 5 ++++- poincare/src/absolute_value.cpp | 1 + poincare/src/decimal.cpp | 2 ++ poincare/src/expression.cpp | 1 + poincare/src/float.cpp | 2 +- poincare/src/infinity.cpp | 2 ++ poincare/src/multiplication.cpp | 1 + poincare/src/number.cpp | 1 + poincare/src/opposite.cpp | 5 +++-- poincare/src/power.cpp | 2 ++ poincare/src/random.cpp | 1 + poincare/src/rational.cpp | 3 ++- poincare/src/sign_function.cpp | 1 + poincare/src/undefined.cpp | 1 + poincare/test/decimal.cpp | 1 + poincare/test/function.cpp | 8 ++++---- poincare/test/properties.cpp | 2 ++ poincare/test/rational.cpp | 1 + 18 files changed, 31 insertions(+), 9 deletions(-) diff --git a/poincare/include/poincare/number.h b/poincare/include/poincare/number.h index 0047c6c22..aee56a55c 100644 --- a/poincare/include/poincare/number.h +++ b/poincare/include/poincare/number.h @@ -49,7 +49,10 @@ public: /* Number::sign() or Number::setSign does not need a context or an angle unit * (a number can be Infinity, Undefined, Float, Decimal, Rational). */ ExpressionNode::Sign sign() { return Expression::sign(nullptr); } - Number setSign(ExpressionNode::Sign s) { return Expression::setSign(s, nullptr, Preferences::ComplexFormat::Real, Preferences::AngleUnit::Degree, ExpressionNode::ReductionTarget::User).convert(); } + Number setSign(ExpressionNode::Sign s) { + assert(s == ExpressionNode::Sign::Positive || s == ExpressionNode::Sign::Negative); + return Expression::setSign(s, nullptr, Preferences::ComplexFormat::Real, Preferences::AngleUnit::Degree, ExpressionNode::ReductionTarget::User).convert(); + } protected: Number() : Expression() {} NumberNode * node() const { return static_cast(Expression::node()); } diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 6ad13fa66..4e007e4bd 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -15,6 +15,7 @@ constexpr Expression::FunctionHelper AbsoluteValue::s_functionHelper; int AbsoluteValueNode::numberOfChildren() const { return AbsoluteValue::s_functionHelper.numberOfChildren(); } Expression AbsoluteValueNode::setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + assert(s == ExpressionNode::Sign::Positive); return AbsoluteValue(this).setSign(s, context, complexFormat, angleUnit); } diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index 56e3f208f..bbcca8d56 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -57,6 +57,7 @@ size_t DecimalNode::size() const { } Expression DecimalNode::setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + assert(s == ExpressionNode::Sign::Positive || s == ExpressionNode::Sign::Negative); return Decimal(this).setSign(s); } @@ -340,6 +341,7 @@ Decimal::Decimal(size_t size, const Integer & m, int e) : Number(TreePool::share } Expression Decimal::setSign(ExpressionNode::Sign s) { + assert(s == ExpressionNode::Sign::Positive || s == ExpressionNode::Sign::Negative); Decimal result = *this; result.node()->setNegative(s == ExpressionNode::Sign::Negative); return result; diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 8e1808823..f9608abc9 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -558,6 +558,7 @@ Expression Expression::deepBeautify(Context & context, Preferences::ComplexForma } Expression Expression::setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + assert(s == ExpressionNode::Sign::Positive || s == ExpressionNode::Sign::Negative); return node()->setSign(s, context, complexFormat, angleUnit, target); } diff --git a/poincare/src/float.cpp b/poincare/src/float.cpp index 95720f70d..b18b88ec4 100644 --- a/poincare/src/float.cpp +++ b/poincare/src/float.cpp @@ -5,7 +5,7 @@ namespace Poincare { template Expression FloatNode::setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { - assert(s != Sign::Unknown); + assert(s == ExpressionNode::Sign::Positive || s == ExpressionNode::Sign::Negative); Sign currentSign = m_value < 0 ? Sign::Negative : Sign::Positive; Expression thisExpr = Number(this); Expression result = Float(s == currentSign ? m_value : -m_value); diff --git a/poincare/src/infinity.cpp b/poincare/src/infinity.cpp index 23bb83526..a862b81db 100644 --- a/poincare/src/infinity.cpp +++ b/poincare/src/infinity.cpp @@ -10,6 +10,7 @@ extern "C" { namespace Poincare { Expression InfinityNode::setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + assert(s == ExpressionNode::Sign::Positive || s == ExpressionNode::Sign::Negative); return Infinity(this).setSign(s, context, complexFormat, angleUnit); } @@ -31,6 +32,7 @@ template Evaluation InfinityNode::templatedApproximate() const { } Expression Infinity::setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { + assert(s == ExpressionNode::Sign::Positive || s == ExpressionNode::Sign::Negative); Expression result = Infinity(s == ExpressionNode::Sign::Negative); replaceWithInPlace(result); return result; diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 132f7b888..5a2722981 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -67,6 +67,7 @@ MatrixComplex MultiplicationNode::computeOnMatrices(const MatrixComplex m, } Expression MultiplicationNode::setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + assert(s == ExpressionNode::Sign::Positive); return Multiplication(this).setSign(s, context, complexFormat, angleUnit, target); } diff --git a/poincare/src/number.cpp b/poincare/src/number.cpp index bfc42b518..d228d9d15 100644 --- a/poincare/src/number.cpp +++ b/poincare/src/number.cpp @@ -20,6 +20,7 @@ double NumberNode::doubleApproximation() const { case Type::Unreal: return NAN; case Type::Infinity: + assert(Number(this).sign() == Sign::Negative || Number(this).sign() == Sign::Positive); return Number(this).sign() == Sign::Negative ? -INFINITY : INFINITY; case Type::Float: if (size() == sizeof(FloatNode)) { diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index 5b67ade67..927f832c6 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -20,10 +20,11 @@ int OppositeNode::polynomialDegree(Context & context, const char * symbolName) c } ExpressionNode::Sign OppositeNode::sign(Context * context) const { - if (childAtIndex(0)->sign(context) == Sign::Positive) { + Sign child0Sign = childAtIndex(0)->sign(context); + if (child0Sign == Sign::Positive) { return Sign::Negative; } - if (childAtIndex(0)->sign(context) == Sign::Negative) { + if (child0Sign == Sign::Negative) { return Sign::Positive; } return ExpressionNode::sign(context); diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index b88399fe2..fef242492 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -49,6 +49,7 @@ ExpressionNode::Sign PowerNode::sign(Context * context) const { } Expression PowerNode::setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + assert(s == ExpressionNode::Sign::Positive); return Power(this).setSign(s, context, complexFormat, angleUnit, target); } @@ -430,6 +431,7 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co result = complexBase.powerInteger(r.unsignedIntegerNumerator().extractedInt(), context, complexFormat, angleUnit, target); } else { // (x+iy)^(-n), n integer positive n < 10 + assert(r.sign() == ExpressionNode::Sign::Negative); result = complexBase.powerInteger(r.unsignedIntegerNumerator().extractedInt(), context, complexFormat, angleUnit, target).inverse(context, complexFormat, angleUnit, target); } } diff --git a/poincare/src/random.cpp b/poincare/src/random.cpp index 737082864..e31bde088 100644 --- a/poincare/src/random.cpp +++ b/poincare/src/random.cpp @@ -13,6 +13,7 @@ constexpr Expression::FunctionHelper Random::s_functionHelper; int RandomNode::numberOfChildren() const { return Random::s_functionHelper.numberOfChildren(); } Expression RandomNode::setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + assert(s == ExpressionNode::Sign::Positive); return Random(this).setSign(s, context, complexFormat, angleUnit); } diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index 3e4ff391d..705c5b010 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -99,6 +99,7 @@ int RationalNode::serialize(char * buffer, int bufferSize, Preferences::PrintFlo // Expression subclassing Expression RationalNode::setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + assert(s == ExpressionNode::Sign::Positive || s == ExpressionNode::Sign::Negative); return Rational(this).setSign(s); } @@ -285,7 +286,7 @@ Expression Rational::denominator(Context & context, Preferences::ComplexFormat c } Expression Rational::setSign(ExpressionNode::Sign s) { - assert(s != ExpressionNode::Sign::Unknown); + assert(s == ExpressionNode::Sign::Positive || s == ExpressionNode::Sign::Negative); node()->setNegative(s == ExpressionNode::Sign::Negative); return *this; } diff --git a/poincare/src/sign_function.cpp b/poincare/src/sign_function.cpp index c706070b4..74cd540b3 100644 --- a/poincare/src/sign_function.cpp +++ b/poincare/src/sign_function.cpp @@ -18,6 +18,7 @@ ExpressionNode::Sign SignFunctionNode::sign(Context * context) const { } Expression SignFunctionNode::setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { + assert(s == ExpressionNode::Sign::Positive || s == ExpressionNode::Sign::Negative); SignFunction sign(this); Rational r(s == ExpressionNode::Sign::Positive ? 1 : -1); sign.replaceWithInPlace(r); diff --git a/poincare/src/undefined.cpp b/poincare/src/undefined.cpp index 4c821ffa6..7031aec61 100644 --- a/poincare/src/undefined.cpp +++ b/poincare/src/undefined.cpp @@ -14,6 +14,7 @@ int UndefinedNode::polynomialDegree(Context & context, const char * symbolName) } Expression UndefinedNode::setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + assert(s == ExpressionNode::Sign::Positive || s == ExpressionNode::Sign::Negative); return Undefined(this); } diff --git a/poincare/test/decimal.cpp b/poincare/test/decimal.cpp index 7945a0dd9..50a4c1e48 100644 --- a/poincare/test/decimal.cpp +++ b/poincare/test/decimal.cpp @@ -40,6 +40,7 @@ QUIZ_CASE(poincare_decimal_properties) { quiz_assert(Decimal(-2, -3).sign() == ExpressionNode::Sign::Negative); quiz_assert(Decimal(2, -3).sign() == ExpressionNode::Sign::Positive); quiz_assert(Decimal(2, 3).sign() == ExpressionNode::Sign::Positive); + quiz_assert(Decimal(0, 1).sign() == ExpressionNode::Sign::Positive); } // Simplify diff --git a/poincare/test/function.cpp b/poincare/test/function.cpp index 257803e50..73b95289d 100644 --- a/poincare/test/function.cpp +++ b/poincare/test/function.cpp @@ -279,10 +279,10 @@ QUIZ_CASE(poincare_function_simplify) { assert_parsed_expression_simplify_to("round(12.9,-2)", "0"); assert_parsed_expression_simplify_to("sign(-23)", "-1"); assert_parsed_expression_simplify_to("sign(-I)", "sign(-I)"); - assert_parsed_expression_simplify_to("sign(0)", "sign(0)"); - assert_parsed_expression_simplify_to("sign(inf)", "1)"); - assert_parsed_expression_simplify_to("sign(-inf)", "-1)"); - assert_parsed_expression_simplify_to("sign(undef)", "undef"); + assert_parsed_expression_simplify_to("sign(0)", "0"); + assert_parsed_expression_simplify_to("sign(inf)", "1"); + assert_parsed_expression_simplify_to("sign(-inf)", "-1"); + assert_parsed_expression_simplify_to("sign(undef)", "sign(undef)"); assert_parsed_expression_simplify_to("sign(23)", "1"); assert_parsed_expression_simplify_to("sign(log(18))", "1"); assert_parsed_expression_simplify_to("sign(-R(2))", "-1"); diff --git a/poincare/test/properties.cpp b/poincare/test/properties.cpp index 01f7c7e30..843d2369a 100644 --- a/poincare/test/properties.cpp +++ b/poincare/test/properties.cpp @@ -34,6 +34,8 @@ QUIZ_CASE(poincare_sign) { assert_parsed_expression_sign("-23/32", Negative); assert_parsed_expression_sign("P", Positive); assert_parsed_expression_sign("X", Positive); + assert_parsed_expression_sign("0", Positive); + assert_parsed_expression_sign("cos(90)", Positive); assert_parsed_expression_sign("R(-1)", Unknown); assert_parsed_expression_sign("R(-1)", Unknown, Real); } diff --git a/poincare/test/rational.cpp b/poincare/test/rational.cpp index b8d740a36..4b090db03 100644 --- a/poincare/test/rational.cpp +++ b/poincare/test/rational.cpp @@ -47,6 +47,7 @@ QUIZ_CASE(poincare_rational_properties) { quiz_assert(Rational(-2).sign() == ExpressionNode::Sign::Negative); quiz_assert(Rational(-2, 3).sign() == ExpressionNode::Sign::Negative); quiz_assert(Rational(2, 3).sign() == ExpressionNode::Sign::Positive); + quiz_assert(Rational(0, 3).sign() == ExpressionNode::Sign::Positive); quiz_assert(Rational(0).isZero()); quiz_assert(!Rational(231).isZero()); quiz_assert(Rational(1).isOne()); From 86f03b800dae0f3b7f310933809c51986cf15c51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 16 Jan 2019 14:17:40 +0100 Subject: [PATCH 238/373] [poincare] Clean the TrigonometryCheatTable It caused Travis compilation problems --- poincare/Makefile | 1 + poincare/include/poincare/expression.h | 1 + poincare/include/poincare/trigonometry.h | 1 - .../poincare/trigonometry_cheat_table.h | 83 ++++++ poincare/src/trigonometry.cpp | 164 +---------- poincare/src/trigonometry_cheat_table.cpp | 272 ++++++++++++++++++ 6 files changed, 369 insertions(+), 153 deletions(-) create mode 100644 poincare/include/poincare/trigonometry_cheat_table.h create mode 100644 poincare/src/trigonometry_cheat_table.cpp diff --git a/poincare/Makefile b/poincare/Makefile index 59e1826f0..2d562b546 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -127,6 +127,7 @@ objs += $(addprefix poincare/src/,\ tree_node.o\ tree_pool.o\ trigonometry.o\ + trigonometry_cheat_table.o\ undefined.o\ unreal.o\ variable_context.o\ diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 4abcf337f..19ca39a68 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -82,6 +82,7 @@ class Expression : public TreeHandle { friend class SymbolAbstractNode; friend class Tangent; friend class Trigonometry; + friend class TrigonometryCheatTable; friend class AdditionNode; friend class DerivativeNode; diff --git a/poincare/include/poincare/trigonometry.h b/poincare/include/poincare/trigonometry.h index 5e46c82a7..794a65b37 100644 --- a/poincare/include/poincare/trigonometry.h +++ b/poincare/include/poincare/trigonometry.h @@ -19,7 +19,6 @@ public: static bool ExpressionIsEquivalentToTangent(const Expression & e); static Expression shallowReduceDirectFunction(Expression & e, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); static Expression shallowReduceInverseFunction(Expression & e, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - constexpr static int k_numberOfEntries = 37; static Expression table(const Expression e, ExpressionNode::Type type, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); // , Function f, bool inverse template static std::complex ConvertToRadian(const std::complex c, Preferences::AngleUnit angleUnit); template static std::complex ConvertRadianToAngleUnit(const std::complex c, Preferences::AngleUnit angleUnit); diff --git a/poincare/include/poincare/trigonometry_cheat_table.h b/poincare/include/poincare/trigonometry_cheat_table.h new file mode 100644 index 000000000..eb81172d5 --- /dev/null +++ b/poincare/include/poincare/trigonometry_cheat_table.h @@ -0,0 +1,83 @@ +#ifndef POINCARE_TRIGONOMETRY_CHEAT_TABLE_H +#define POINCARE_TRIGONOMETRY_CHEAT_TABLE_H + +#include +#include + +namespace Poincare { + + /* We use the cheat table to look for known simplifications (e.g. cos(0)=1, + * cos(Pi/2)=1...). For each entry of the table, we store its expression and + * its float approximation in order to quickly scan the table looking for our + * input approximation. If one entry matches the float approximation, we then + * check that the actual expression of our input is equivalent to the table + * expression. + * + * Example: ArcSine(1/2) + * -> Approximate 1/2: 0.5 + * -> Look up the row for 0.5 in the "Sine" column + * -> Return the "Angle" value of this row */ + +class TrigonometryCheatTable { +public: + constexpr static int k_numberOfEntries = 37; + enum class Type { + AngleInDegrees = 0, + AngleInRadians = 1, + Cosine = 2, + Sine = 3, + Tangent = 4 + }; + static const TrigonometryCheatTable * Table(); + Expression simplify(const Expression e, ExpressionNode::Type type, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) const; + +private: + + // ROW CLASS + class Row { + public: + + // PAIR + class Pair { + public: + constexpr Pair(const char * expression, float value = NAN) : + m_expression(expression), m_value(value) {} + Expression reducedExpression(bool assertNotUninitialized, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) const; + float value() const { return m_value; } + private: + const char * m_expression; + float m_value; + }; + // END OF PAIR CLASS + + constexpr Row(Pair angleInRadians, Pair angleInDegrees, Pair sine, Pair cosine, Pair tangent) : + m_pairs{angleInRadians, angleInDegrees, sine, cosine, tangent} {} + float floatForType(Type t) const { + assert(((int) t) >= 0 && ((int) t) < k_numberOfPairs); + return m_pairs[(int)t].value(); + } + Expression expressionForType(Type t, bool assertNotUninitialized, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) const { + assert(((int) t) >= 0 && ((int) t) < k_numberOfPairs); + return m_pairs[(int)t].reducedExpression(assertNotUninitialized, context, complexFormat, angleUnit, target); + } + private: + constexpr static int k_numberOfPairs = 5; + const Pair m_pairs[k_numberOfPairs]; + }; + // END OF ROW CLASS + + constexpr TrigonometryCheatTable(const Row * rows) : m_rows(rows) {} + float floatForTypeAtIndex(Type t, int i) const { + assert(i >= 0 && i < k_numberOfEntries); + return m_rows[i].floatForType(t); + } + Expression expressionForTypeAtIndex(Type t, int i, bool assertNotUninitialized, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) const { + assert(i >= 0 && i < k_numberOfEntries); + return m_rows[i].expressionForType(t, assertNotUninitialized, context, complexFormat, angleUnit, target); + } + const Row * m_rows; +}; + +} + +#endif diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 786f79872..832ca5f4a 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -1,17 +1,18 @@ #include +#include #include -#include -#include -#include -#include +#include +#include +#include #include +#include +#include +#include #include #include -#include -#include -#include -#include -#include +#include +#include +#include #include #include #include @@ -87,7 +88,7 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& co assert(isDirectTrigonometryFunction(e)); // Step 1. Try finding an easy standard calculation reduction - Expression lookup = Trigonometry::table(e.childAtIndex(0), e.type(), context, complexFormat, angleUnit, target); + Expression lookup = TrigonometryCheatTable::Table()->simplify(e.childAtIndex(0), e.type(), context, complexFormat, angleUnit, target); if (!lookup.isUninitialized()) { e.replaceWithInPlace(lookup); return lookup; @@ -290,7 +291,7 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& c } // Step 4. Try finding an easy standard calculation reduction - Expression lookup = Trigonometry::table(e.childAtIndex(0), e.type(), context, complexFormat, angleUnit, target); + Expression lookup = TrigonometryCheatTable::Table()->simplify(e.childAtIndex(0), e.type(), context, complexFormat, angleUnit, target); if (!lookup.isUninitialized()) { e.replaceWithInPlace(lookup); return lookup; @@ -334,147 +335,6 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& c return e; } -/* We use the cheat table to look for known simplifications (e.g. - * cos(0)=1, cos(Pi/2)=1...). For each entry of the table, we store its - * expression and its float approximation in order to quickly scan the table - * looking for our input approximation. If one entry matches, we then check that - * the actual expression of our input is equivalent to the table expression. - */ - -static_assert('\x8A' == Ion::Charset::SmallPi, "Unicode error"); - -struct Pair { - constexpr Pair(const char * e, float v = NAN) : expression(e), value(v) {} - const char * expression; - float value; -}; -constexpr Pair cheatTable[Trigonometry::k_numberOfEntries][5] = -// Angle in Radian | Angle in Degree | Cosine | Sine | Tangent -{{Pair("-90", -90.0f), Pair("\x8A*(-2)^(-1)", -1.5707963267948966f), "", - Pair("-1",-1.0f), "undef"}, - {Pair("-75",-75.0), Pair("\x8A*(-5)*12^(-1)",-1.3089969389957472f), "", - Pair("(-1)*6^(1/2)*4^(-1)-2^(1/2)*4^(-1)",-0.9659258262890683f), Pair("-(3^(1/2)+2)",-3.7320508075688776f)}, - {Pair("-72",-72.0), Pair("\x8A*2*(-5)^(-1)",-1.2566370614359172f), "", - Pair("-(5/8+5^(1/2)/8)^(1/2)",-0.9510565162951535f), Pair("-(5+2*5^(1/2))^(1/2)",-3.077683537175253f)}, - {Pair("-135/2",67.5f), Pair("\x8A*(-3)*8^(-1)",-1.1780972450961724f), "", - Pair("-(2+2^(1/2))^(1/2)*2^(-1)",-0.9238795325112867f), Pair("-1-2^(1/2)",-2.4142135623730945f)}, - {Pair("-60",-60.0f), Pair("\x8A*(-3)^(-1)",-1.0471975511965976f), "", - Pair("-3^(1/2)*2^(-1)",-0.8660254037844386f), Pair("-3^(1/2)",-1.7320508075688767f)}, - {Pair("-54",-54.0f), Pair("\x8A*(-3)*10^(-1)",-0.9424777960769379), "", - Pair("4^(-1)*(-1-5^(1/2))",-0.8090169943749473f), Pair("-(1+2*5^(-1/2))^(1/2)",-1.3763819204711731f)}, - {Pair("-45",-45.0f), Pair("\x8A*(-4)^(-1)",-0.7853981633974483f), "", - Pair("(-1)*(2^(-1/2))",-0.7071067811865475f), Pair("-1",-1.0f)}, - {Pair("-36",-36.0f), Pair("\x8A*(-5)^(-1)",-0.6283185307179586f), "", - Pair("-(5/8-5^(1/2)/8)^(1/2)",-0.5877852522924731f), Pair("-(5-2*5^(1/2))^(1/2)",-0.7265425280053609f)}, - {Pair("-30",-30.0f), Pair("\x8A*(-6)^(-1)",-0.5235987755982988f), "", - Pair("-0.5",-0.5f), Pair("-3^(-1/2)",-0.5773502691896256f)}, - {Pair("-45/2",-22.5f), Pair("\x8A*(-8)^(-1)",-0.39269908169872414f), "", - Pair("(2-2^(1/2))^(1/2)*(-2)^(-1)",-0.3826834323650898f), Pair("1-2^(1/2)",-0.4142135623730951f)}, - {Pair("-18",-18.0f), Pair("\x8A*(-10)^(-1)",-0.3141592653589793f), "", - Pair("4^(-1)*(1-5^(1/2))",-0.3090169943749474f), Pair("-(1-2*5^(-1/2))^(1/2)",-0.3249196962329063f)}, - {Pair("-15",-15.0f), Pair("\x8A*(-12)^(-1)",-0.2617993877991494f), "", - Pair("-6^(1/2)*4^(-1)+2^(1/2)*4^(-1)",-0.25881904510252074f), Pair("3^(1/2)-2",-0.2679491924311227f)}, - {Pair("0",0.0f), Pair("0",0.0f), Pair("1",1.0f), - Pair("0",0.0f), Pair("0",0.0f)}, - {Pair("15",15.0f), Pair("\x8A*12^(-1)",0.2617993877991494f), Pair("6^(1/2)*4^(-1)+2^(1/2)*4^(-1)",0.9659258262890683f), - Pair("6^(1/2)*4^(-1)+2^(1/2)*(-4)^(-1)",0.25881904510252074f), Pair("-(3^(1/2)-2)",0.2679491924311227f)}, - {Pair("18",18.0f), Pair("\x8A*10^(-1)",0.3141592653589793f), Pair("(5/8+5^(1/2)/8)^(1/2)",0.9510565162951535f), - Pair("4^(-1)*(5^(1/2)-1)",0.3090169943749474f), Pair("(1-2*5^(-1/2))^(1/2)",0.3249196962329063f)}, - {Pair("45/2",22.5f), Pair("\x8A*8^(-1)",0.39269908169872414f), Pair("(2+2^(1/2))^(1/2)*2^(-1)",0.9238795325112867f), - Pair("(2-2^(1/2))^(1/2)*2^(-1)",0.3826834323650898f), Pair("2^(1/2)-1",0.4142135623730951f)}, - {Pair("30",30.0f), Pair("\x8A*6^(-1)",0.5235987755982988f), Pair("3^(1/2)*2^(-1)",0.8660254037844387f), - Pair("0.5",0.5f), Pair("3^(-1/2)",0.5773502691896256f)}, - {Pair("36",36.0f), Pair("\x8A*5^(-1)",0.6283185307179586f), Pair("(5^(1/2)+1)*4^(-1)",0.8090169943749475f), - Pair("(5/8-5^(1/2)/8)^(1/2)",0.5877852522924731f), Pair("(5-2*5^(1/2))^(1/2)",0.7265425280053609f)}, - {Pair("45",45.0f), Pair("\x8A*4^(-1)",0.7853981633974483f), Pair("2^(-1/2)",0.7071067811865476f), - Pair("2^(-1/2)",0.7071067811865475f), Pair("1",1.0f)}, - {Pair("54",54.0f), Pair("\x8A*3*10^(-1)",0.9424777960769379f), Pair("(5/8-5^(1/2)/8)^(1/2)",0.5877852522924732f), - Pair("4^(-1)*(5^(1/2)+1)",0.8090169943749473f), Pair("(1+2*5^(-1/2))^(1/2)",1.3763819204711731f)}, - {Pair("60",60.0f), Pair("\x8A*3^(-1)",1.0471975511965976f), Pair("0.5",0.5f), - Pair("3^(1/2)*2^(-1)",0.8660254037844386f), Pair("3^(1/2)",1.7320508075688767f)}, - {Pair("135/2",67.5f), Pair("\x8A*3*8^(-1)",1.1780972450961724f), Pair("(2-2^(1/2))^(1/2)*2^(-1)",0.38268343236508984f), - Pair("(2+2^(1/2))^(1/2)*2^(-1)",0.9238795325112867f), Pair("1+2^(1/2)",2.4142135623730945f)}, - {Pair("72",72.0f), Pair("\x8A*2*5^(-1)",1.2566370614359172f), Pair("(5^(1/2)-1)*4^(-1)",0.30901699437494745f), - Pair("(5/8+5^(1/2)/8)^(1/2)",0.9510565162951535f), Pair("(5+2*5^(1/2))^(1/2)",3.077683537175253f)}, - {Pair("75",75.0f), Pair("\x8A*5*12^(-1)",1.3089969389957472f), Pair("6^(1/2)*4^(-1)+2^(1/2)*(-4)^(-1)",0.25881904510252074f), - Pair("6^(1/2)*4^(-1)+2^(1/2)*4^(-1)",0.9659258262890683f), Pair("3^(1/2)+2",3.7320508075688776f)}, - {Pair("90",90.0f), Pair("\x8A*2^(-1)",1.5707963267948966f), Pair("0",0.0f), - Pair("1",1.0f), "undef"}, - {Pair("105",105.0f), Pair("\x8A*7*12^(-1)",1.832595714594046f), Pair("-6^(1/2)*4^(-1)+2^(1/2)*4^(-1)",-0.25881904510252063f), - "", ""}, - {Pair("108",108.0f), Pair("\x8A*3*5^(-1)",1.8849555921538759f), Pair("(1-5^(1/2))*4^(-1)",-0.30901699437494734f), - "", ""}, - {Pair("225/2",112.5f), Pair("\x8A*5*8^(-1)",1.9634954084936207f), Pair("(2-2^(1/2))^(1/2)*(-2)^(-1)",-0.3826834323650897f), - "", ""}, - {Pair("120",120.0f), Pair("\x8A*2*3^(-1)",2.0943951023931953f), Pair("-0.5",-0.5f), - "", ""}, - {Pair("126",126.0f), Pair("\x8A*7*10^(-1)",2.199114857512855f), Pair("-(5*8^(-1)-5^(1/2)*8^(-1))^(1/2)",-0.587785252292473f), - "", ""}, - {Pair("135",135.0f), Pair("\x8A*3*4^(-1)",2.356194490192345f), Pair("(-1)*(2^(-1/2))",-0.7071067811865475f), - "", ""}, - {Pair("144",144.0f), Pair("\x8A*4*5^(-1)",2.5132741228718345f), Pair("(-5^(1/2)-1)*4^(-1)",-0.8090169943749473f), - "", ""}, - {Pair("150",150.0f), Pair("\x8A*5*6^(-1)",2.6179938779914944f), Pair("-3^(1/2)*2^(-1)",-0.8660254037844387f), - "", ""}, - {Pair("315/2",157.5f), Pair("\x8A*7*8^(-1)",2.748893571891069f), Pair("-(2+2^(1/2))^(1/2)*2^(-1)",-0.9238795325112867f), - "", ""}, - {Pair("162",162.0f), Pair("\x8A*9*10^(-1)",2.827433388230814f), Pair("-(5*8^(-1)+5^(1/2)*8^(-1))^(1/2)",-0.9510565162951535f), - "", ""}, - {Pair("165",165.0f), Pair("\x8A*11*12^(-1)",2.8797932657906435f), Pair("(-1)*6^(1/2)*4^(-1)-2^(1/2)*4^(-1)",-0.9659258262890682f), - "", ""}, - {Pair("180",180.0f), Pair("\x8A",3.141592653589793f), Pair("-1",-1.0f), - Pair("0",0.0f), Pair("0",0.0f)}}; - -Expression Trigonometry::table(const Expression e, ExpressionNode::Type type, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { - assert(type == ExpressionNode::Type::Sine - || type == ExpressionNode::Type::Cosine - || type == ExpressionNode::Type::Tangent - || type == ExpressionNode::Type::ArcCosine - || type == ExpressionNode::Type::ArcSine - || type == ExpressionNode::Type::ArcTangent); - - int angleUnitIndex = angleUnit == Preferences::AngleUnit::Radian ? 1 : 0; - int trigonometricFunctionIndex = type == ExpressionNode::Type::Cosine || type == ExpressionNode::Type::ArcCosine ? 2 : (type == ExpressionNode::Type::Sine || type == ExpressionNode::Type::ArcSine ? 3 : 4); - int inputIndex = type == ExpressionNode::Type::ArcCosine || type == ExpressionNode::Type::ArcSine || type == ExpressionNode::Type::ArcTangent ? trigonometricFunctionIndex : angleUnitIndex; - int outputIndex = type == ExpressionNode::Type::ArcCosine || type == ExpressionNode::Type::ArcSine || type == ExpressionNode::Type::ArcTangent ? angleUnitIndex : trigonometricFunctionIndex; - - /* Avoid looping if we can exclude quickly that the e is in the table */ - if (inputIndex == 0 && e.type() != ExpressionNode::Type::Rational) { - return Expression(); - } - if (inputIndex == 1 && e.type() != ExpressionNode::Type::Rational && e.type() != ExpressionNode::Type::Multiplication && e.type() != ExpressionNode::Type::Constant) { - return Expression(); - } - if (inputIndex >1 && e.type() != ExpressionNode::Type::Rational && e.type() != ExpressionNode::Type::Multiplication && e.type() != ExpressionNode::Type::Power && e.type() != ExpressionNode::Type::Addition) { - return Expression(); - } - // We approximate the given expression to quickly compare it to the cheat table entries. - float eValue = e.node()->approximate(float(), context, complexFormat, angleUnit).toScalar(); - if (std::isnan(eValue) || std::isinf(eValue)) { - return Expression(); - } - for (int i = 0; i < k_numberOfEntries; i++) { - float inputValue = cheatTable[i][inputIndex].value; - if (std::isnan(inputValue) || std::fabs(inputValue-eValue) > Expression::Epsilon()) { - continue; - } - // Our given expression approximation matches a table entry, we check that both expressions are identical - Expression input = Expression::Parse(cheatTable[i][inputIndex].expression); - assert(!input.isUninitialized()); - input = input.deepReduce(context, complexFormat, angleUnit, target); - bool rightInput = input.isIdenticalTo(e); - if (rightInput) { - Expression output = Expression::Parse(cheatTable[i][outputIndex].expression); - if (output.isUninitialized()) { - return Expression(); - } - return output.deepReduce(context, complexFormat, angleUnit, target); - } - break; - } - return Expression(); -} - template std::complex Trigonometry::ConvertToRadian(const std::complex c, Preferences::AngleUnit angleUnit) { if (angleUnit == Preferences::AngleUnit::Degree) { diff --git a/poincare/src/trigonometry_cheat_table.cpp b/poincare/src/trigonometry_cheat_table.cpp new file mode 100644 index 000000000..62810698f --- /dev/null +++ b/poincare/src/trigonometry_cheat_table.cpp @@ -0,0 +1,272 @@ +#include + +namespace Poincare { + +Expression TrigonometryCheatTable::Row::Pair::reducedExpression(bool assertNotUninitialized, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) const { + Expression e = Expression::Parse(m_expression); + if (assertNotUninitialized) { + assert(!e.isUninitialized()); + } else { + if (e.isUninitialized()) { + return Expression(); + } + } + return e.deepReduce(context, complexFormat, angleUnit, target); +} + +Expression TrigonometryCheatTable::simplify(const Expression e, ExpressionNode::Type type, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) const { + assert(type == ExpressionNode::Type::Sine + || type == ExpressionNode::Type::Cosine + || type == ExpressionNode::Type::Tangent + || type == ExpressionNode::Type::ArcCosine + || type == ExpressionNode::Type::ArcSine + || type == ExpressionNode::Type::ArcTangent); + + // Compute the input and output types + Type angleUnitType = angleUnit == Preferences::AngleUnit::Radian ? Type::AngleInRadians : Type::AngleInDegrees; + Type trigonometricFunctionType; + if (type == ExpressionNode::Type::Cosine || type == ExpressionNode::Type::ArcCosine) { + trigonometricFunctionType = Type::Cosine; + } else if (type == ExpressionNode::Type::Sine || type == ExpressionNode::Type::ArcSine) { + trigonometricFunctionType = Type::Sine; + } else { + trigonometricFunctionType = Type::Tangent; + } + bool isIndirectType = type == ExpressionNode::Type::ArcCosine || type == ExpressionNode::Type::ArcSine || type == ExpressionNode::Type::ArcTangent; + Type inputType = isIndirectType ? trigonometricFunctionType : angleUnitType; + Type outputType = isIndirectType ? angleUnitType : trigonometricFunctionType; + + // Avoid looping if we can exclude quickly that e is in the table + if ((inputType == Type::AngleInDegrees + && e.type() != ExpressionNode::Type::Rational) + || (inputType == Type::AngleInRadians + && e.type() != ExpressionNode::Type::Rational + && e.type() != ExpressionNode::Type::Multiplication + && e.type() != ExpressionNode::Type::Constant) + || (inputType > Type::AngleInRadians + && e.type() != ExpressionNode::Type::Rational + && e.type() != ExpressionNode::Type::Multiplication + && e.type() != ExpressionNode::Type::Power + && e.type() != ExpressionNode::Type::Addition)) + { + return Expression(); + } + + // Approximate e to quickly compare it to cheat table entries + float eValue = e.node()->approximate(float(), context, complexFormat, angleUnit).toScalar(); + if (std::isnan(eValue) || std::isinf(eValue)) { + return Expression(); + } + for (int i = 0; i < k_numberOfEntries; i++) { + float inputValue = floatForTypeAtIndex(inputType, i); + if (std::isnan(inputValue) || std::fabs(inputValue - eValue) > Expression::Epsilon()) { + continue; + } + /* e's approximation matches a table entry, check that both expressions are + * identical */ + Expression input = expressionForTypeAtIndex(inputType, i, true, context, complexFormat, angleUnit, target); + if (input.isIdenticalTo(e)) { + return expressionForTypeAtIndex(outputType, i, false, context, complexFormat, angleUnit, target); + } + } + return Expression(); +} + +static_assert('\x8A' == Ion::Charset::SmallPi, "Unicode error"); + +/* Some cheat tables values were not entered because they would never be needed + * For instance, when simplfy a Cosine, we always compute the value for an angle + * in the top right trigonometric quadrant. */ +const TrigonometryCheatTable * TrigonometryCheatTable::Table() { + static Row sTableRows[] = { + Row(Row::Pair("-90", -90.0f), + Row::Pair("\x8A*(-2)^(-1)", -1.5707963267948966f), + Row::Pair(""), + Row::Pair("-1",-1.0f), + Row::Pair("undef")), + Row(Row::Pair("-75",-75.0), + Row::Pair("\x8A*(-5)*12^(-1)",-1.3089969389957472f), + Row::Pair(""), + Row::Pair("(-1)*6^(1/2)*4^(-1)-2^(1/2)*4^(-1)",-0.9659258262890683f), + Row::Pair("-(3^(1/2)+2)",-3.7320508075688776f)), + Row(Row::Pair("-72",-72.0), + Row::Pair("\x8A*2*(-5)^(-1)",-1.2566370614359172f), + Row::Pair(""), + Row::Pair("-(5/8+5^(1/2)/8)^(1/2)",-0.9510565162951535f), + Row::Pair("-(5+2*5^(1/2))^(1/2)",-3.077683537175253f)), + Row(Row::Pair("-135/2",67.5f), + Row::Pair("\x8A*(-3)*8^(-1)",-1.1780972450961724f), + Row::Pair(""), + Row::Pair("-(2+2^(1/2))^(1/2)*2^(-1)",-0.9238795325112867f), + Row::Pair("-1-2^(1/2)",-2.4142135623730945f)), + Row(Row::Pair("-60",-60.0f), + Row::Pair("\x8A*(-3)^(-1)",-1.0471975511965976f), + Row::Pair(""), + Row::Pair("-3^(1/2)*2^(-1)",-0.8660254037844386f), + Row::Pair("-3^(1/2)",-1.7320508075688767f)), + Row(Row::Pair("-54",-54.0f), + Row::Pair("\x8A*(-3)*10^(-1)",-0.9424777960769379), + Row::Pair(""), + Row::Pair("4^(-1)*(-1-5^(1/2))",-0.8090169943749473f), + Row::Pair("-(1+2*5^(-1/2))^(1/2)",-1.3763819204711731f)), + Row(Row::Pair("-45",-45.0f), + Row::Pair("\x8A*(-4)^(-1)",-0.7853981633974483f), + Row::Pair(""), + Row::Pair("(-1)*(2^(-1/2))",-0.7071067811865475f), + Row::Pair("-1",-1.0f)), + Row(Row::Pair("-36",-36.0f), + Row::Pair("\x8A*(-5)^(-1)",-0.6283185307179586f), + Row::Pair(""), + Row::Pair("-(5/8-5^(1/2)/8)^(1/2)",-0.5877852522924731f), + Row::Pair("-(5-2*5^(1/2))^(1/2)",-0.7265425280053609f)), + Row(Row::Pair("-30",-30.0f), + Row::Pair("\x8A*(-6)^(-1)",-0.5235987755982988f), + Row::Pair(""), + Row::Pair("-0.5",-0.5f), + Row::Pair("-3^(-1/2)",-0.5773502691896256f)), + Row(Row::Pair("-45/2",-22.5f), + Row::Pair("\x8A*(-8)^(-1)",-0.39269908169872414f), + Row::Pair(""), + Row::Pair("(2-2^(1/2))^(1/2)*(-2)^(-1)",-0.3826834323650898f), + Row::Pair("1-2^(1/2)",-0.4142135623730951f)), + Row(Row::Pair("-18",-18.0f), + Row::Pair("\x8A*(-10)^(-1)",-0.3141592653589793f), + Row::Pair(""), + Row::Pair("4^(-1)*(1-5^(1/2))",-0.3090169943749474f), + Row::Pair("-(1-2*5^(-1/2))^(1/2)",-0.3249196962329063f)), + Row(Row::Pair("-15",-15.0f), + Row::Pair("\x8A*(-12)^(-1)",-0.2617993877991494f), + Row::Pair(""), + Row::Pair("-6^(1/2)*4^(-1)+2^(1/2)*4^(-1)",-0.25881904510252074f), + Row::Pair("3^(1/2)-2",-0.2679491924311227f)), + Row(Row::Pair("0",0.0f), + Row::Pair("0",0.0f), + Row::Pair("1",1.0f), + Row::Pair("0",0.0f), + Row::Pair("0",0.0f)), + Row(Row::Pair("15",15.0f), + Row::Pair("\x8A*12^(-1)",0.2617993877991494f), + Row::Pair("6^(1/2)*4^(-1)+2^(1/2)*4^(-1)",0.9659258262890683f), + Row::Pair("6^(1/2)*4^(-1)+2^(1/2)*(-4)^(-1)",0.25881904510252074f), + Row::Pair("-(3^(1/2)-2)",0.2679491924311227f)), + Row(Row::Pair("18",18.0f), + Row::Pair("\x8A*10^(-1)",0.3141592653589793f), + Row::Pair("(5/8+5^(1/2)/8)^(1/2)",0.9510565162951535f), + Row::Pair("4^(-1)*(5^(1/2)-1)",0.3090169943749474f), + Row::Pair("(1-2*5^(-1/2))^(1/2)",0.3249196962329063f)), + Row(Row::Pair("45/2",22.5f), + Row::Pair("\x8A*8^(-1)",0.39269908169872414f), + Row::Pair("(2+2^(1/2))^(1/2)*2^(-1)",0.9238795325112867f), + Row::Pair("(2-2^(1/2))^(1/2)*2^(-1)",0.3826834323650898f), + Row::Pair("2^(1/2)-1",0.4142135623730951f)), + Row(Row::Pair("30",30.0f), + Row::Pair("\x8A*6^(-1)",0.5235987755982988f), + Row::Pair("3^(1/2)*2^(-1)",0.8660254037844387f), + Row::Pair("0.5",0.5f), + Row::Pair("3^(-1/2)",0.5773502691896256f)), + Row(Row::Pair("36",36.0f), + Row::Pair("\x8A*5^(-1)",0.6283185307179586f), + Row::Pair("(5^(1/2)+1)*4^(-1)",0.8090169943749475f), + Row::Pair("(5/8-5^(1/2)/8)^(1/2)",0.5877852522924731f), + Row::Pair("(5-2*5^(1/2))^(1/2)",0.7265425280053609f)), + Row(Row::Pair("45",45.0f), + Row::Pair("\x8A*4^(-1)",0.7853981633974483f), + Row::Pair("2^(-1/2)",0.7071067811865476f), + Row::Pair("2^(-1/2)",0.7071067811865475f), + Row::Pair("1",1.0f)), + Row(Row::Pair("54",54.0f), + Row::Pair("\x8A*3*10^(-1)",0.9424777960769379f), + Row::Pair("(5/8-5^(1/2)/8)^(1/2)",0.5877852522924732f), + Row::Pair("4^(-1)*(5^(1/2)+1)",0.8090169943749473f), + Row::Pair("(1+2*5^(-1/2))^(1/2)",1.3763819204711731f)), + Row(Row::Pair("60",60.0f), + Row::Pair("\x8A*3^(-1)",1.0471975511965976f), + Row::Pair("0.5",0.5f), + Row::Pair("3^(1/2)*2^(-1)",0.8660254037844386f), + Row::Pair("3^(1/2)",1.7320508075688767f)), + Row(Row::Pair("135/2",67.5f), + Row::Pair("\x8A*3*8^(-1)",1.1780972450961724f), + Row::Pair("(2-2^(1/2))^(1/2)*2^(-1)",0.38268343236508984f), + Row::Pair("(2+2^(1/2))^(1/2)*2^(-1)",0.9238795325112867f), + Row::Pair("1+2^(1/2)",2.4142135623730945f)), + Row(Row::Pair("72",72.0f), + Row::Pair("\x8A*2*5^(-1)",1.2566370614359172f), + Row::Pair("(5^(1/2)-1)*4^(-1)",0.30901699437494745f), + Row::Pair("(5/8+5^(1/2)/8)^(1/2)",0.9510565162951535f), + Row::Pair("(5+2*5^(1/2))^(1/2)",3.077683537175253f)), + Row(Row::Pair("75",75.0f), + Row::Pair("\x8A*5*12^(-1)",1.3089969389957472f), + Row::Pair("6^(1/2)*4^(-1)+2^(1/2)*(-4)^(-1)",0.25881904510252074f), + Row::Pair("6^(1/2)*4^(-1)+2^(1/2)*4^(-1)",0.9659258262890683f), + Row::Pair("3^(1/2)+2",3.7320508075688776f)), + Row(Row::Pair("90",90.0f), + Row::Pair("\x8A*2^(-1)",1.5707963267948966f), + Row::Pair("0",0.0f), + Row::Pair("1",1.0f), + Row::Pair("undef")), + Row(Row::Pair("105",105.0f), + Row::Pair("\x8A*7*12^(-1)",1.832595714594046f), + Row::Pair("-6^(1/2)*4^(-1)+2^(1/2)*4^(-1)",-0.25881904510252063f), + Row::Pair(""), + Row::Pair("")), + Row(Row::Pair("108",108.0f), + Row::Pair("\x8A*3*5^(-1)",1.8849555921538759f), + Row::Pair("(1-5^(1/2))*4^(-1)",-0.30901699437494734f), + Row::Pair(""), + Row::Pair("")), + Row(Row::Pair("225/2",112.5f), + Row::Pair("\x8A*5*8^(-1)",1.9634954084936207f), + Row::Pair("(2-2^(1/2))^(1/2)*(-2)^(-1)",-0.3826834323650897f), + Row::Pair(""), + Row::Pair("")), + Row(Row::Pair("120",120.0f), + Row::Pair("\x8A*2*3^(-1)",2.0943951023931953f), + Row::Pair("-0.5",-0.5f), + Row::Pair(""), + Row::Pair("")), + Row(Row::Pair("126",126.0f), + Row::Pair("\x8A*7*10^(-1)",2.199114857512855f), + Row::Pair("-(5*8^(-1)-5^(1/2)*8^(-1))^(1/2)",-0.587785252292473f), + Row::Pair(""), + Row::Pair("")), + Row(Row::Pair("135",135.0f), + Row::Pair("\x8A*3*4^(-1)",2.356194490192345f), + Row::Pair("(-1)*(2^(-1/2))",-0.7071067811865475f), + Row::Pair(""), + Row::Pair("")), + Row(Row::Pair("144",144.0f), + Row::Pair("\x8A*4*5^(-1)",2.5132741228718345f), + Row::Pair("(-5^(1/2)-1)*4^(-1)",-0.8090169943749473f), + Row::Pair(""), + Row::Pair("")), + Row(Row::Pair("150",150.0f), + Row::Pair("\x8A*5*6^(-1)",2.6179938779914944f), + Row::Pair("-3^(1/2)*2^(-1)",-0.8660254037844387f), + Row::Pair(""), + Row::Pair("")), + Row(Row::Pair("315/2",157.5f), + Row::Pair("\x8A*7*8^(-1)",2.748893571891069f), + Row::Pair("-(2+2^(1/2))^(1/2)*2^(-1)",-0.9238795325112867f), + Row::Pair(""), + Row::Pair("")), + Row(Row::Pair("162",162.0f), + Row::Pair("\x8A*9*10^(-1)",2.827433388230814f), + Row::Pair("-(5*8^(-1)+5^(1/2)*8^(-1))^(1/2)",-0.9510565162951535f), + Row::Pair(""), + Row::Pair("")), + Row(Row::Pair("165",165.0f), + Row::Pair("\x8A*11*12^(-1)",2.8797932657906435f), + Row::Pair("(-1)*6^(1/2)*4^(-1)-2^(1/2)*4^(-1)",-0.9659258262890682f), + Row::Pair(""), + Row::Pair("")), + Row(Row::Pair("180",180.0f), + Row::Pair("\x8A",3.141592653589793f), + Row::Pair("-1",-1.0f), + Row::Pair("0",0.0f), + Row::Pair("0",0.0f)) + }; + static TrigonometryCheatTable sTable(sTableRows); + return &sTable; +} + +} From 31866aaaf527ae3b40242191bb78acf22cb1c5da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 15 Jan 2019 10:02:19 +0100 Subject: [PATCH 239/373] [apps/calculation] Fix display of unreal For instance ln(-2) in real mode should display "unreal" --- apps/calculation/calculation.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/apps/calculation/calculation.cpp b/apps/calculation/calculation.cpp index 5476cb861..e794cbf30 100644 --- a/apps/calculation/calculation.cpp +++ b/apps/calculation/calculation.cpp @@ -155,7 +155,7 @@ bool Calculation::shouldOnlyDisplayApproximateOutput(Context * context) { * because of the number of significant digits, we display both. */ return exactAndApproximateDisplayedOutputsAreEqual(context) == Calculation::EqualSign::Equal; } - if (strcmp(m_exactOutputText, Undefined::Name()) == 0 || strcmp(m_approximateOutputText, Unreal::Name()) == 0 ) { + if (strcmp(m_exactOutputText, Undefined::Name()) == 0 || strcmp(m_approximateOutputText, Unreal::Name()) == 0) { // If the approximate result is 'unreal' or the exact result is 'undef' return true; } @@ -163,12 +163,10 @@ bool Calculation::shouldOnlyDisplayApproximateOutput(Context * context) { } bool Calculation::shouldOnlyDisplayExactOutput() { - /* If the approximateOutput is undef or unreal, we not not want to display it. - * This prevents: + /* If the approximateOutput is undef, do not display it. This prevents: * x->f(x) from displaying x = undef * x+x from displaying 2x = undef */ - return strcmp(m_approximateOutputText, Undefined::Name()) == 0 - || strcmp(m_approximateOutputText, Unreal::Name()) == 0; + return strcmp(m_approximateOutputText, Undefined::Name()) == 0; } Calculation::EqualSign Calculation::exactAndApproximateDisplayedOutputsAreEqual(Poincare::Context * context) { From d189a60effcf5b9baecd0c40725d59e38816cba8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 7 Jan 2019 17:07:54 +0100 Subject: [PATCH 240/373] [simulator] Fix left parenthesis Would send a '5' before --- ion/src/simulator/keyboard/fltkkbd.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ion/src/simulator/keyboard/fltkkbd.cpp b/ion/src/simulator/keyboard/fltkkbd.cpp index 8b55d0b42..c08b71322 100644 --- a/ion/src/simulator/keyboard/fltkkbd.cpp +++ b/ion/src/simulator/keyboard/fltkkbd.cpp @@ -25,10 +25,10 @@ static const int kShortcutForKey[Ion::Keyboard::NumberOfKeys] = { 0, 0, 'x', 0, 0, FL_BackSpace, 0, 0, 0, 'i', ',', 0, 0, 0, 0, 0, 0, 0, - '7', '8', '9', '(',')', 0, - '4', '5', '6', '*', '/', 0, - '1', '2', '3', '+', '-', 0, - '0', '.', 0, 0, FL_KP_Enter, 0 + FL_SHIFT | '7', FL_SHIFT | '8', FL_SHIFT | '9', '(',')', 0, + FL_SHIFT | '4', FL_SHIFT | '5', FL_SHIFT | '6', '*', '/', 0, + FL_SHIFT | '1', FL_SHIFT | '2', FL_SHIFT | '3', '+', '-', 0, + FL_SHIFT | '0', '.', 0, 0, FL_KP_Enter, 0 }; static bool shouldRepeatKey(Ion::Keyboard::Key k) { From 5e2ea6ee32cfcae6f7142d74665f3e8832cd49d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 7 Jan 2019 17:45:34 +0100 Subject: [PATCH 241/373] [simulator] Process letter keyboard events --- ion/src/simulator/keyboard/fltkkbd.cpp | 47 ++++++++++++++++++++++++-- ion/src/simulator/keyboard/fltkkbd.h | 2 ++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/ion/src/simulator/keyboard/fltkkbd.cpp b/ion/src/simulator/keyboard/fltkkbd.cpp index c08b71322..2a7cd3a85 100644 --- a/ion/src/simulator/keyboard/fltkkbd.cpp +++ b/ion/src/simulator/keyboard/fltkkbd.cpp @@ -22,8 +22,8 @@ static const char* kCharForKey[Ion::Keyboard::NumberOfKeys] = { static const int kShortcutForKey[Ion::Keyboard::NumberOfKeys] = { FL_Left, FL_Up, FL_Down, FL_Right, FL_Enter, FL_Escape, FL_Home, 0, 0, 0, 0, 0, - 0, 0, 'x', 0, 0, FL_BackSpace, - 0, 0, 0, 'i', ',', 0, + 0, 0, 0, 0, 0, FL_BackSpace, + 0, 0, 0, 0, ',', 0, 0, 0, 0, 0, 0, 0, FL_SHIFT | '7', FL_SHIFT | '8', FL_SHIFT | '9', '(',')', 0, FL_SHIFT | '4', FL_SHIFT | '5', FL_SHIFT | '6', '*', '/', 0, @@ -44,6 +44,31 @@ static void keyHandler(Fl_Widget *, long key) { } } +static void alphabetEventHandler(Fl_Widget *, long c) { + static Ion::Events::Event lowerEvents[FltkKbd::sNumberOfLettersInAlphabet] = { + Ion::Events::LowerA, Ion::Events::LowerB, Ion::Events::LowerC, Ion::Events::LowerD, Ion::Events::LowerE, + Ion::Events::LowerF, Ion::Events::LowerG, Ion::Events::LowerH, Ion::Events::LowerI, Ion::Events::LowerJ, + Ion::Events::LowerK, Ion::Events::LowerL, Ion::Events::LowerM, Ion::Events::LowerN, Ion::Events::LowerO, + Ion::Events::LowerP, Ion::Events::LowerQ, Ion::Events::LowerR, Ion::Events::LowerS, Ion::Events::LowerT, + Ion::Events::LowerU, Ion::Events::LowerV, Ion::Events::LowerW, Ion::Events::LowerX, Ion::Events::LowerY, + Ion::Events::LowerZ }; + static Ion::Events::Event upperEvents[FltkKbd::sNumberOfLettersInAlphabet] = { + Ion::Events::UpperA, Ion::Events::UpperB, Ion::Events::UpperC, Ion::Events::UpperD, Ion::Events::UpperE, + Ion::Events::UpperF, Ion::Events::UpperG, Ion::Events::UpperH, Ion::Events::UpperI, Ion::Events::UpperJ, + Ion::Events::UpperK, Ion::Events::UpperL, Ion::Events::UpperM, Ion::Events::UpperN, Ion::Events::UpperO, + Ion::Events::UpperP, Ion::Events::UpperQ, Ion::Events::UpperR, Ion::Events::UpperS, Ion::Events::UpperT, + Ion::Events::UpperU, Ion::Events::UpperV, Ion::Events::UpperW, Ion::Events::UpperX, Ion::Events::UpperY, + Ion::Events::UpperZ + }; + if (currentEvent == Ion::Events::None) { + if (c >= 'a' && c <= 'z') { + currentEvent = lowerEvents[c - 'a']; + } else if (c >= 'A' && c <= 'Z') { + currentEvent = upperEvents[c - 'A']; + } + } +} + FltkKbd::FltkKbd(int x, int y, int w, int h) : Fl_Group(x, y, w, h) { assert(KeyboardRows*KeyboardColumns == Ion::Keyboard::NumberOfKeys); int key_width = w/KeyboardColumns; @@ -69,6 +94,24 @@ FltkKbd::FltkKbd(int x, int y, int w, int h) : Fl_Group(x, y, w, h) { } m_buttons[k]->clear_visible_focus(); } + + // Get keyboard letters event + for (int k = 0; k < sNumberOfLettersInAlphabet; k++) { + char l = 'a' + k; + m_alphabetShortcuts[k] = new Fl_Button(0, 0, 0, 0, ""); + m_alphabetShortcuts[k]->callback(alphabetEventHandler,l); + m_alphabetShortcuts[k]->shortcut(l); + m_alphabetShortcuts[k]->clear_visible_focus(); + } + for (int k = 0; k < sNumberOfLettersInAlphabet; k++) { + char l = 'A' + k; + int index = sNumberOfLettersInAlphabet + k; + m_alphabetShortcuts[index] = new Fl_Button(0, 0, 0, 0, ""); + m_alphabetShortcuts[index]->callback(alphabetEventHandler, l); + m_alphabetShortcuts[index]->shortcut(FL_SHIFT | ('a' + k)); + m_alphabetShortcuts[index]->clear_visible_focus(); + } + end(); } diff --git a/ion/src/simulator/keyboard/fltkkbd.h b/ion/src/simulator/keyboard/fltkkbd.h index 3ff1673f4..dc30a76d3 100644 --- a/ion/src/simulator/keyboard/fltkkbd.h +++ b/ion/src/simulator/keyboard/fltkkbd.h @@ -7,10 +7,12 @@ class FltkKbd : public Fl_Group { public: + constexpr static int sNumberOfLettersInAlphabet = 26; FltkKbd(int x, int y, int w, int h); bool key_down(Ion::Keyboard::Key key); private: Fl_Button * m_buttons[Ion::Keyboard::NumberOfKeys]; + Fl_Button * m_alphabetShortcuts[2*sNumberOfLettersInAlphabet]; }; #endif From caa079571391434b694b2c4a103bc8d591404dfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 7 Jan 2019 17:47:43 +0100 Subject: [PATCH 242/373] [simulator] Coding style --- ion/src/simulator/init.cpp | 3 +-- ion/src/simulator/keyboard/fltkkbd.cpp | 16 ++++++++-------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/ion/src/simulator/init.cpp b/ion/src/simulator/init.cpp index 437ef5be6..b8bf9693d 100644 --- a/ion/src/simulator/init.cpp +++ b/ion/src/simulator/init.cpp @@ -76,9 +76,8 @@ void Ion::Display::waitForVBlank() { Ion::Keyboard::State Ion::Keyboard::scan() { Ion::Keyboard::State result = 0; - for (int i=0; ikey_down((Ion::Keyboard::Key)(Ion::Keyboard::NumberOfKeys-1-i)); - } return result; } diff --git a/ion/src/simulator/keyboard/fltkkbd.cpp b/ion/src/simulator/keyboard/fltkkbd.cpp index 2a7cd3a85..22282a121 100644 --- a/ion/src/simulator/keyboard/fltkkbd.cpp +++ b/ion/src/simulator/keyboard/fltkkbd.cpp @@ -70,16 +70,16 @@ static void alphabetEventHandler(Fl_Widget *, long c) { } FltkKbd::FltkKbd(int x, int y, int w, int h) : Fl_Group(x, y, w, h) { - assert(KeyboardRows*KeyboardColumns == Ion::Keyboard::NumberOfKeys); - int key_width = w/KeyboardColumns; - int key_height = h/KeyboardRows; - for (int k=0; klabelfont(FL_SYMBOL); From a6a2baeb01f4c39b9da400b772cc7db488d776b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 8 Jan 2019 10:53:34 +0100 Subject: [PATCH 243/373] [simulator] Process more keyboard event, such as ! ? ; --- ion/include/ion/events.h | 3 +- ion/src/simulator/keyboard/fltkkbd.cpp | 129 +++++++++++++++++++------ ion/src/simulator/keyboard/fltkkbd.h | 7 +- 3 files changed, 107 insertions(+), 32 deletions(-) diff --git a/ion/include/ion/events.h b/ion/include/ion/events.h index fc5270631..3ecbc5d2f 100644 --- a/ion/include/ion/events.h +++ b/ion/include/ion/events.h @@ -16,8 +16,9 @@ public: constexpr Event() : m_id(4*PageSize){} // Return Ion::Event::None by default constexpr Event(int i) : m_id(i){} // TODO: Assert here that i>=0 && i<255 -#if DEBUG + uint8_t id() const { return m_id; } +#if DEBUG const char * name() const; #endif Event(Keyboard::Key key, bool shift, bool alpha); diff --git a/ion/src/simulator/keyboard/fltkkbd.cpp b/ion/src/simulator/keyboard/fltkkbd.cpp index 22282a121..ad1c1988a 100644 --- a/ion/src/simulator/keyboard/fltkkbd.cpp +++ b/ion/src/simulator/keyboard/fltkkbd.cpp @@ -31,10 +31,6 @@ static const int kShortcutForKey[Ion::Keyboard::NumberOfKeys] = { FL_SHIFT | '0', '.', 0, 0, FL_KP_Enter, 0 }; -static bool shouldRepeatKey(Ion::Keyboard::Key k) { - return k <= Ion::Keyboard::Key::A4 || k == Ion::Keyboard::Key::A6; -} - static void keyHandler(Fl_Widget *, long key) { if (currentEvent == Ion::Events::None) { currentEvent = Ion::Events::Event((Ion::Keyboard::Key)key, @@ -44,32 +40,18 @@ static void keyHandler(Fl_Widget *, long key) { } } -static void alphabetEventHandler(Fl_Widget *, long c) { - static Ion::Events::Event lowerEvents[FltkKbd::sNumberOfLettersInAlphabet] = { - Ion::Events::LowerA, Ion::Events::LowerB, Ion::Events::LowerC, Ion::Events::LowerD, Ion::Events::LowerE, - Ion::Events::LowerF, Ion::Events::LowerG, Ion::Events::LowerH, Ion::Events::LowerI, Ion::Events::LowerJ, - Ion::Events::LowerK, Ion::Events::LowerL, Ion::Events::LowerM, Ion::Events::LowerN, Ion::Events::LowerO, - Ion::Events::LowerP, Ion::Events::LowerQ, Ion::Events::LowerR, Ion::Events::LowerS, Ion::Events::LowerT, - Ion::Events::LowerU, Ion::Events::LowerV, Ion::Events::LowerW, Ion::Events::LowerX, Ion::Events::LowerY, - Ion::Events::LowerZ }; - static Ion::Events::Event upperEvents[FltkKbd::sNumberOfLettersInAlphabet] = { - Ion::Events::UpperA, Ion::Events::UpperB, Ion::Events::UpperC, Ion::Events::UpperD, Ion::Events::UpperE, - Ion::Events::UpperF, Ion::Events::UpperG, Ion::Events::UpperH, Ion::Events::UpperI, Ion::Events::UpperJ, - Ion::Events::UpperK, Ion::Events::UpperL, Ion::Events::UpperM, Ion::Events::UpperN, Ion::Events::UpperO, - Ion::Events::UpperP, Ion::Events::UpperQ, Ion::Events::UpperR, Ion::Events::UpperS, Ion::Events::UpperT, - Ion::Events::UpperU, Ion::Events::UpperV, Ion::Events::UpperW, Ion::Events::UpperX, Ion::Events::UpperY, - Ion::Events::UpperZ - }; - if (currentEvent == Ion::Events::None) { - if (c >= 'a' && c <= 'z') { - currentEvent = lowerEvents[c - 'a']; - } else if (c >= 'A' && c <= 'Z') { - currentEvent = upperEvents[c - 'A']; - } - } +FltkKbd::FltkKbd(int x, int y, int w, int h) : Fl_Group(x, y, w, h) { + initButtons(x, y, w, h); + initAlphabetShortcuts(); + initOtherShortcuts(); + end(); } -FltkKbd::FltkKbd(int x, int y, int w, int h) : Fl_Group(x, y, w, h) { +static bool shouldRepeatKey(Ion::Keyboard::Key k) { + return k <= Ion::Keyboard::Key::A4 || k == Ion::Keyboard::Key::A6; +} + +void FltkKbd::initButtons(int x, int y, int w, int h) { assert(KeyboardRows * KeyboardColumns == Ion::Keyboard::NumberOfKeys); int keyWidth = w / KeyboardColumns; int keyHeight = h / KeyboardRows; @@ -94,12 +76,38 @@ FltkKbd::FltkKbd(int x, int y, int w, int h) : Fl_Group(x, y, w, h) { } m_buttons[k]->clear_visible_focus(); } +} +static void alphabetEventHandler(Fl_Widget *, long c) { + static Ion::Events::Event lowerEvents[FltkKbd::sNumberOfLettersInAlphabet] = { + Ion::Events::LowerA, Ion::Events::LowerB, Ion::Events::LowerC, Ion::Events::LowerD, Ion::Events::LowerE, + Ion::Events::LowerF, Ion::Events::LowerG, Ion::Events::LowerH, Ion::Events::LowerI, Ion::Events::LowerJ, + Ion::Events::LowerK, Ion::Events::LowerL, Ion::Events::LowerM, Ion::Events::LowerN, Ion::Events::LowerO, + Ion::Events::LowerP, Ion::Events::LowerQ, Ion::Events::LowerR, Ion::Events::LowerS, Ion::Events::LowerT, + Ion::Events::LowerU, Ion::Events::LowerV, Ion::Events::LowerW, Ion::Events::LowerX, Ion::Events::LowerY, + Ion::Events::LowerZ}; + static Ion::Events::Event upperEvents[FltkKbd::sNumberOfLettersInAlphabet] = { + Ion::Events::UpperA, Ion::Events::UpperB, Ion::Events::UpperC, Ion::Events::UpperD, Ion::Events::UpperE, + Ion::Events::UpperF, Ion::Events::UpperG, Ion::Events::UpperH, Ion::Events::UpperI, Ion::Events::UpperJ, + Ion::Events::UpperK, Ion::Events::UpperL, Ion::Events::UpperM, Ion::Events::UpperN, Ion::Events::UpperO, + Ion::Events::UpperP, Ion::Events::UpperQ, Ion::Events::UpperR, Ion::Events::UpperS, Ion::Events::UpperT, + Ion::Events::UpperU, Ion::Events::UpperV, Ion::Events::UpperW, Ion::Events::UpperX, Ion::Events::UpperY, + Ion::Events::UpperZ}; + if (currentEvent == Ion::Events::None) { + if (c >= 'a' && c <= 'z') { + currentEvent = lowerEvents[c - 'a']; + } else if (c >= 'A' && c <= 'Z') { + currentEvent = upperEvents[c - 'A']; + } + } +} + +void FltkKbd::initAlphabetShortcuts() { // Get keyboard letters event for (int k = 0; k < sNumberOfLettersInAlphabet; k++) { char l = 'a' + k; m_alphabetShortcuts[k] = new Fl_Button(0, 0, 0, 0, ""); - m_alphabetShortcuts[k]->callback(alphabetEventHandler,l); + m_alphabetShortcuts[k]->callback(alphabetEventHandler, l); m_alphabetShortcuts[k]->shortcut(l); m_alphabetShortcuts[k]->clear_visible_focus(); } @@ -111,10 +119,71 @@ FltkKbd::FltkKbd(int x, int y, int w, int h) : Fl_Group(x, y, w, h) { m_alphabetShortcuts[index]->shortcut(FL_SHIFT | ('a' + k)); m_alphabetShortcuts[index]->clear_visible_focus(); } +} - end(); +static void otherEventHandler(Fl_Widget *, long c) { + if (currentEvent == Ion::Events::None) { + currentEvent = Ion::Events::Event(c); + } +} + +void FltkKbd::initOtherShortcuts() { + // Get other events + for (int k = 0; k < sNumberOfOtherShortcuts; k++) { + m_otherShortcuts[k] = new Fl_Button(0, 0, 0, 0, ""); + } + int index = 0; + m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::Imaginary.id()); + m_otherShortcuts[index++]->shortcut(FL_ALT | 'i'); + m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::Comma.id()); + m_otherShortcuts[index++]->shortcut(','); + m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::Power.id()); + m_otherShortcuts[index++]->shortcut('^'); + m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::ShiftLeft.id()); + m_otherShortcuts[index++]->shortcut(FL_SHIFT | FL_Left); + m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::ShiftRight.id()); + m_otherShortcuts[index++]->shortcut(FL_SHIFT | FL_Right); + m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::Cut.id()); + m_otherShortcuts[index++]->shortcut(FL_META | 'x'); + m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::Copy.id()); + m_otherShortcuts[index++]->shortcut(FL_META | 'c'); + m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::Paste.id()); + m_otherShortcuts[index++]->shortcut(FL_META | 'v'); + m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::Clear.id()); + m_otherShortcuts[index++]->shortcut(FL_META | FL_BackSpace); + m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::LeftBracket.id()); + m_otherShortcuts[index++]->shortcut(FL_SHIFT | FL_ALT | '('); + m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::RightBracket.id()); + m_otherShortcuts[index++]->shortcut(FL_SHIFT | FL_ALT | ')'); + m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::LeftBrace.id()); + m_otherShortcuts[index++]->shortcut(FL_ALT | '('); + m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::RightBrace.id()); + m_otherShortcuts[index++]->shortcut(FL_ALT | ')'); + m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::Underscore.id()); + m_otherShortcuts[index++]->shortcut('_'); + m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::Equal.id()); + m_otherShortcuts[index++]->shortcut('='); + m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::Lower.id()); + m_otherShortcuts[index++]->shortcut('<'); + m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::Greater.id()); + m_otherShortcuts[index++]->shortcut('>'); + m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::Colon.id()); + m_otherShortcuts[index++]->shortcut(':'); + m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::SemiColon.id()); + m_otherShortcuts[index++]->shortcut(';'); + m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::DoubleQuotes.id()); + m_otherShortcuts[index++]->shortcut('"'); + m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::Question.id()); + m_otherShortcuts[index++]->shortcut('?'); + m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::Exclamation.id()); + m_otherShortcuts[index++]->shortcut('!'); + assert(index == sNumberOfOtherShortcuts); + for (int k = 0; k < sNumberOfOtherShortcuts; k++) { + m_otherShortcuts[k]->clear_visible_focus(); + } } bool FltkKbd::key_down(Ion::Keyboard::Key key) { + assert((int)key >= 0 && (int)key < Ion::Keyboard::NumberOfKeys); return m_buttons[(int)key]->value(); } diff --git a/ion/src/simulator/keyboard/fltkkbd.h b/ion/src/simulator/keyboard/fltkkbd.h index dc30a76d3..8c5fd444d 100644 --- a/ion/src/simulator/keyboard/fltkkbd.h +++ b/ion/src/simulator/keyboard/fltkkbd.h @@ -8,11 +8,16 @@ class FltkKbd : public Fl_Group { public: constexpr static int sNumberOfLettersInAlphabet = 26; + constexpr static int sNumberOfOtherShortcuts = 22; FltkKbd(int x, int y, int w, int h); bool key_down(Ion::Keyboard::Key key); private: + void initButtons(int x, int y, int w, int h); + void initAlphabetShortcuts(); + void initOtherShortcuts(); Fl_Button * m_buttons[Ion::Keyboard::NumberOfKeys]; - Fl_Button * m_alphabetShortcuts[2*sNumberOfLettersInAlphabet]; + Fl_Button * m_alphabetShortcuts[2 * sNumberOfLettersInAlphabet]; + Fl_Button * m_otherShortcuts[sNumberOfOtherShortcuts]; }; #endif From 15c87dc0b3635f3fa001e8994901eb097f02d94b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 8 Jan 2019 10:57:32 +0100 Subject: [PATCH 244/373] [simulator] Comment 3 keyboard events that are not working --- ion/src/simulator/keyboard/fltkkbd.cpp | 3 +++ ion/src/simulator/keyboard/fltkkbd.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ion/src/simulator/keyboard/fltkkbd.cpp b/ion/src/simulator/keyboard/fltkkbd.cpp index ad1c1988a..fa95d5215 100644 --- a/ion/src/simulator/keyboard/fltkkbd.cpp +++ b/ion/src/simulator/keyboard/fltkkbd.cpp @@ -151,6 +151,8 @@ void FltkKbd::initOtherShortcuts() { m_otherShortcuts[index++]->shortcut(FL_META | 'v'); m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::Clear.id()); m_otherShortcuts[index++]->shortcut(FL_META | FL_BackSpace); + // TODO not working +#if 0 m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::LeftBracket.id()); m_otherShortcuts[index++]->shortcut(FL_SHIFT | FL_ALT | '('); m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::RightBracket.id()); @@ -158,6 +160,7 @@ void FltkKbd::initOtherShortcuts() { m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::LeftBrace.id()); m_otherShortcuts[index++]->shortcut(FL_ALT | '('); m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::RightBrace.id()); +#endif m_otherShortcuts[index++]->shortcut(FL_ALT | ')'); m_otherShortcuts[index]->callback(otherEventHandler, Ion::Events::Underscore.id()); m_otherShortcuts[index++]->shortcut('_'); diff --git a/ion/src/simulator/keyboard/fltkkbd.h b/ion/src/simulator/keyboard/fltkkbd.h index 8c5fd444d..482896b1e 100644 --- a/ion/src/simulator/keyboard/fltkkbd.h +++ b/ion/src/simulator/keyboard/fltkkbd.h @@ -8,7 +8,7 @@ class FltkKbd : public Fl_Group { public: constexpr static int sNumberOfLettersInAlphabet = 26; - constexpr static int sNumberOfOtherShortcuts = 22; + constexpr static int sNumberOfOtherShortcuts = 19; // TODO 3 are not working, when fixed put 22 FltkKbd(int x, int y, int w, int h); bool key_down(Ion::Keyboard::Key key); private: From 8cbbd927616eb837cbe8cb541649871dcfcaeb42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 21 Jan 2019 11:53:37 +0100 Subject: [PATCH 245/373] [ion/device] Fix keyboard output GPIO activation --- ion/src/device/keyboard.cpp | 4 ++-- ion/src/device/keyboard.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ion/src/device/keyboard.cpp b/ion/src/device/keyboard.cpp index 91c634dae..0e2047d1c 100644 --- a/ion/src/device/keyboard.cpp +++ b/ion/src/device/keyboard.cpp @@ -53,8 +53,8 @@ State scan() { for (uint8_t i=0; igetBitRange(5,0); + // TODO: Assert pin numbers are sequentials and dynamically find 5 and 0 + uint8_t columns = Device::ColumnGPIO.IDR()->getBitRange(Device::numberOfColumns-1,0); /* The key is down if the input is brought low by the output. In other * words, we want to return true if the input is low (false). So we need to diff --git a/ion/src/device/keyboard.h b/ion/src/device/keyboard.h index fa69ab39f..7247745a6 100644 --- a/ion/src/device/keyboard.h +++ b/ion/src/device/keyboard.h @@ -52,8 +52,8 @@ inline void activateRow(uint8_t row) { * the others to 1. */ uint16_t rowState = ~(1<setBitRange(9, 0, rowState); + // TODO: Assert pin numbers are sequentials and dynamically find 8 and 0 + Device::RowGPIO.ODR()->setBitRange(numberOfRows-1, 0, rowState); // TODO: 100 us seems to work, but wasn't really calculated Timing::usleep(100); From 8f0246b9d648988758ae84a8229c8bdd2ec3a123 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 21 Jan 2019 11:54:44 +0100 Subject: [PATCH 246/373] [build/device] Remove duplicate line in gdb script --- build/device/gdb_script.gdb | 1 - 1 file changed, 1 deletion(-) diff --git a/build/device/gdb_script.gdb b/build/device/gdb_script.gdb index 04d744db2..fef280e82 100644 --- a/build/device/gdb_script.gdb +++ b/build/device/gdb_script.gdb @@ -3,7 +3,6 @@ define armex printf "SCB_CFSR 0x%x\n", *0xE000ED28 printf "SCB_HFSR 0x%x\n", *0xE000ED2C - printf "SCB_HFSR 0x%x\n", *0xE000ED2C printf "SCB_MMAR 0x%x\n", *0xE000ED34 printf "SCB_BFAR 0x%x\n", *0xE000ED38 printf "xPSR 0x%x\n", *(int *)($msp+28) From 6948de2ad3facc4df0dc8348fceeb0747c26b732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 16 Jan 2019 12:13:20 +0100 Subject: [PATCH 247/373] [poincare] ComplexCartesian: fix approximation The assertions that the real and imaginary parts are real can be false due to double lack of precision. We escape these cases by returning an undefined approximation. --- poincare/src/complex_cartesian.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/poincare/src/complex_cartesian.cpp b/poincare/src/complex_cartesian.cpp index b8682a89e..fc2241a96 100644 --- a/poincare/src/complex_cartesian.cpp +++ b/poincare/src/complex_cartesian.cpp @@ -35,6 +35,18 @@ Complex ComplexCartesianNode::templatedApproximate(Context& context, Preferen assert(imagEvalution.type() == EvaluationNode::Type::Complex); std::complex a = static_cast &>(realEvaluation).stdComplex(); std::complex b = static_cast &>(imagEvalution).stdComplex(); + if ((a.imag() != 0.0 && !std::isnan(a.imag())) || (b.imag() != 0.0 && !std::isnan(b.imag()))) { + /* a and b are supposed to be real (if they are not undefined). However, + * due to double precision limit, the approximation of the real part or the + * imaginary part can lead to complex values. + * For instance, let the real part be + * sqrt(2*sqrt(5E23+1)-1E12*sqrt(2)) ~ 1.1892E-6. Due to std::sqrt(2.0) + * unprecision, 2*sqrt(5E23+1)-1E12*sqrt(2) < 0 which leads to + * sqrt(2*sqrt(5E23+1)-1E12*sqrt(2)) being a complex number. + * In this case, we return an undefined complex because the approximation + * is very likely to be false. */ + return Complex::Undefined(); + } assert(a.imag() == 0.0 || std::isnan(a.imag())); assert(b.imag() == 0.0 || std::isnan(b.imag())); return Complex(a.real(), b.real()); From 2f9f40f1a79176c4b962eed8380e406305e403ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 15 Jan 2019 13:58:57 +0100 Subject: [PATCH 248/373] [python/turtle] Store the heading in degrees with no k_headingOffset This reduces rouding errors, such as: setHeading(0) right(1) heading() -> gives -1.00...01 --- python/port/mod/turtle/turtle.cpp | 28 +++++++++------------------- python/port/mod/turtle/turtle.h | 9 ++++----- 2 files changed, 13 insertions(+), 24 deletions(-) diff --git a/python/port/mod/turtle/turtle.cpp b/python/port/mod/turtle/turtle.cpp index 2bbc45487..0d87ee256 100644 --- a/python/port/mod/turtle/turtle.cpp +++ b/python/port/mod/turtle/turtle.cpp @@ -31,7 +31,7 @@ void Turtle::reset() { // Reset turtle values m_x = 0; m_y = 0; - m_heading = k_headingOffset; + m_heading = 0; m_color = k_defaultColor; m_penDown = true; m_visible = true; @@ -45,20 +45,18 @@ void Turtle::reset() { bool Turtle::forward(mp_float_t length) { return goTo( - m_x + length * sin(m_heading), - m_y + length * cos(m_heading) + m_x + length * cos(m_heading * k_headingScale), + m_y + length * sin(m_heading * k_headingScale) ); } void Turtle::left(mp_float_t angle) { - setHeading( - k_invertedYAxisCoefficient * ((m_heading - k_headingOffset) + k_invertedYAxisCoefficient * (angle * k_headingScale)) / k_headingScale - ); + setHeading(m_heading + angle); } void Turtle::circle(mp_int_t radius, mp_float_t angle) { mp_float_t oldHeading = heading(); - mp_float_t length = ((angle > 0 ? 1 : -1) * angle * k_headingScale) * radius; + mp_float_t length = (angle > 0 ? 1 : -1) * angle * k_headingScale * radius; if (length > 1) { for (int i = 1; i < length; i++) { mp_float_t progress = i / length; @@ -99,10 +97,6 @@ bool Turtle::goTo(mp_float_t x, mp_float_t y) { return false; } -mp_float_t Turtle::heading() const { - return k_invertedYAxisCoefficient * (m_heading - k_headingOffset) / k_headingScale; -} - void Turtle::setHeading(mp_float_t angle) { micropython_port_vm_hook_loop(); setHeadingPrivate(angle); @@ -173,10 +167,6 @@ void Turtle::viewDidDisappear() { // Private functions -void Turtle::setHeadingPrivate(mp_float_t angle) { - m_heading = k_invertedYAxisCoefficient * angle * k_headingScale + k_headingOffset; -} - KDPoint Turtle::position(mp_float_t x, mp_float_t y) const { return KDPoint(floor(x + k_xOffset), floor(k_invertedYAxisCoefficient * y + k_yOffset)); } @@ -245,8 +235,8 @@ bool Turtle::draw(bool force) { // Draw the head KDCoordinate headOffsetLength = 6; - KDCoordinate headOffsetX = headOffsetLength * sin(m_heading); - KDCoordinate headOffsetY = -headOffsetLength * cos(m_heading); + KDCoordinate headOffsetX = headOffsetLength * cos(m_heading * k_headingScale); + KDCoordinate headOffsetY = k_invertedYAxisCoefficient * headOffsetLength * sin(m_heading * k_headingScale); KDPoint headOffset(headOffsetX, headOffsetY); drawingRect = KDRect( position().translatedBy(headOffset).translatedBy(KDPoint(-k_iconHeadSize/2, -k_iconHeadSize/2)), @@ -336,8 +326,8 @@ void Turtle::drawPaw(PawType type, PawPosition pos) { // Compute the paw offset from the turtle center float currentAngle = angles[(int) type]; float crawlDelta = ((float)((int)pos)) * crawlOffset; - float pawX = pawOffset * sin(m_heading+currentAngle) + crawlDelta * sin(m_heading); - float pawY = - pawOffset * cos(m_heading+currentAngle) - crawlDelta * cos(m_heading); + float pawX = pawOffset * cos(m_heading * k_headingScale + currentAngle) + crawlDelta * cos(m_heading * k_headingScale); + float pawY = k_invertedYAxisCoefficient * (pawOffset * sin(m_heading * k_headingScale + currentAngle) + crawlDelta * sin(m_heading * k_headingScale)); KDCoordinate pawOffsetX = ((int)pawX) - (pawX < 0 ? 1 : 0); KDCoordinate pawOffsetY = ((int)pawY) - (pawY < 0 ? 1 : 0); KDPoint offset(pawOffsetX, pawOffsetY); diff --git a/python/port/mod/turtle/turtle.h b/python/port/mod/turtle/turtle.h index 532669939..88857fad2 100644 --- a/python/port/mod/turtle/turtle.h +++ b/python/port/mod/turtle/turtle.h @@ -24,7 +24,7 @@ public: constexpr Turtle() : m_x(0), m_y(0), - m_heading(k_headingOffset), + m_heading(0), m_color(k_defaultColor), m_penDown(true), m_visible(true), @@ -47,7 +47,7 @@ public: void circle(mp_int_t radius, mp_float_t angle = 360); bool goTo(mp_float_t x, mp_float_t y); - mp_float_t heading() const; + mp_float_t heading() const { return m_heading; } void setHeading(mp_float_t angle); uint8_t speed() const { return m_speed; } @@ -76,7 +76,6 @@ public: void viewDidDisappear(); private: - static constexpr mp_float_t k_headingOffset = M_PI_2; static constexpr mp_float_t k_headingScale = M_PI / 180; /* The Y axis is oriented upwards in Turtle and downwards in Kandinsky, so we * need to invert some values, hence k_invertedYAxisCoefficient. */ @@ -116,7 +115,7 @@ private: KDColor m_color; }; - void setHeadingPrivate(mp_float_t angle); + void setHeadingPrivate(mp_float_t angle) { m_heading = angle; } KDPoint position(mp_float_t x, mp_float_t y) const; KDPoint position() const { return position(m_x, m_y); } @@ -137,7 +136,7 @@ private: * right and the y axis goes upwards. */ mp_float_t m_x; mp_float_t m_y; - /* The heading is the angle in radians between the direction of the turtle and + /* The heading is the angle in degrees between the direction of the turtle and * the X axis, in the counterclockwise direction. */ mp_float_t m_heading; From 2bde26af6921ebc27f31fb9074e8bb4c9ca4cfdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 21 Jan 2019 11:58:55 +0100 Subject: [PATCH 249/373] [python/turtle] Specify namespace std when using cos, sin --- python/port/mod/turtle/turtle.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/python/port/mod/turtle/turtle.cpp b/python/port/mod/turtle/turtle.cpp index 0d87ee256..3a3499750 100644 --- a/python/port/mod/turtle/turtle.cpp +++ b/python/port/mod/turtle/turtle.cpp @@ -1,5 +1,6 @@ #include "turtle.h" #include +#include extern "C" { #include } @@ -45,8 +46,8 @@ void Turtle::reset() { bool Turtle::forward(mp_float_t length) { return goTo( - m_x + length * cos(m_heading * k_headingScale), - m_y + length * sin(m_heading * k_headingScale) + m_x + length * std::cos(m_heading * k_headingScale), + m_y + length * std::sin(m_heading * k_headingScale) ); } @@ -235,8 +236,8 @@ bool Turtle::draw(bool force) { // Draw the head KDCoordinate headOffsetLength = 6; - KDCoordinate headOffsetX = headOffsetLength * cos(m_heading * k_headingScale); - KDCoordinate headOffsetY = k_invertedYAxisCoefficient * headOffsetLength * sin(m_heading * k_headingScale); + KDCoordinate headOffsetX = headOffsetLength * std::cos(m_heading * k_headingScale); + KDCoordinate headOffsetY = k_invertedYAxisCoefficient * headOffsetLength * std::sin(m_heading * k_headingScale); KDPoint headOffset(headOffsetX, headOffsetY); drawingRect = KDRect( position().translatedBy(headOffset).translatedBy(KDPoint(-k_iconHeadSize/2, -k_iconHeadSize/2)), @@ -326,8 +327,8 @@ void Turtle::drawPaw(PawType type, PawPosition pos) { // Compute the paw offset from the turtle center float currentAngle = angles[(int) type]; float crawlDelta = ((float)((int)pos)) * crawlOffset; - float pawX = pawOffset * cos(m_heading * k_headingScale + currentAngle) + crawlDelta * cos(m_heading * k_headingScale); - float pawY = k_invertedYAxisCoefficient * (pawOffset * sin(m_heading * k_headingScale + currentAngle) + crawlDelta * sin(m_heading * k_headingScale)); + float pawX = pawOffset * std::cos(m_heading * k_headingScale + currentAngle) + crawlDelta * std::cos(m_heading * k_headingScale); + float pawY = k_invertedYAxisCoefficient * (pawOffset * std::sin(m_heading * k_headingScale + currentAngle) + crawlDelta * std::sin(m_heading * k_headingScale)); KDCoordinate pawOffsetX = ((int)pawX) - (pawX < 0 ? 1 : 0); KDCoordinate pawOffsetY = ((int)pawY) - (pawY < 0 ? 1 : 0); KDPoint offset(pawOffsetX, pawOffsetY); From 282feac8a1766686a8d3fb47033e867879f8bf4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 14 Jan 2019 10:47:35 +0100 Subject: [PATCH 250/373] [apps/code] Do not allow script names starting with a number. --- apps/code/script.cpp | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/apps/code/script.cpp b/apps/code/script.cpp index f0d8072bc..c6069fd54 100644 --- a/apps/code/script.cpp +++ b/apps/code/script.cpp @@ -37,17 +37,35 @@ bool Script::DefaultName(char buffer[], size_t bufferSize) { return false; } +bool isSmallLetterOrUnderscoreChar(const char c) { + return (c >= 'a' && c <= 'z') || c == '_'; +} +bool isNumberChar(const char c) { + return c >= '0' && c <= '9'; +} + bool Script::nameCompliant(const char * name) { - /* The name format is [a-z0-9_\.]+ */ - const char * currentChar = name; - while (*currentChar != 0) { - if ((*currentChar >= 'a' && *currentChar <= 'z') || *currentChar == '_' || (*currentChar >= '0' && *currentChar <= '9') || *currentChar == '.') { - currentChar++; - continue; - } + /* We allow here the empty script name ".py", because it is the name used to + * create a new empty script. When naming or renaming a script, we check + * elsewhere that the name is no longer empty. + * The name format is ([a-z_][a-z0-9_]*)*\.py + * */ + const char * c = name; + if (*c == 0 || (!isSmallLetterOrUnderscoreChar(*c) && *c != '.')) { + /* The name cannot be empty. Its first letter must be in [a-z_] or the + * extension dot. */ return false; } - return name != currentChar; + while (*c != 0) { + if (*c == '.' && strcmp(c+1, ScriptStore::k_scriptExtension) == 0) { + return true; + } + if (!isSmallLetterOrUnderscoreChar(*c) && !isNumberChar(*c)) { + return false; + } + c++; + } + return false; } bool Script::importationStatus() const { From 1994e716bf2b719cf7e4a7129626994681fa7417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 14 Jan 2019 11:23:42 +0100 Subject: [PATCH 251/373] [i18n] Change Message name --- apps/code/base.de.i18n | 2 +- apps/code/base.en.i18n | 2 +- apps/code/base.es.i18n | 2 +- apps/code/base.fr.i18n | 2 +- apps/code/base.pt.i18n | 2 +- apps/code/menu_controller.cpp | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/code/base.de.i18n b/apps/code/base.de.i18n index 70b704e82..155cd5ccd 100644 --- a/apps/code/base.de.i18n +++ b/apps/code/base.de.i18n @@ -5,4 +5,4 @@ ExecuteScript = "Skript ausfuehren" AutoImportScript = "Automatischer Import in Konsole" DeleteScript = "Skript loeschen" FunctionsAndVariables = "Funktionen und Variablen" -NonCompliantName = "Erlaubte Zeichen: a-z, 0-9, _" +AllowedCharactersaz09 = "Erlaubte Zeichen: a-z, 0-9, _" diff --git a/apps/code/base.en.i18n b/apps/code/base.en.i18n index 7a4a9c4bc..8bf1e3c9f 100644 --- a/apps/code/base.en.i18n +++ b/apps/code/base.en.i18n @@ -5,4 +5,4 @@ ExecuteScript = "Execute script" AutoImportScript = "Auto import in shell" DeleteScript = "Delete script" FunctionsAndVariables = "Functions and variables" -NonCompliantName = "Allowed characters: a-z, 0-9, _" +AllowedCharactersaz09 = "Allowed characters: a-z, 0-9, _" diff --git a/apps/code/base.es.i18n b/apps/code/base.es.i18n index eaae8c3bd..1f6fc5aaf 100644 --- a/apps/code/base.es.i18n +++ b/apps/code/base.es.i18n @@ -5,4 +5,4 @@ ExecuteScript = "Ejecutar el archivo" AutoImportScript = "Importacion auto en interprete" DeleteScript = "Eliminar el archivo" FunctionsAndVariables = "Funciones y variables" -NonCompliantName = "Caracteres permitidos : a-z, 0-9, _" +AllowedCharactersaz09 = "Caracteres permitidos : a-z, 0-9, _" diff --git a/apps/code/base.fr.i18n b/apps/code/base.fr.i18n index b063007dd..876bac18c 100644 --- a/apps/code/base.fr.i18n +++ b/apps/code/base.fr.i18n @@ -5,4 +5,4 @@ ExecuteScript = "Executer le script" AutoImportScript = "Importation auto dans la console" DeleteScript = "Supprimer le script" FunctionsAndVariables = "Fonctions et variables" -NonCompliantName = "Caractères autorisés : a-z, 0-9, _" +AllowedCharactersaz09 = "Caractères autorisés : a-z, 0-9, _" diff --git a/apps/code/base.pt.i18n b/apps/code/base.pt.i18n index 4d083b061..29acc7c3c 100644 --- a/apps/code/base.pt.i18n +++ b/apps/code/base.pt.i18n @@ -5,4 +5,4 @@ ExecuteScript = "Executar o script" AutoImportScript = "Importacao auto no interpretador" DeleteScript = "Eliminar o script" FunctionsAndVariables = "Funções e variáveis" -NonCompliantName = "Caracteres permitidos : a-z, 0-9, _" +AllowedCharactersaz09 = "Caracteres permitidos : a-z, 0-9, _" diff --git a/apps/code/menu_controller.cpp b/apps/code/menu_controller.cpp index 289fd2947..f37c0c42a 100644 --- a/apps/code/menu_controller.cpp +++ b/apps/code/menu_controller.cpp @@ -338,7 +338,7 @@ bool MenuController::textFieldDidFinishEditing(TextField * textField, const char } else if (error == Script::ErrorStatus::NameTaken) { app()->displayWarning(I18n::Message::NameTaken); } else if (error == Script::ErrorStatus::NonCompliantName) { - app()->displayWarning(I18n::Message::NonCompliantName); + app()->displayWarning(I18n::Message::AllowedCharactersaz09); } else { assert(error == Script::ErrorStatus::NotEnoughSpaceAvailable); app()->displayWarning(I18n::Message::NameTooLong); From f392ca80638c3e9d0512d8c7ba45f7a9c5d5fb34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 14 Jan 2019 11:25:54 +0100 Subject: [PATCH 252/373] [apps/code] More details in NonCompliantName warning --- apps/code/menu_controller.cpp | 2 +- apps/graph/base.de.i18n | 1 - apps/graph/base.en.i18n | 1 - apps/graph/base.es.i18n | 1 - apps/graph/base.fr.i18n | 1 - apps/graph/base.pt.i18n | 1 - apps/shared.de.i18n | 1 + apps/shared.en.i18n | 1 + apps/shared.es.i18n | 1 + apps/shared.fr.i18n | 1 + apps/shared.pt.i18n | 1 + 11 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/code/menu_controller.cpp b/apps/code/menu_controller.cpp index f37c0c42a..1c8e3823d 100644 --- a/apps/code/menu_controller.cpp +++ b/apps/code/menu_controller.cpp @@ -338,7 +338,7 @@ bool MenuController::textFieldDidFinishEditing(TextField * textField, const char } else if (error == Script::ErrorStatus::NameTaken) { app()->displayWarning(I18n::Message::NameTaken); } else if (error == Script::ErrorStatus::NonCompliantName) { - app()->displayWarning(I18n::Message::AllowedCharactersaz09); + app()->displayWarning(I18n::Message::AllowedCharactersaz09, I18n::Message::NameCannotStartWithNumber); } else { assert(error == Script::ErrorStatus::NotEnoughSpaceAvailable); app()->displayWarning(I18n::Message::NameTooLong); diff --git a/apps/graph/base.de.i18n b/apps/graph/base.de.i18n index 108ebd0a7..ed06c9cbc 100644 --- a/apps/graph/base.de.i18n +++ b/apps/graph/base.de.i18n @@ -21,4 +21,3 @@ DerivativeFunctionColumn = "Spalte der Ableitungsfunktion" HideDerivativeColumn = "Ableitungsfunktion ausblenden" AllowedCharactersAZaz09 = "Erlaubte Zeichen: A-Z, a-z, 0-9, _" ReservedName = "Reserviertes Wort" -NameCannotStartWithNumber = "Ein name darf nicht mit einer Zahl beginnen" diff --git a/apps/graph/base.en.i18n b/apps/graph/base.en.i18n index 36f2820dd..34847cd07 100644 --- a/apps/graph/base.en.i18n +++ b/apps/graph/base.en.i18n @@ -21,4 +21,3 @@ DerivativeFunctionColumn = "Derivative function column" HideDerivativeColumn = "Hide the derivative function" AllowedCharactersAZaz09 = "Allowed characters: A-Z, a-z, 0-9, _" ReservedName = "Reserved name" -NameCannotStartWithNumber = "A name cannot start with a number" diff --git a/apps/graph/base.es.i18n b/apps/graph/base.es.i18n index 6386083e2..23d2e66a6 100644 --- a/apps/graph/base.es.i18n +++ b/apps/graph/base.es.i18n @@ -21,4 +21,3 @@ DerivativeFunctionColumn = "Columna de la derivada" HideDerivativeColumn = "Ocultar la derivada" AllowedCharactersAZaz09 = "Caracteres permitidos : A-Z, a-z, 0-9, _" ReservedName = "Nombre reservado" -NameCannotStartWithNumber = "Un nombre no puede empezar con un número" diff --git a/apps/graph/base.fr.i18n b/apps/graph/base.fr.i18n index b27e0ee06..4d3a06807 100644 --- a/apps/graph/base.fr.i18n +++ b/apps/graph/base.fr.i18n @@ -21,4 +21,3 @@ DerivativeFunctionColumn = "Colonne de la fonction derivee" HideDerivativeColumn = "Masquer la fonction derivee" AllowedCharactersAZaz09 = "Caractères autorisés : A-Z, a-z, 0-9, _" ReservedName = "Nom réservé" -NameCannotStartWithNumber = "Un nom ne peut pas commencer par un chiffre" diff --git a/apps/graph/base.pt.i18n b/apps/graph/base.pt.i18n index 1c702aee8..693d1c8ca 100644 --- a/apps/graph/base.pt.i18n +++ b/apps/graph/base.pt.i18n @@ -21,4 +21,3 @@ DerivativeFunctionColumn = "Coluna da funcao derivada" HideDerivativeColumn = "Esconder funcao derivada" AllowedCharactersAZaz09 = "Caracteres permitidos : A-Z, a-z, 0-9, _" ReservedName = "Nome reservado" -NameCannotStartWithNumber = "Um nome não pode começar com um número" diff --git a/apps/shared.de.i18n b/apps/shared.de.i18n index c395cc81f..06bebef52 100644 --- a/apps/shared.de.i18n +++ b/apps/shared.de.i18n @@ -32,6 +32,7 @@ Language = "Sprache" LowBattery = "Batterie erschoepft" Mean = "Mittelwert" Move = " Verschieben: " +NameCannotStartWithNumber = "Ein name darf nicht mit einer Zahl beginnen" NameTaken = "Dieser Name ist bereits vergeben" NameTooLong = "Der Name ist zu lang" Next = "Naechste" diff --git a/apps/shared.en.i18n b/apps/shared.en.i18n index ce0555eb7..8cff681b6 100644 --- a/apps/shared.en.i18n +++ b/apps/shared.en.i18n @@ -32,6 +32,7 @@ Language = "Language" LowBattery = "Low battery" Mean = "Mean" Move = " Move: " +NameCannotStartWithNumber = "A name cannot start with a number" NameTaken = "This name has already been taken" NameTooLong = "This name is too long" Next = "Next" diff --git a/apps/shared.es.i18n b/apps/shared.es.i18n index ff3874dfe..697790e12 100644 --- a/apps/shared.es.i18n +++ b/apps/shared.es.i18n @@ -32,6 +32,7 @@ Language = "Idioma" LowBattery = "Bateria baja" Mean = "Media" Move = " Mover : " +NameCannotStartWithNumber = "Un nombre no puede empezar con un número" NameTaken = "Este nombre ya está en uso" NameTooLong = "Este nombre es demasiado largo" Next = "Siguiente" diff --git a/apps/shared.fr.i18n b/apps/shared.fr.i18n index fb485d58e..df664c364 100644 --- a/apps/shared.fr.i18n +++ b/apps/shared.fr.i18n @@ -32,6 +32,7 @@ Language = "Langue" LowBattery = "Batterie faible" Mean = "Moyenne" Move = " Deplacer : " +NameCannotStartWithNumber = "Un nom ne peut pas commencer par un chiffre" NameTaken = "Ce nom est déjà utilisé" NameTooLong = "Ce nom est trop long" Next = "Suivant" diff --git a/apps/shared.pt.i18n b/apps/shared.pt.i18n index bb68a1858..9e12ec57a 100644 --- a/apps/shared.pt.i18n +++ b/apps/shared.pt.i18n @@ -32,6 +32,7 @@ Language = "Idioma" LowBattery = "Bateria fraca" Mean = "Media" Move = " Mover : " +NameCannotStartWithNumber = "Um nome não pode começar com um número" NameTaken = "Este nome é já usado" NameTooLong = "Este nome é muito longo" Next = "Seguinte" From 1b78f03219b53c63f2ceda451210482a49f04d22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 14 Jan 2019 11:33:12 +0100 Subject: [PATCH 253/373] [apps/code] Comment the non support for upper cases in script names --- apps/code/script.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/code/script.cpp b/apps/code/script.cpp index c6069fd54..1c97a9083 100644 --- a/apps/code/script.cpp +++ b/apps/code/script.cpp @@ -49,7 +49,10 @@ bool Script::nameCompliant(const char * name) { * create a new empty script. When naming or renaming a script, we check * elsewhere that the name is no longer empty. * The name format is ([a-z_][a-z0-9_]*)*\.py - * */ + * + * We do not allow upper cases in the script names because script names are + * used in the URLs of the NumWorks workshop website and we do not want + * problems with case sensitivity. */ const char * c = name; if (*c == 0 || (!isSmallLetterOrUnderscoreChar(*c) && *c != '.')) { /* The name cannot be empty. Its first letter must be in [a-z_] or the From f8f47059290607fbc314071aa002ac34da5d9d5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 21 Jan 2019 11:36:30 +0100 Subject: [PATCH 254/373] [poincare] AbsoluteValue: fix shallowReduce to reduce abs(0) to 0 --- poincare/src/absolute_value.cpp | 13 +++++++++---- poincare/test/function.cpp | 1 + 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 4e007e4bd..dcb428794 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -51,12 +51,17 @@ Expression AbsoluteValue::shallowReduce(Context & context, Preferences::ComplexF Expression c = childAtIndex(0); if (c.isReal(context)) { float app = c.node()->approximate(float(), context, complexFormat, angleUnit).toScalar(); - if (!std::isnan(app) && app >= Expression::Epsilon()) { - // abs(a) = a with a > 0 + if (!std::isnan(app) && + ((c.isNumber() && app >= 0) || app >= Expression::Epsilon())) { + /* abs(a) = a with a >= 0 + * To check that a > 0, if a is a number we can use float comparison; + * in other cases, we are more conservative and rather check that + * a > epsilon ~ 1E-7 to avoid potential error due to float precision. */ replaceWithInPlace(c); return c; - } else if (!std::isnan(app) && app <= -Expression::Epsilon()) { - // abs(a) = -a with a < 0 + } else if (!std::isnan(app) && + ((c.isNumber() && app < 0.0f) || app <= -Expression::Epsilon())) { + // abs(a) = -a with a < 0 (same comment as above to check that a < 0) Multiplication m(Rational(-1), c); replaceWithInPlace(m); return m.shallowReduce(context, complexFormat, angleUnit, target); diff --git a/poincare/test/function.cpp b/poincare/test/function.cpp index 73b95289d..74b22c42e 100644 --- a/poincare/test/function.cpp +++ b/poincare/test/function.cpp @@ -244,6 +244,7 @@ QUIZ_CASE(poincare_function_simplify) { assert_parsed_expression_simplify_to("abs(P)", "P"); assert_parsed_expression_simplify_to("abs(-P)", "P"); assert_parsed_expression_simplify_to("abs(1+I)", "R(2)"); + assert_parsed_expression_simplify_to("abs(0)", "0"); assert_parsed_expression_simplify_to("arg(1+I)", "P/4"); assert_parsed_expression_simplify_to("binomial(20,3)", "1140"); assert_parsed_expression_simplify_to("binomial(20,10)", "184756"); From 48bf209f4870cc2afe88a85a091aa636d5fb1eb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 16 Jan 2019 16:40:20 +0100 Subject: [PATCH 255/373] [apps/curve_view] Fix zero label position For instance, in Probability app, draw a standard normal law. The zero was top left of the screen... --- apps/shared/curve_view.cpp | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index 692824078..d60a29130 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -308,6 +308,7 @@ void CurveView::drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOr float xPosition = 0.0f; float yPosition = 0.0f; + bool positioned = false; if (strcmp(labelI, "0") == 0) { if (floatingLabels != FloatingPosition::None) { // Do not draw the zero, it is symbolized by the other axis @@ -316,24 +317,28 @@ void CurveView::drawLabels(KDContext * ctx, KDRect rect, Axis axis, bool shiftOr if (shiftOrigin && floatingLabels == FloatingPosition::None) { xPosition = horizontalCoordinate - k_labelMargin - textSize.width(); yPosition = verticalCoordinate + k_labelMargin; + positioned = true; } - } else if (axis == Axis::Horizontal) { - xPosition = labelPosition - textSize.width()/2; - if (floatingLabels == FloatingPosition::None) { - yPosition = verticalCoordinate + k_labelMargin; - } else if (floatingLabels == FloatingPosition::Min) { - yPosition = k_labelMargin; + } + if (!positioned) { + if (axis == Axis::Horizontal) { + xPosition = labelPosition - textSize.width()/2; + if (floatingLabels == FloatingPosition::None) { + yPosition = verticalCoordinate + k_labelMargin; + } else if (floatingLabels == FloatingPosition::Min) { + yPosition = k_labelMargin; + } else { + yPosition = viewHeight - k_font->glyphSize().height() - k_labelMargin; + } } else { - yPosition = viewHeight - k_font->glyphSize().height() - k_labelMargin; - } - } else { - yPosition = labelPosition - textSize.height()/2; - if (floatingLabels == FloatingPosition::None) { - xPosition = horizontalCoordinate - k_labelMargin - textSize.width(); - } else if (floatingLabels == FloatingPosition::Min) { - xPosition = k_labelMargin; - } else { - xPosition = Ion::Display::Width - textSize.width() - k_labelMargin; + yPosition = labelPosition - textSize.height()/2; + if (floatingLabels == FloatingPosition::None) { + xPosition = horizontalCoordinate - k_labelMargin - textSize.width(); + } else if (floatingLabels == FloatingPosition::Min) { + xPosition = k_labelMargin; + } else { + xPosition = Ion::Display::Width - textSize.width() - k_labelMargin; + } } } KDPoint origin = KDPoint(xPosition, yPosition); From 5e714c371ca2c191325b802060e79a2547f1f0f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 15 Jan 2019 15:57:55 +0100 Subject: [PATCH 256/373] [python/turtle] Increase chances that GC collection works fine on turtle --- python/port/mod/turtle/turtle.h | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/python/port/mod/turtle/turtle.h b/python/port/mod/turtle/turtle.h index 88857fad2..987d73a90 100644 --- a/python/port/mod/turtle/turtle.h +++ b/python/port/mod/turtle/turtle.h @@ -22,6 +22,9 @@ extern "C" { class Turtle { public: constexpr Turtle() : + m_underneathPixelBuffer(nullptr), + m_dotMask(nullptr), + m_dotWorkingPixelBuffer(nullptr), m_x(0), m_y(0), m_heading(0), @@ -31,10 +34,7 @@ public: m_speed(k_defaultSpeed), m_penSize(k_defaultPenSize), m_mileage(0), - m_drawn(false), - m_underneathPixelBuffer(nullptr), - m_dotMask(nullptr), - m_dotWorkingPixelBuffer(nullptr) + m_drawn(false) { } @@ -132,6 +132,14 @@ private: void drawPaw(PawType type, PawPosition position); void erase(); + /* When GC is performed, sTurtle is marked as root for GC collection and its + * data is scanned for pointers that point to the Python heap. We put the 3 + * pointers that should be marked at the beginning of the object to maximize + * the chances they will be correctly aligned and interpreted as pointers. */ + KDColor * m_underneathPixelBuffer; + uint8_t * m_dotMask; + KDColor * m_dotWorkingPixelBuffer; + /* The frame's center is the center of the screen, the x axis goes to the * right and the y axis goes upwards. */ mp_float_t m_x; @@ -149,9 +157,6 @@ private: KDCoordinate m_mileage; bool m_drawn; - KDColor * m_underneathPixelBuffer; - uint8_t * m_dotMask; - KDColor * m_dotWorkingPixelBuffer; }; #endif From 835c112f2f2b8fee21de1fdab9f9f4b0fc7532f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 15 Jan 2019 15:59:12 +0100 Subject: [PATCH 257/373] [python/port] Clean gc_collect --- python/port/port.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/python/port/port.cpp b/python/port/port.cpp index 302427e45..af3ea103c 100644 --- a/python/port/port.cpp +++ b/python/port/port.cpp @@ -138,13 +138,15 @@ void gc_collect(void) { * the case on a computer. We thus have to take the absolute value of the * addresses difference. */ size_t stackLength; + void ** scanStart; if ((uintptr_t)python_stack_top > (uintptr_t)®s) { stackLength = ((uintptr_t)python_stack_top - (uintptr_t)®s) / sizeof(uintptr_t); - gc_collect_root(regs_ptr, stackLength); + scanStart = regs_ptr; } else { stackLength = ((uintptr_t)(®s) - (uintptr_t)python_stack_top) / sizeof(uintptr_t); - gc_collect_root((void **)python_stack_top, stackLength); + scanStart = (void **)python_stack_top; } + gc_collect_root(scanStart, stackLength); gc_collect_end(); } From fdc02ee5e1e8330618cbea389195503dbc6f9906 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 15 Jan 2019 16:14:59 +0100 Subject: [PATCH 258/373] [python/port] Fix size of gc collection --- python/port/port.cpp | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/python/port/port.cpp b/python/port/port.cpp index af3ea103c..6f01f26ca 100644 --- a/python/port/port.cpp +++ b/python/port/port.cpp @@ -2,6 +2,7 @@ #include +#include #include #include #include @@ -140,11 +141,30 @@ void gc_collect(void) { size_t stackLength; void ** scanStart; if ((uintptr_t)python_stack_top > (uintptr_t)®s) { - stackLength = ((uintptr_t)python_stack_top - (uintptr_t)®s) / sizeof(uintptr_t); + + /* To compute the stack length: + * regs + * <-----------> + * STACK -> ...| | | | | |--|--|--|--| | | | | | | + * ^®s ^python_stack_top + * */ + + stackLength = ceil((float)((uintptr_t)python_stack_top - (uintptr_t)®s) / (float)sizeof(uintptr_t)); scanStart = regs_ptr; + } else { - stackLength = ((uintptr_t)(®s) - (uintptr_t)python_stack_top) / sizeof(uintptr_t); + + /* When computing the stack length, take into account regs' size. + * regs + * <-----------> + * STACK -> | | | | | | | | | | | |--|--|--|--| | | |... + * ^python_stack_top ^®s + * */ + + size_t sizeOfRegs = ceil(((float)sizeof(regs))/(float)sizeof(uintptr_t)); + stackLength = (size_t)ceil(((float)((uintptr_t)(®s) - (uintptr_t)python_stack_top)) / (float)sizeof(uintptr_t)) + sizeOfRegs; scanStart = (void **)python_stack_top; + } gc_collect_root(scanStart, stackLength); From c7a585cae8bcf7b3fd090e21dcb55ca03452fc4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 15 Jan 2019 16:03:25 +0100 Subject: [PATCH 259/373] [micropython] Fix GC bug --- python/src/py/gc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/src/py/gc.c b/python/src/py/gc.c index 84c9918fd..5b5088920 100644 --- a/python/src/py/gc.c +++ b/python/src/py/gc.c @@ -444,7 +444,7 @@ void *gc_alloc(size_t n_bytes, bool has_finaliser) { size_t i; size_t end_block; size_t start_block; - size_t n_free = 0; + size_t n_free; int collected = !MP_STATE_MEM(gc_auto_collect_enabled); #if MICROPY_GC_ALLOC_THRESHOLD @@ -456,7 +456,7 @@ void *gc_alloc(size_t n_bytes, bool has_finaliser) { #endif for (;;) { - + n_free = 0; // Fixes bug, should be written in the next MicroPython version // look for a run of n_blocks available blocks for (i = MP_STATE_MEM(gc_last_free_atb_index); i < MP_STATE_MEM(gc_alloc_table_byte_len); i++) { byte a = MP_STATE_MEM(gc_alloc_table_start)[i]; From 0a5290d5a680014557c362b81fb87b896f105a7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 14 Jan 2019 14:00:55 +0100 Subject: [PATCH 260/373] [apps/code] Fix MenuController::willExitResponderChain It called textFieldDidAbortEditing, which called setFirstResponder, which could clash with another setFirstResponder higher in the call tree. Scenario: build with an update popup, create a new script, edit its name with an unvalid name and press the Power key while editing. When powering on the device again, the first responder is not the popup even though it is displayed, and pressing OK does not dismiss it. --- apps/code/menu_controller.cpp | 65 +++++++++++++++++++---------------- apps/code/menu_controller.h | 5 ++- 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/apps/code/menu_controller.cpp b/apps/code/menu_controller.cpp index 1c8e3823d..e7e04a8d4 100644 --- a/apps/code/menu_controller.cpp +++ b/apps/code/menu_controller.cpp @@ -49,7 +49,7 @@ void MenuController::willExitResponderChain(Responder * nextFirstResponder) { TextField * tf = static_cast(m_selectableTableView.selectedCell())->textField(); if (tf->isEditing()) { tf->setEditing(false, false); - textFieldDidAbortEditing(tf); + privateTextFieldDidAbortEditing(tf, false); } } } @@ -346,34 +346,6 @@ bool MenuController::textFieldDidFinishEditing(TextField * textField, const char return false; } -bool MenuController::textFieldDidAbortEditing(TextField * textField) { - Script script = m_scriptStore->scriptAtIndex(m_selectableTableView.selectedRow()); - const char * scriptName = script.fullName(); - if (strlen(scriptName) <= 1 + strlen(ScriptStore::k_scriptExtension)) { - // The previous text was an empty name. Use a numbered default script name. - char numberedDefaultName[Script::k_defaultScriptNameMaxSize]; - bool foundDefaultName = Script::DefaultName(numberedDefaultName, Script::k_defaultScriptNameMaxSize); - if (!foundDefaultName) { - // If we did not find a default name, delete the script - deleteScript(script); - return true; - } - Script::ErrorStatus error = script.setBaseNameWithExtension(numberedDefaultName, ScriptStore::k_scriptExtension); - scriptName = m_scriptStore->scriptAtIndex(m_selectableTableView.selectedRow()).fullName(); - /* Because we use the numbered default name, the name should not be - * already taken. Plus, the script could be added only if the storage has - * enough available space to add a script named 'script99.py' */ - (void) error; // Silence the "variable unused" warning if assertions are not enabled - assert(error == Script::ErrorStatus::None); - updateAddScriptRowDisplay(); - } - textField->setText(scriptName); - m_selectableTableView.selectCellAtLocation(m_selectableTableView.selectedColumn(), m_selectableTableView.selectedRow()); - app()->setFirstResponder(&m_selectableTableView); - static_cast(const_cast(app()->container()))->setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::Default); - return true; -} - bool MenuController::textFieldDidHandleEvent(TextField * textField, bool returnValue, bool textSizeDidChange) { int scriptExtensionLength = 1 + strlen(ScriptStore::k_scriptExtension); if (textField->isEditing() && textField->cursorLocation() > textField->draftTextLength() - scriptExtensionLength) { @@ -411,4 +383,39 @@ void MenuController::updateAddScriptRowDisplay() { m_selectableTableView.reloadData(); } +bool MenuController::privateTextFieldDidAbortEditing(TextField * textField, bool menuControllerStaysInResponderChain) { + /* If menuControllerStaysInResponderChain is false, we do not want to use + * methods that might call setFirstResponder, because we might be in the + * middle of another setFirstResponder call. */ + Script script = m_scriptStore->scriptAtIndex(m_selectableTableView.selectedRow()); + const char * scriptName = script.fullName(); + if (strlen(scriptName) <= 1 + strlen(ScriptStore::k_scriptExtension)) { + // The previous text was an empty name. Use a numbered default script name. + char numberedDefaultName[Script::k_defaultScriptNameMaxSize]; + bool foundDefaultName = Script::DefaultName(numberedDefaultName, Script::k_defaultScriptNameMaxSize); + if (!foundDefaultName) { + // If we did not find a default name, delete the script + deleteScript(script); + return true; + } + Script::ErrorStatus error = script.setBaseNameWithExtension(numberedDefaultName, ScriptStore::k_scriptExtension); + scriptName = m_scriptStore->scriptAtIndex(m_selectableTableView.selectedRow()).fullName(); + /* Because we use the numbered default name, the name should not be + * already taken. Plus, the script could be added only if the storage has + * enough available space to add a script named 'script99.py' */ + (void) error; // Silence the "variable unused" warning if assertions are not enabled + assert(error == Script::ErrorStatus::None); + if (menuControllerStaysInResponderChain) { + updateAddScriptRowDisplay(); + } + } + textField->setText(scriptName); + if (menuControllerStaysInResponderChain) { + m_selectableTableView.selectCellAtLocation(m_selectableTableView.selectedColumn(), m_selectableTableView.selectedRow()); + app()->setFirstResponder(&m_selectableTableView); + } + static_cast(const_cast(app()->container()))->setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::Default); + return true; +} + } diff --git a/apps/code/menu_controller.h b/apps/code/menu_controller.h index b4383549f..7b94014f4 100644 --- a/apps/code/menu_controller.h +++ b/apps/code/menu_controller.h @@ -52,7 +52,9 @@ public: bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override; bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override; bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override; - bool textFieldDidAbortEditing(TextField * textField) override; + bool textFieldDidAbortEditing(TextField * textField) override { + return privateTextFieldDidAbortEditing(textField, true); + } bool textFieldDidHandleEvent(TextField * textField, bool returnValue, bool textSizeDidChange) override; /* ButtonRowDelegate */ @@ -74,6 +76,7 @@ private: void editScriptAtIndex(int scriptIndex); void numberedDefaultScriptName(char * buffer); void updateAddScriptRowDisplay(); + bool privateTextFieldDidAbortEditing(TextField * textField, bool menuControllerStaysInResponderChain); ScriptStore * m_scriptStore; ScriptNameCell m_scriptCells[k_maxNumberOfDisplayableScriptCells]; EvenOddCellWithEllipsis m_scriptParameterCells[k_maxNumberOfDisplayableScriptCells]; From b97873473bab250b88f73bec307bbaffc93c6973 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 21 Jan 2019 16:18:51 +0100 Subject: [PATCH 261/373] [poincare] Clearer variable names in Gauss-Kronrod algorithm --- poincare/src/integral.cpp | 73 ++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/poincare/src/integral.cpp b/poincare/src/integral.cpp index 299eccf44..77e59259f 100644 --- a/poincare/src/integral.cpp +++ b/poincare/src/integral.cpp @@ -113,72 +113,81 @@ IntegralNode::DetailedResult IntegralNode::kronrodGaussQuadrature(T a, T b, C static T max = sizeof(T) == sizeof(double) ? DBL_MAX : FLT_MAX; /* We here use Kronrod-Legendre quadrature with n = 21 * The abscissa and weights are taken from QUADPACK library. */ - const static T wg[5]= {0.066671344308688137593568809893332, 0.149451349150580593145776339657697, - 0.219086362515982043995534934228163, 0.269266719309996355091226921569469, 0.295524224714752870173892994651338}; - const static T xgk[11]= {0.995657163025808080735527280689003, 0.973906528517171720077964012084452, + + // Abscissae for the gauss (odd weights) and kronrod rules (all weights) + const static T x[11]= {0.995657163025808080735527280689003, 0.973906528517171720077964012084452, 0.930157491355708226001207180059508, 0.865063366688984510732096688423493, 0.780817726586416897063717578345042, 0.679409568299024406234327365114874, 0.562757134668604683339000099272694, 0.433395394129247190799265943165784, 0.294392862701460198131126603103866, 0.148874338981631210884826001129720, 0.000000000000000000000000000000000}; - const static T wgk[11]= {0.011694638867371874278064396062192, 0.032558162307964727478818972459390, + + // Weights for the gauss integral + const static T wGauss[5]= {0.066671344308688137593568809893332, 0.149451349150580593145776339657697, + 0.219086362515982043995534934228163, 0.269266719309996355091226921569469, 0.295524224714752870173892994651338}; + + // Weights for the kronrod rule + const static T wKronrod[11]= {0.011694638867371874278064396062192, 0.032558162307964727478818972459390, 0.054755896574351996031381300244580, 0.075039674810919952767043140916190, 0.093125454583697605535065465083366, 0.109387158802297641899210590325805, 0.123491976262065851077958109831074, 0.134709217311473325928054001771707, 0.142775938577060080797094273138717, 0.147739104901338491374841515972068, 0.149445554002916905664936468389821}; + T fv1[10]; T fv2[10]; - T centr = 0.5*(a+b); - T hlgth = 0.5*(b-a); - T dhlgth = std::fabs(hlgth); + T center = 0.5 * (a+b); + T halfLength = 0.5 * (b-a); + T absHalfLength = std::fabs(halfLength); DetailedResult errorResult; errorResult.integral = NAN; errorResult.absoluteError = 0; - T resg = 0; - T fc = functionValueAtAbscissa(centr, context, complexFormat, angleUnit); - if (std::isnan(fc)) { + T gaussIntegral = 0; + T fCenter = functionValueAtAbscissa(center, context, complexFormat, angleUnit); + if (std::isnan(fCenter)) { return errorResult; } - T resk = wgk[10]*fc; - T resabs = std::fabs(resk); + T kronrodIntegral = wKronrod[10] * fCenter; + T absKronrodIntegral = std::fabs(kronrodIntegral); for (int j = 0; j < 10; j++) { - T absc = hlgth*xgk[j]; - T fval1 = functionValueAtAbscissa(centr-absc, context, complexFormat, angleUnit); + T xDelta = halfLength * x[j]; + T fval1 = functionValueAtAbscissa(center - xDelta, context, complexFormat, angleUnit); if (std::isnan(fval1)) { return errorResult; } - T fval2 = functionValueAtAbscissa(centr+absc, context, complexFormat, angleUnit); + T fval2 = functionValueAtAbscissa(center + xDelta, context, complexFormat, angleUnit); if (std::isnan(fval2)) { return errorResult; } fv1[j] = fval1; fv2[j] = fval2; - T fsum = fval1+fval2; - if (j%2 == 1) { - resg += wg[j/2]*fsum; + T fsum = fval1 + fval2; + if (j % 2 == 1) { + gaussIntegral += wGauss[j/2] * fsum; } - resk += wgk[j]*fsum; - resabs += wgk[j]*(std::fabs(fval1)+std::fabs(fval2)); + kronrodIntegral += wKronrod[j] * fsum; + absKronrodIntegral += wKronrod[j] * (std::fabs(fval1) + std::fabs(fval2)); } - T reskh = resk*0.5; - T resasc = wgk[10]*std::fabs(fc-reskh); + T halfKronrodIntegral = 0.5 * kronrodIntegral; + T kronrodIntegralDifference = wKronrod[10] * std::fabs(fCenter - halfKronrodIntegral); for (int j = 0; j < 10; j++) { - resasc += wgk[j]*(std::fabs(fv1[j]-reskh)+std::fabs(fv2[j]-reskh)); + kronrodIntegralDifference += wKronrod[j] * (std::fabs(fv1[j] - halfKronrodIntegral) + std::fabs(fv2[j] - halfKronrodIntegral)); } - T integral = resk*hlgth; - resabs = resabs*dhlgth; - resasc = resasc*dhlgth; - T abserr = std::fabs((resk-resg)*hlgth); - if (resasc != 0 && abserr != 0) { - abserr = 1 > std::pow((T)(200*abserr/resasc), (T)1.5)? resasc*std::pow((T)(200*abserr/resasc), (T)1.5) : resasc; + T integral = kronrodIntegral * halfLength; + absKronrodIntegral = absKronrodIntegral * absHalfLength; + kronrodIntegralDifference = kronrodIntegralDifference * absHalfLength; + T absError = std::fabs((kronrodIntegral - gaussIntegral) * halfLength); + if (kronrodIntegralDifference != 0 && absError != 0) { + T errorCoefficient = std::pow((T)(200*absError/kronrodIntegralDifference), (T)1.5); + absError = 1 > errorCoefficient ? kronrodIntegralDifference * errorCoefficient : kronrodIntegralDifference; } - if (resabs > max/(50.0*epsilon)) { - abserr = abserr > epsilon*50*resabs ? abserr : epsilon*50*resabs; + if (absKronrodIntegral > max/(50.0 * epsilon)) { + T minError = epsilon * 50 * absKronrodIntegral; + absError = absError > minError ? absError : minError; } DetailedResult result; result.integral = integral; - result.absoluteError = abserr; + result.absoluteError = absError; return result; } From 7558d08770461f721466c514075b7d739f93f433 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 21 Jan 2019 15:46:21 +0100 Subject: [PATCH 262/373] [poincarE] Fix compilation warning --- poincare/src/nth_root.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index e0d5360dc..e570abd7e 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -53,7 +53,7 @@ Evaluation NthRootNode::templatedApproximate(Context& context, Preferences::C // compute root(|x|, q) Complex absBasePowIndex = PowerNode::compute(absBasec, std::complex(1.0)/(indexc), complexFormat); // q odd if (-1)^q = -1 - if (std::pow(-1.0, indexc.real()) < 0.0) { + if (std::pow((T)-1.0, (T)indexc.real()) < 0.0) { return basec.real() < 0 ? Complex(-absBasePowIndex.stdComplex()) : absBasePowIndex; } } From 21fcc84df03b87522b0197c2e716dbbb867ef8dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 22 Jan 2019 14:20:23 +0100 Subject: [PATCH 263/373] [poincare/parsing] Avoid invalid read (valgrind) --- poincare/src/parsing/parser.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/poincare/src/parsing/parser.cpp b/poincare/src/parsing/parser.cpp index 1b493dea2..26eb10d01 100644 --- a/poincare/src/parsing/parser.cpp +++ b/poincare/src/parsing/parser.cpp @@ -361,10 +361,10 @@ void Parser::parseSequence(Expression & leftHandSide, const char name, Token::Ty } else if (!popTokenIfType(rightDelimiter)) { m_status = Status::Error; // Right delimiter missing. } else if (rank.isIdenticalTo(Symbol("n",1))) { - char sym[4] = {name, '(', 'n', ')'}; + char sym[5] = {name, '(', 'n', ')', 0}; leftHandSide = Symbol(sym, 4); } else if (rank.isIdenticalTo(Addition(Symbol("n",1),Rational("1")))) { - char sym[6] = {name, '(', 'n', '+', '1', ')'}; + char sym[7] = {name, '(', 'n', '+', '1', ')', 0}; leftHandSide = Symbol(sym, 6); } else { m_status = Status::Error; // Unexpected parameter. From 5abb05e7bc9f4725b0cc3f4b4ed6fedfb8d6d5ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 21 Jan 2019 17:54:11 +0100 Subject: [PATCH 264/373] [poincare] Store: implementation of deepReduceChildren should recursively test that the children are not matrix (or enable the interruption flag) --- poincare/src/store.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index a38327460..52b17fac4 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -16,6 +16,10 @@ extern "C" { namespace Poincare { void StoreNode::deepReduceChildren(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + // Interrupt simplification if the expression stored contains a matrix + if (Expression(childAtIndex(0)).recursivelyMatches([](const Expression e, Context & context, bool replaceSymbols) { return Expression::IsMatrix(e, context, replaceSymbols); }, context, true)) { + Expression::SetInterruption(true); + } return; } From fd2eb95ae7818244a02256a5d84cf08d2777d490 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 22 Jan 2019 10:30:17 +0100 Subject: [PATCH 265/373] [poincare] Fix tests on user variables --- poincare/test/user_variable.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/poincare/test/user_variable.cpp b/poincare/test/user_variable.cpp index 9814cc638..7e7ba4490 100644 --- a/poincare/test/user_variable.cpp +++ b/poincare/test/user_variable.cpp @@ -183,7 +183,10 @@ QUIZ_CASE(poincare_user_variable_properties) { quiz_assert(Symbol('a').isApproximate(context)); quiz_assert(Poincare::Expression::IsMatrix(Symbol('a'), context, true)); - parse_and_simplify("[[x]]>f(x)"); + /* [[x]]->f(x) expression contains a matrix, so its simplification is going + * to be interrupted. We thus rather approximate it instead of simplifying it. + * TODO: use parse_and_simplify when matrix are simplified. */ + assert_parsed_expression_evaluates_to("[[x]]>f(x)", "[[undef]]"); quiz_assert(Function("f", 1, Rational(2)).isApproximate(context)); quiz_assert(Poincare::Expression::IsMatrix(Function("f", 1, Symbol('x')), context, true)); From 476c42c42e97ef647d7a739839acb602b3a761be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 22 Jan 2019 10:30:35 +0100 Subject: [PATCH 266/373] [poincare] Store: shallowReducing and approximating a store do the same thing: storing the expression for the corresponding symbol --- poincare/include/poincare/store.h | 4 +++ poincare/src/store.cpp | 55 ++++++++++++++++--------------- 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/poincare/include/poincare/store.h b/poincare/include/poincare/store.h index 2efa3013b..b4c9e61a5 100644 --- a/poincare/include/poincare/store.h +++ b/poincare/include/poincare/store.h @@ -37,6 +37,7 @@ private: }; class Store final : public Expression { +friend class StoreNode; public: Store(const StoreNode * n) : Expression(n) {} Store(Expression value, SymbolAbstract symbol) : Expression(TreePool::sharedPool()->createTreeNode()) { @@ -56,6 +57,9 @@ public: // Expression Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); +private: + Expression storeValueForSymbol(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; + StoreNode * node() const { return static_cast(Expression::node()); } }; } diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index 52b17fac4..7039a3fd9 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -44,17 +44,32 @@ Evaluation StoreNode::templatedApproximate(Context& context, Preferences::Com /* If we are here, it means that the store node was not shallowReduced. * Otherwise, it would have been replaced by its symbol. We thus have to * setExpressionForSymbol. */ - Store s(this); - assert(!s.value().isUninitialized()); - context.setExpressionForSymbol(s.value(), s.symbol(), context); - Expression e = context.expressionForSymbol(s.symbol(), false); - if (e.isUninitialized()) { - return Complex::Undefined(); - } - return e.node()->approximate(T(), context, complexFormat, angleUnit); + Expression storedExpression = Store(this).storeValueForSymbol(context, complexFormat, angleUnit); + assert(!storedExpression.isUninitialized()); + return storedExpression.node()->approximate(T(), context, complexFormat, angleUnit); } Expression Store::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + Expression storedExpression = storeValueForSymbol(context, complexFormat, angleUnit); + + /* We want to replace the store with its reduced left side. If the + * simplification of the left side failed, just replace with the left side of + * the store without simplifying it. + * The simplification fails for [x]->d(x) for instance, because we do not + * have exact simplification of matrices yet. */ + bool interruptedSimplification = SimplificationHasBeenInterrupted(); + Expression reducedE = storedExpression.clone().deepReduce(context, complexFormat, angleUnit, target); + if (!reducedE.isUninitialized() && !SimplificationHasBeenInterrupted()) { + storedExpression = reducedE; + } + // Restore the previous interruption flag + SetInterruption(interruptedSimplification); + + replaceWithInPlace(storedExpression); + return storedExpression; +} + +Expression Store::storeValueForSymbol(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { Expression finalValue; if (symbol().type() == ExpressionNode::Type::Function) { // In tata + 2 ->f(tata), replace tata with xUnknown symbol @@ -68,8 +83,9 @@ Expression Store::shallowReduce(Context & context, Preferences::ComplexFormat co } assert(!finalValue.isUninitialized()); context.setExpressionForSymbol(finalValue, symbol(), context); - Expression e = context.expressionForSymbol(symbol(), true); - if (e.isUninitialized()) { + Expression storedExpression = context.expressionForSymbol(symbol(), true); + + if (storedExpression.isUninitialized()) { return Undefined(); } if (symbol().type() == ExpressionNode::Type::Function) { @@ -77,24 +93,9 @@ Expression Store::shallowReduce(Context & context, Preferences::ComplexFormat co assert(symbol().childAtIndex(0).type() == ExpressionNode::Type::Symbol); Expression userDefinedUnknown = symbol().childAtIndex(0); Symbol xUnknown = Symbol(Symbol::SpecialSymbols::UnknownX); - e = e.replaceSymbolWithExpression(xUnknown, static_cast(userDefinedUnknown)); + storedExpression = storedExpression.replaceSymbolWithExpression(xUnknown, static_cast(userDefinedUnknown)); } - - /* We want to replace the store with its reduced left side. If the - * simplification of the left side failed, just replace with the left side of - * the store without simplifying it. - * The simplification fails for [x]->d(x) for instance, because we do not - * have exact simplification of matrices yet. */ - bool interruptedSimplification = SimplificationHasBeenInterrupted(); - Expression reducedE = e.clone().deepReduce(context, complexFormat, angleUnit, target); - if (!reducedE.isUninitialized() && !SimplificationHasBeenInterrupted()) { - e = reducedE; - } - // Restore the previous interruption flag - SetInterruption(interruptedSimplification); - - replaceWithInPlace(e); - return e; + return storedExpression; } } From 4128ebb8642cb1b3b262606d1ccc5fa77b16d1cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 21 Jan 2019 15:13:39 +0100 Subject: [PATCH 267/373] [escher] In container, check the app can be exited before switching apps --- apps/apps_container.cpp | 1 - escher/src/container.cpp | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index 9963aaa24..bd738d3f6 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -223,7 +223,6 @@ bool AppsContainer::processEvent(Ion::Events::Event event) { } void AppsContainer::switchTo(App::Snapshot * snapshot) { - assert(activeApp() == nullptr || activeApp()->prepareForExit()); if (activeApp() && snapshot != activeApp()->snapshot()) { resetShiftAlphaStatus(); } diff --git a/escher/src/container.cpp b/escher/src/container.cpp index 136ffb2f4..597bc4875 100644 --- a/escher/src/container.cpp +++ b/escher/src/container.cpp @@ -17,6 +17,11 @@ void Container::switchTo(App::Snapshot * snapshot) { if (m_activeApp && snapshot == m_activeApp->snapshot()) { return; } + if (m_activeApp && !m_activeApp->prepareForExit()) { + /* activeApp()->prepareForExit() returned false, which means that the app + * needs another event loop to prepare for being switched off. */ + return; + } if (m_activeApp) { m_activeApp->willBecomeInactive(); m_activeApp->snapshot()->pack(m_activeApp); From a7208ade0f6e87f24271047ce3d1ee57c1b82dfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 21 Jan 2019 15:33:32 +0100 Subject: [PATCH 268/373] [apps] Container::switchTo returns a bool (false if could not switch) --- apps/apps_container.cpp | 30 +++++++++++++----------- apps/apps_container.h | 2 +- apps/hardware_test/pop_up_controller.cpp | 4 +++- apps/home/controller.cpp | 4 +++- apps/on_boarding/pop_up_controller.cpp | 4 +++- escher/include/escher/container.h | 2 +- escher/src/container.cpp | 7 +++--- 7 files changed, 31 insertions(+), 22 deletions(-) diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index bd738d3f6..d5dd6ad98 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -152,18 +152,19 @@ bool AppsContainer::dispatchEvent(Ion::Events::Event event) { if (event == Ion::Events::USBEnumeration) { if (Ion::USB::isPlugged()) { App::Snapshot * activeSnapshot = (activeApp() == nullptr ? appSnapshotAtIndex(0) : activeApp()->snapshot()); - if (activeApp() == nullptr || activeApp()->prepareForExit()) { + if (switchTo(usbConnectedAppSnapshot())) { /* Just after a software update, the battery timer does not have time to * fire before the calculator enters DFU mode. As the DFU mode blocks the * event loop, we update the battery state "manually" here. */ updateBatteryState(); - switchTo(usbConnectedAppSnapshot()); Ion::USB::DFU(); - switchTo(activeSnapshot); + bool switched = switchTo(activeSnapshot); + assert(switched); + (void) switched; // Silence compilation warning about unused variable. didProcessEvent = true; } else { - /* activeApp()->prepareForExit() returned false, which means that the - * app needs another event loop to prepare for being switched off. + /* We could not switch apps, which means that the current app needs + * another event loop to prepare for being switched off. * Discard the current enumeration interruption. * The USB host tries a few times in a row to enumerate the device, so * hopefully the device will get another enumeration event soon and this @@ -222,7 +223,7 @@ bool AppsContainer::processEvent(Ion::Events::Event event) { return false; } -void AppsContainer::switchTo(App::Snapshot * snapshot) { +bool AppsContainer::switchTo(App::Snapshot * snapshot) { if (activeApp() && snapshot != activeApp()->snapshot()) { resetShiftAlphaStatus(); } @@ -234,7 +235,7 @@ void AppsContainer::switchTo(App::Snapshot * snapshot) { if (snapshot) { m_window.setTitle(snapshot->descriptor()->upperName()); } - Container::switchTo(snapshot); + return Container::switchTo(snapshot); } void AppsContainer::run() { @@ -251,15 +252,14 @@ void AppsContainer::run() { /* Normal execution. The exception checkpoint must be created before * switching to the first app, because the first app might create nodes on * the pool. */ + bool switched = #if EPSILON_ONBOARDING_APP - switchTo(onBoardingAppSnapshot()); + switchTo(onBoardingAppSnapshot()); #else - if (numberOfApps() == 2) { - switchTo(appSnapshotAtIndex(1)); - } else { - switchTo(appSnapshotAtIndex(0)); - } + switchTo(appSnapshotAtIndex(numberOfApps() == 2 ? 1 : 0)); #endif + assert(switched); + (void) switched; // Silence compilation warning about unused variable. } else { // Exception if (activeApp() != nullptr) { @@ -276,7 +276,9 @@ void AppsContainer::run() { * history here, we will be stuck outside the calculation app. */ activeApp()->snapshot()->reset(); } - switchTo(appSnapshotAtIndex(0)); + bool switched = switchTo(appSnapshotAtIndex(0)); + assert(switched); + (void) switched; // Silence compilation warning about unused variable. Poincare::Tidy(); activeApp()->displayWarning(I18n::Message::PoolMemoryFull1, I18n::Message::PoolMemoryFull2, true); } diff --git a/apps/apps_container.h b/apps/apps_container.h index afa3ef224..cda82c429 100644 --- a/apps/apps_container.h +++ b/apps/apps_container.h @@ -42,7 +42,7 @@ public: VariableBoxController * variableBoxController(); void suspend(bool checkIfPowerKeyReleased = false); virtual bool dispatchEvent(Ion::Events::Event event) override; - void switchTo(App::Snapshot * snapshot) override; + bool switchTo(App::Snapshot * snapshot) override; void run() override; bool updateBatteryState(); void refreshPreferences(); diff --git a/apps/hardware_test/pop_up_controller.cpp b/apps/hardware_test/pop_up_controller.cpp index 92905900c..60b385232 100644 --- a/apps/hardware_test/pop_up_controller.cpp +++ b/apps/hardware_test/pop_up_controller.cpp @@ -41,7 +41,9 @@ PopUpController::ContentView::ContentView(Responder * parentResponder) : m_okButton(this, I18n::Message::Ok, Invocation([](void * context, void * sender) { PopUpController::ContentView * view = (PopUpController::ContentView *)context; AppsContainer * appsContainer = (AppsContainer *)view->app()->container(); - appsContainer->switchTo(appsContainer->hardwareTestAppSnapshot()); + bool switched = appsContainer->switchTo(appsContainer->hardwareTestAppSnapshot()); + assert(switched); + (void) switched; // Silence compilation warning about unused variable. return true; }, this), KDFont::SmallFont), m_warningTextView(KDFont::SmallFont, I18n::Message::Warning, 0.5, 0.5, KDColorWhite, KDColorBlack), diff --git a/apps/home/controller.cpp b/apps/home/controller.cpp index 37857cb24..aa99eb587 100644 --- a/apps/home/controller.cpp +++ b/apps/home/controller.cpp @@ -58,7 +58,9 @@ Controller::Controller(Responder * parentResponder, ::AppsContainer * container, bool Controller::handleEvent(Ion::Events::Event event) { if (event == Ion::Events::OK || event == Ion::Events::EXE) { - m_container->switchTo(m_container->appSnapshotAtIndex(m_selectionDataSource->selectedRow()*k_numberOfColumns+m_selectionDataSource->selectedColumn()+1)); + bool switched = m_container->switchTo(m_container->appSnapshotAtIndex(m_selectionDataSource->selectedRow()*k_numberOfColumns+m_selectionDataSource->selectedColumn()+1)); + assert(switched); + (void) switched; // Silence compilation warning about unused variable. return true; } diff --git a/apps/on_boarding/pop_up_controller.cpp b/apps/on_boarding/pop_up_controller.cpp index ccc1e84e6..d9596863b 100644 --- a/apps/on_boarding/pop_up_controller.cpp +++ b/apps/on_boarding/pop_up_controller.cpp @@ -55,7 +55,9 @@ bool PopUpController::handleEvent(Ion::Events::Event event) { app()->dismissModalViewController(); AppsContainer * appsContainer = (AppsContainer *)app()->container(); if (appsContainer->activeApp()->snapshot() == appsContainer->onBoardingAppSnapshot()) { - appsContainer->switchTo(appsContainer->appSnapshotAtIndex(0)); + bool switched = appsContainer->switchTo(appsContainer->appSnapshotAtIndex(0)); + assert(switched); + (void) switched; // Silence compilation warning about unused variable. } return true; } diff --git a/escher/include/escher/container.h b/escher/include/escher/container.h index 8857c59bc..e4f33604e 100644 --- a/escher/include/escher/container.h +++ b/escher/include/escher/container.h @@ -27,7 +27,7 @@ public: virtual void run(); App * activeApp(); virtual bool dispatchEvent(Ion::Events::Event event) override; - virtual void switchTo(App::Snapshot * snapshot); + virtual bool switchTo(App::Snapshot * snapshot); protected: virtual Window * window() = 0; private: diff --git a/escher/src/container.cpp b/escher/src/container.cpp index 597bc4875..fd92857a4 100644 --- a/escher/src/container.cpp +++ b/escher/src/container.cpp @@ -13,14 +13,14 @@ Container::~Container() { } } -void Container::switchTo(App::Snapshot * snapshot) { +bool Container::switchTo(App::Snapshot * snapshot) { if (m_activeApp && snapshot == m_activeApp->snapshot()) { - return; + return true; } if (m_activeApp && !m_activeApp->prepareForExit()) { /* activeApp()->prepareForExit() returned false, which means that the app * needs another event loop to prepare for being switched off. */ - return; + return false; } if (m_activeApp) { m_activeApp->willBecomeInactive(); @@ -34,6 +34,7 @@ void Container::switchTo(App::Snapshot * snapshot) { m_activeApp->didBecomeActive(window()); window()->redraw(); } + return true; } App * Container::activeApp() { From 66fe9baa7d9e1c92c672ba4d296bff45a8a306f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 23 Jan 2019 14:33:12 +0100 Subject: [PATCH 269/373] [ion] Storage: clean implementation (do not re-code strlen) --- ion/src/shared/storage.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ion/src/shared/storage.cpp b/ion/src/shared/storage.cpp index 66b303843..b08ccc900 100644 --- a/ion/src/shared/storage.cpp +++ b/ion/src/shared/storage.cpp @@ -360,10 +360,8 @@ const char * Storage::fullNameOfRecordStarting(char * start) const { const void * Storage::valueOfRecordStarting(char * start) const { char * currentChar = start+sizeof(record_size_t); - while (*currentChar != 0) { - currentChar++; - } - return currentChar+1; + size_t fullNameLength = strlen(currentChar); + return currentChar+fullNameLength+1; } size_t Storage::overrideSizeAtPosition(char * position, record_size_t size) { From b58573bad33822817ee1b89a3968fb91622f32cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 31 Jan 2019 11:23:19 +0100 Subject: [PATCH 270/373] [poincare] Multiplication: do not apply rule 0*x --> 0 if x involves an infinite expression --- poincare/src/multiplication.cpp | 17 ++++++++++++++--- poincare/test/infinity.cpp | 2 ++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 5a2722981..0e01b53a4 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -434,13 +434,24 @@ Expression Multiplication::privateShallowReduce(Context & context, Preferences:: /* Step 5: If the first child is zero, the multiplication result is zero. We * do this after merging the rational children, because the merge takes care - * of turning 0*inf into undef. + * of turning 0*inf into undef. We still have to check that no other child + * involves an inifity expression to avoid reducing 0*e^(inf) to 0. * If the first child is 1, we remove it if there are other children. */ { const Expression c = childAtIndex(0); if (c.type() == ExpressionNode::Type::Rational && static_cast(c).isZero()) { - replaceWithInPlace(c); - return c; + // Check that other children don't match inf + bool infiniteFactor = false; + for (int i = 1; i < numberOfChildren(); i++) { + infiniteFactor = childAtIndex(i).recursivelyMatches([](const Expression e, Context & context, bool replaceSymbols) { return e.type() == ExpressionNode::Type::Infinity; }, context, true); + if (infiniteFactor) { + break; + } + } + if (!infiniteFactor) { + replaceWithInPlace(c); + return c; + } } if (c.type() == ExpressionNode::Type::Rational && static_cast(c).isOne() && numberOfChildren() > 1) { removeChildAtIndexInPlace(0); diff --git a/poincare/test/infinity.cpp b/poincare/test/infinity.cpp index aff3038ba..9eacc7a90 100644 --- a/poincare/test/infinity.cpp +++ b/poincare/test/infinity.cpp @@ -34,5 +34,7 @@ QUIZ_CASE(poincare_infinity) { assert_parsed_expression_simplify_to("(-inf)^R(2)", "inf*(-1)^R(2)"); assert_parsed_expression_simplify_to("inf^x", "inf^x"); assert_parsed_expression_simplify_to("1/inf+24", "24"); + assert_parsed_expression_simplify_to("X^(inf)/inf", "0*X^inf"); + assert_parsed_expression_simplify_to("ln(inf)*0", "0*ln(inf)"); } From 3226426a55e6ea843c6a72d4b66a833d95546d75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 31 Jan 2019 13:28:26 +0100 Subject: [PATCH 271/373] [poincare] Fix Logarithm with Infinite arguments --- poincare/src/logarithm.cpp | 31 +++++++++++++++++++++---------- poincare/test/infinity.cpp | 11 ++++++++++- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 2f773a16a..2ee184e6e 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -135,6 +135,7 @@ Expression Logarithm::shallowReduce(Context & context, Preferences::ComplexForma * information on the parent which could later be a power of b. */ bool letLogAtRoot = parentIsAPowerOfSameBase(); + // log(x^y, b)->y*log(x, b) if x>0 if (!letLogAtRoot && c.type() == ExpressionNode::Type::Power && c.childAtIndex(0).sign(&context) == ExpressionNode::Sign::Positive) { Power p = static_cast(c); @@ -190,37 +191,47 @@ Expression Logarithm::shallowReduce(Context & context, Preferences::ComplexForma Expression Logarithm::simpleShallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { Expression c = childAtIndex(0); + Expression b = childAtIndex(1); // log(0,0)->Undefined - if (c.type() == ExpressionNode::Type::Rational && childAtIndex(1).type() == ExpressionNode::Type::Rational && childAtIndex(1).convert().isZero() && static_cast(c).isZero()) { + if (c.type() == ExpressionNode::Type::Rational && b.type() == ExpressionNode::Type::Rational && static_cast(b).isZero() && static_cast(c).isZero()) { Expression result = Undefined(); replaceWithInPlace(result); return result; } // log(x,1)->Undefined - if (childAtIndex(1).type() == ExpressionNode::Type::Rational && childAtIndex(1).convert().isOne()) { + if (b.type() == ExpressionNode::Type::Rational && static_cast(b).isOne()) { Expression result = Undefined(); replaceWithInPlace(result); return result; } - // log(x,x)->1 - if (c.isIdenticalTo(childAtIndex(1))) { - Expression result = Rational(1); + bool infiniteArg = c.recursivelyMatches([](const Expression e, Context & context, bool replaceSymbols) { return e.type() == ExpressionNode::Type::Infinity; }, context, true); + // log(x,x)->1 with x != inf and log(inf,inf) = undef + if (c.isIdenticalTo(b)) { + Expression result = infiniteArg ? Undefined().convert() : Rational(1).convert(); replaceWithInPlace(result); return result; } - // log(x,0)->0 - if (childAtIndex(1).type() == ExpressionNode::Type::Rational && childAtIndex(1).convert().isZero()) { - Expression result = Rational(0); + // log(x,0)->0 with x != inf and log(inf,0) = undef + if (b.type() == ExpressionNode::Type::Rational && static_cast(b).isZero()) { + Expression result = infiniteArg ? Undefined().convert() : Rational(0).convert(); replaceWithInPlace(result); return result; } + if (c.type() == ExpressionNode::Type::Rational) { const Rational r = static_cast(c); - // log(0, x) = -inf if x > 1 || inf x < 1 || undef if x < 0 + // log(0, x) = -inf if x > 1 && x != inf || inf x < 1 || undef if x < 0 if (r.isZero()) { + bool infiniteBase = b.recursivelyMatches([](const Expression e, Context & context, bool replaceSymbols) { return e.type() == ExpressionNode::Type::Infinity; }, context, true); + // Special case: log(0,inf) -> undef + if (infiniteBase) { + Expression result = Undefined(); + replaceWithInPlace(result); + return result; + } bool isNegative = true; Expression result; - Evaluation baseApproximation = childAtIndex(1).node()->approximate(1.0f, context, complexFormat, angleUnit); + Evaluation baseApproximation = b.node()->approximate(1.0f, context, complexFormat, angleUnit); std::complex logDenominator = std::log10(static_cast&>(baseApproximation).stdComplex()); if (logDenominator.imag() != 0.0f || logDenominator.real() == 0.0f) { result = Undefined(); diff --git a/poincare/test/infinity.cpp b/poincare/test/infinity.cpp index 9eacc7a90..a1681810c 100644 --- a/poincare/test/infinity.cpp +++ b/poincare/test/infinity.cpp @@ -35,6 +35,15 @@ QUIZ_CASE(poincare_infinity) { assert_parsed_expression_simplify_to("inf^x", "inf^x"); assert_parsed_expression_simplify_to("1/inf+24", "24"); assert_parsed_expression_simplify_to("X^(inf)/inf", "0*X^inf"); - assert_parsed_expression_simplify_to("ln(inf)*0", "0*ln(inf)"); + + // Logarithm + assert_parsed_expression_simplify_to("log(inf,0)", "undef"); + assert_parsed_expression_simplify_to("log(inf,1)", "undef"); + assert_parsed_expression_simplify_to("log(0,inf)", "undef"); + assert_parsed_expression_simplify_to("log(1,inf)", "0"); + assert_parsed_expression_simplify_to("log(inf,inf)", "undef"); + + assert_parsed_expression_simplify_to("ln(inf)", "inf"); + assert_parsed_expression_simplify_to("ln(inf)*0", "undef"); } From 8855390f91541dba038a96c78b1e7f1e67d594bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 31 Jan 2019 13:30:10 +0100 Subject: [PATCH 272/373] [poincare] Logarithm: add rule on log(inf) --- poincare/src/logarithm.cpp | 18 ++++++++++++++++++ poincare/test/infinity.cpp | 4 ++++ 2 files changed, 22 insertions(+) diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 2ee184e6e..f60caf128 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -136,6 +136,24 @@ Expression Logarithm::shallowReduce(Context & context, Preferences::ComplexForma */ bool letLogAtRoot = parentIsAPowerOfSameBase(); + // log(+inf, a) ? + if (!letLogAtRoot && c.type() == ExpressionNode::Type::Infinity && c.sign(&context) == ExpressionNode::Sign::Positive) { + Expression base = childAtIndex(1); + // log(+inf, a) --> ±inf with a rational and a > 0 + if (base.type() == ExpressionNode::Type::Rational && !static_cast(base).isNegative() && !static_cast(base).isZero()) { + // log(+inf,a) with a < 1 --> -inf + // log(+inf,a) with a > 1 --> inf + if (static_cast(base).signedIntegerNumerator().isLowerThan(static_cast(base).integerDenominator())) { + c = c.setSign(ExpressionNode::Sign::Negative, &context, complexFormat, angleUnit, target); + } + replaceWithInPlace(c); + return c; + } else if (base.type() == ExpressionNode::Type::Constant && (static_cast(base).isExponential() || static_cast(base).isPi())) { + replaceWithInPlace(c); + return c; + } + } + // log(x^y, b)->y*log(x, b) if x>0 if (!letLogAtRoot && c.type() == ExpressionNode::Type::Power && c.childAtIndex(0).sign(&context) == ExpressionNode::Sign::Positive) { Power p = static_cast(c); diff --git a/poincare/test/infinity.cpp b/poincare/test/infinity.cpp index a1681810c..c80735c0e 100644 --- a/poincare/test/infinity.cpp +++ b/poincare/test/infinity.cpp @@ -44,6 +44,10 @@ QUIZ_CASE(poincare_infinity) { assert_parsed_expression_simplify_to("log(inf,inf)", "undef"); assert_parsed_expression_simplify_to("ln(inf)", "inf"); + assert_parsed_expression_simplify_to("log(inf,-3)", "log(inf,-3)"); + assert_parsed_expression_simplify_to("log(inf,3)", "inf"); + assert_parsed_expression_simplify_to("log(inf,0.3)", "-inf"); + assert_parsed_expression_simplify_to("log(inf,x)", "log(inf,x)"); assert_parsed_expression_simplify_to("ln(inf)*0", "undef"); } From 3caf165621824cc67baea49458ee7851dcb05bea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 31 Jan 2019 14:12:38 +0100 Subject: [PATCH 273/373] [poincare] Factorize code in method: Expression::recursivelyMatchesInfinity --- poincare/include/poincare/expression.h | 1 + poincare/src/logarithm.cpp | 4 ++-- poincare/src/multiplication.cpp | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 19ca39a68..12bd9af66 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -128,6 +128,7 @@ public: typedef bool (*ExpressionTest)(const Expression e, Context & context, bool replaceSymbols); bool recursivelyMatches(ExpressionTest test, Context & context, bool replaceSymbols) const; bool isApproximate(Context & context) const; + bool recursivelyMatchesInfinity(Context & context) { return recursivelyMatches([](const Expression e, Context & context, bool replaceSymbols) { return e.type() == ExpressionNode::Type::Infinity; }, context, true); } static bool IsMatrix(const Expression e, Context & context, bool replaceSymbols); /* 'characteristicXRange' tries to assess the range on x where the expression * (considered as a function on x) has an interesting evolution. For example, diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index f60caf128..8256aab9e 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -222,7 +222,7 @@ Expression Logarithm::simpleShallowReduce(Context & context, Preferences::Comple replaceWithInPlace(result); return result; } - bool infiniteArg = c.recursivelyMatches([](const Expression e, Context & context, bool replaceSymbols) { return e.type() == ExpressionNode::Type::Infinity; }, context, true); + bool infiniteArg = c.recursivelyMatchesInfinity(context); // log(x,x)->1 with x != inf and log(inf,inf) = undef if (c.isIdenticalTo(b)) { Expression result = infiniteArg ? Undefined().convert() : Rational(1).convert(); @@ -240,7 +240,7 @@ Expression Logarithm::simpleShallowReduce(Context & context, Preferences::Comple const Rational r = static_cast(c); // log(0, x) = -inf if x > 1 && x != inf || inf x < 1 || undef if x < 0 if (r.isZero()) { - bool infiniteBase = b.recursivelyMatches([](const Expression e, Context & context, bool replaceSymbols) { return e.type() == ExpressionNode::Type::Infinity; }, context, true); + bool infiniteBase = b.recursivelyMatchesInfinity(context); // Special case: log(0,inf) -> undef if (infiniteBase) { Expression result = Undefined(); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 0e01b53a4..801297f39 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -443,7 +443,7 @@ Expression Multiplication::privateShallowReduce(Context & context, Preferences:: // Check that other children don't match inf bool infiniteFactor = false; for (int i = 1; i < numberOfChildren(); i++) { - infiniteFactor = childAtIndex(i).recursivelyMatches([](const Expression e, Context & context, bool replaceSymbols) { return e.type() == ExpressionNode::Type::Infinity; }, context, true); + infiniteFactor = childAtIndex(i).recursivelyMatchesInfinity(context); if (infiniteFactor) { break; } From e9b11d5bf7ea15d02a6a77a9deb19a99f711b40e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 31 Jan 2019 14:37:26 +0100 Subject: [PATCH 274/373] [poincare] Power: fix rule x^0 and 1^x with x infinity --- poincare/src/power.cpp | 10 ++++++---- poincare/test/infinity.cpp | 3 +++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index fef242492..26a660c36 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -348,8 +348,8 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co const Rational b = childAtIndex(1).convert(); // x^0 if (b.isZero()) { - // 0^0 = undef - if (childAtIndex(0).type() == ExpressionNode::Type::Rational && childAtIndex(0).convert().isZero()) { + // 0^0 = undef or (±inf)^0 = undef + if ((childAtIndex(0).type() == ExpressionNode::Type::Rational && childAtIndex(0).convert().isZero()) || childAtIndex(0).type() == ExpressionNode::Type::Infinity) { Expression result = Undefined(); replaceWithInPlace(result); return result; @@ -376,19 +376,21 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co Rational a = childAtIndex(0).convert(); // 0^x if (a.isZero()) { + // 0^x with x > 0 = 0 if (childAtIndex(1).sign(&context) == ExpressionNode::Sign::Positive) { Expression result = Rational(0); replaceWithInPlace(result); return result; } + // 0^x with x < 0 = undef if (childAtIndex(1).sign(&context) == ExpressionNode::Sign::Negative) { Expression result = Undefined(); replaceWithInPlace(result); return result; } } - // 1^x - if (a.isOne()) { + // 1^x = 1 if x != ±inf + if (a.isOne() && !childAtIndex(1).recursivelyMatchesInfinity(context)) { Expression result = Rational(1); replaceWithInPlace(result); return result; diff --git a/poincare/test/infinity.cpp b/poincare/test/infinity.cpp index c80735c0e..c84e8765f 100644 --- a/poincare/test/infinity.cpp +++ b/poincare/test/infinity.cpp @@ -24,6 +24,9 @@ QUIZ_CASE(poincare_infinity) { assert_parsed_expression_simplify_to("1E-1000", "0"); assert_parsed_expression_evaluates_to("1*10^1000", "inf"); + assert_parsed_expression_simplify_to("inf^0", "undef"); + assert_parsed_expression_simplify_to("1^inf", "1^inf"); + assert_parsed_expression_simplify_to("1^(X^inf)", "1^(X^inf)"); assert_parsed_expression_simplify_to("inf^(-1)", "0"); assert_parsed_expression_simplify_to("(-inf)^(-1)", "0"); assert_parsed_expression_simplify_to("inf^(-R(2))", "0"); From 4f3bd12fea11c64240f5a3767af98b1ac4525b2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 5 Feb 2019 16:07:17 +0100 Subject: [PATCH 275/373] [poincare] Fix bug: undef*x--> undef --- poincare/src/expression.cpp | 2 +- poincare/test/function.cpp | 2 +- poincare/test/multiplication.cpp | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index f9608abc9..cf1b1bbaf 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -216,7 +216,7 @@ Expression Expression::defaultShallowReduce() { result = Unreal(); break; } else if (childAtIndex(i).type() == ExpressionNode::Type::Undefined) { - Expression result = Undefined(); + result = Undefined(); } } if (!result.isUninitialized()) { diff --git a/poincare/test/function.cpp b/poincare/test/function.cpp index 74b22c42e..f85359c1c 100644 --- a/poincare/test/function.cpp +++ b/poincare/test/function.cpp @@ -283,7 +283,7 @@ QUIZ_CASE(poincare_function_simplify) { assert_parsed_expression_simplify_to("sign(0)", "0"); assert_parsed_expression_simplify_to("sign(inf)", "1"); assert_parsed_expression_simplify_to("sign(-inf)", "-1"); - assert_parsed_expression_simplify_to("sign(undef)", "sign(undef)"); + assert_parsed_expression_simplify_to("sign(undef)", "undef"); assert_parsed_expression_simplify_to("sign(23)", "1"); assert_parsed_expression_simplify_to("sign(log(18))", "1"); assert_parsed_expression_simplify_to("sign(-R(2))", "-1"); diff --git a/poincare/test/multiplication.cpp b/poincare/test/multiplication.cpp index a1be66d6e..41d4fd816 100644 --- a/poincare/test/multiplication.cpp +++ b/poincare/test/multiplication.cpp @@ -20,6 +20,7 @@ QUIZ_CASE(poincare_multiplication_evaluate) { } QUIZ_CASE(poincare_multiplication_simplify) { + assert_parsed_expression_simplify_to("undef*x", "undef"); assert_parsed_expression_simplify_to("0*x+B", "B"); assert_parsed_expression_simplify_to("0*x*0*32*cos(3)", "0"); assert_parsed_expression_simplify_to("3*A^4*B^x*B^2*(A^2+2)*2*1.2", "(36*A^6*B^(x+2)+72*A^4*B^(x+2))/5"); From 79f0834f4e031371bebb7f5b6fd97124db37dd1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 5 Feb 2019 11:48:31 +0100 Subject: [PATCH 276/373] [poincare] Add method 'hasNode' on TreeHandle --- poincare/include/poincare/tree_handle.h | 2 ++ poincare/src/tree_handle.cpp | 4 ++-- poincare/src/tree_node.cpp | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/tree_handle.h b/poincare/include/poincare/tree_handle.h index f9e58440b..87b6ade6d 100644 --- a/poincare/include/poincare/tree_handle.h +++ b/poincare/include/poincare/tree_handle.h @@ -107,6 +107,8 @@ protected: void setIdentifierAndRetain(int newId); void setTo(const TreeHandle & tr); + static bool hasNode(int identifier) { return identifier > TreeNode::NoNodeIdentifier; } + /* Hierarchy operations */ // Add void addChildAtIndexInPlace(TreeHandle t, int index, int currentNumberOfChildren); diff --git a/poincare/src/tree_handle.cpp b/poincare/src/tree_handle.cpp index e4eaba5ed..1ae1abe60 100644 --- a/poincare/src/tree_handle.cpp +++ b/poincare/src/tree_handle.cpp @@ -16,7 +16,7 @@ TreeHandle TreeHandle::clone() const { } /* Hierarchy operations */ -TreeNode * TreeHandle::node() const { assert(m_identifier != TreeNode::NoNodeIdentifier); return TreePool::sharedPool()->node(m_identifier); } +TreeNode * TreeHandle::node() const { assert(hasNode(m_identifier)); return TreePool::sharedPool()->node(m_identifier); } size_t TreeHandle::size() const { return node()->deepSize(node()->numberOfChildren()); } @@ -204,7 +204,7 @@ void TreeHandle::setTo(const TreeHandle & tr) { } void TreeHandle::release(int identifier) { - if (identifier == TreeNode::NoNodeIdentifier) { + if (!hasNode(identifier)) { return; } TreeNode * node = TreePool::sharedPool()->node(identifier); diff --git a/poincare/src/tree_node.cpp b/poincare/src/tree_node.cpp index 1c8df84ee..3036690b6 100644 --- a/poincare/src/tree_node.cpp +++ b/poincare/src/tree_node.cpp @@ -31,7 +31,7 @@ void TreeNode::rename(int identifier, bool unregisterPreviousIdentifier) { // Hierarchy TreeNode * TreeNode::parent() const { - return m_parentIdentifier == NoNodeIdentifier ? nullptr : TreePool::sharedPool()->node(m_parentIdentifier); + return TreeHandle::hasNode(m_parentIdentifier) ? TreePool::sharedPool()->node(m_parentIdentifier) : nullptr; } TreeNode * TreeNode::root() { From f4d63a21607fa8e79e8bd2ae0118558f52ddc868 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 5 Feb 2019 11:59:58 +0100 Subject: [PATCH 277/373] [poincare] Integer are allocated on the TreePool instead of using their own buffer. Short Integers are kept in the handle as an optimization. --- poincare/include/poincare/decimal.h | 2 +- poincare/include/poincare/integer.h | 124 ++++++----- poincare/src/init.cpp | 3 - poincare/src/integer.cpp | 310 ++++++++++------------------ poincare/src/rational.cpp | 4 +- poincare/src/tree_pool.cpp | 1 + 6 files changed, 183 insertions(+), 261 deletions(-) diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index 3c86ff89d..22971bb8c 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -39,7 +39,7 @@ public: virtual void logAttributes(std::ostream & stream) const override { stream << " negative=\"" << m_negative << "\""; stream << " mantissa=\""; - this->signedMantissa().log(stream); + this->signedMantissa().logInteger(stream); stream << "\""; stream << " exponent=\"" << m_exponent << "\""; } diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 041cff08e..ec6009b1e 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -29,32 +29,70 @@ static_assert(sizeof(double_native_int_t) == 2*sizeof(native_int_t), "double_nat struct IntegerDivision; -class Integer final { +class IntegerNode final : public TreeNode { +public: + // TreeNode + void initToMatchSize(size_t goalSize) override; + size_t size() const override; + int numberOfChildren() const override { return 0; } +#if POINCARE_TREE_LOG + void log(std::ostream & stream) const; + virtual void logNodeName(std::ostream & stream) const override { + stream << "Integer"; + } + virtual void logAttributes(std::ostream & stream) const override; +#endif + + virtual void setDigits(const native_uint_t * digits, uint8_t numberOfDigits); + const native_uint_t * digits() const { return m_digits; } + uint8_t numberOfDigits() const { return m_numberOfDigits; } +private: + uint8_t m_numberOfDigits; // In base native_uint_t + native_uint_t m_digits[0]; // Little-endian +}; + +class Integer final : public TreeHandle { public: /* Constructors & Destructors */ + static Integer BuildInteger(native_uint_t * digits, uint16_t numberOfDigits, bool negative, bool enableOverflow = false); Integer(native_int_t i = 0); Integer(double_native_int_t i); Integer(const char * digits, size_t length, bool negative); Integer(const char * digits) : Integer(digits, strlen(digits), false) {} - static Integer Overflow(bool negative) { return Integer((native_uint_t *)nullptr, k_maxNumberOfDigits+1, negative); } - static Integer BuildInteger(native_uint_t * digits, uint16_t numberOfDigits, bool negative, bool enableOverflow = false); - ~Integer(); - static void TidyIntegerBuffer(); - + static Integer Overflow(bool negative) { return Integer(OverflowIdentifier, negative); } #if POINCARE_TREE_LOG - void log(std::ostream & stream = std::cout) const; + void logInteger(std::ostream & stream) const { + if (isOverflow()) { + stream << "overflow"; + return; + } else if (usesImmediateDigit()) { + stream << m_digit; + return; + } + node()->log(stream); + } #endif - /* Copy/Move constructors/assignments */ - Integer(Integer&& other); // C++11 move constructor - Integer& operator=(Integer&& other); // C++11 move assignment operator - Integer(const Integer& other); // C++11 copy constructor - Integer& operator=(const Integer& other); // C++11 copy assignment operator - // Getters - const native_uint_t * digits() const { return usesImmediateDigit() ? &m_digit : m_digits; } - uint8_t numberOfDigits() const { return m_numberOfDigits; } + const native_uint_t * digits() const { + if (usesImmediateDigit()) { + return &m_digit; + } else if (isOverflow()) { + return nullptr; + } + return node()->digits(); + } + uint8_t numberOfDigits() const { + if (usesImmediateDigit()) { + return m_digit == 0 ? 0 : 1; + } else if (isOverflow()) { + return k_maxNumberOfDigits+1; + } + return node()->numberOfDigits(); + } + bool isNegative() const { return m_negative; } + void setNegative(bool negative) { m_negative = numberOfDigits() > 0 ? negative : false; } // 0 is always positive // Serialization int serialize(char * buffer, int bufferSize) const; @@ -66,21 +104,19 @@ public: template T approximate() const; // Sign - bool isNegative() const { return m_negative; } - void setNegative(bool negative) { m_negative = m_numberOfDigits > 0 ? negative : false; } // Properties static int NumberOfBase10DigitsWithoutSign(const Integer & i); - bool isOne() const { return (m_numberOfDigits == 1 && digit(0) == 1 && !m_negative); }; - bool isTwo() const { return (m_numberOfDigits == 1 && digit(0) == 2 && !m_negative); }; - bool isTen() const { return (m_numberOfDigits == 1 && digit(0) == 10 && !m_negative); }; - bool isMinusOne() const { return (m_numberOfDigits == 1 && digit(0) == 1 && m_negative); }; - bool isZero() const { return (m_numberOfDigits == 0); }; - bool isInfinity() const { return m_numberOfDigits > k_maxNumberOfDigits; } + bool isOne() const { return (numberOfDigits() == 1 && digit(0) == 1 && !m_negative); }; + bool isTwo() const { return (numberOfDigits() == 1 && digit(0) == 2 && !m_negative); }; + bool isTen() const { return (numberOfDigits() == 1 && digit(0) == 10 && !m_negative); }; + bool isMinusOne() const { return (numberOfDigits() == 1 && digit(0) == 1 && m_negative); }; + bool isZero() const { return (numberOfDigits() == 0); }; + bool isInfinity() const { return numberOfDigits() > k_maxNumberOfDigits; } bool isEven() const { return ((digit(0) & 1) == 0); } constexpr static int k_maxExtractableInteger = 0x7FFFFFFF; - int extractedInt() const { assert(m_numberOfDigits == 0 || (m_numberOfDigits <= 1 && digit(0) <= k_maxExtractableInteger)); return m_numberOfDigits == 0 ? 0 : (m_negative ? -digit(0) : digit(0)); } + int extractedInt() const { assert(numberOfDigits() == 0 || (numberOfDigits() <= 1 && digit(0) <= k_maxExtractableInteger)); return numberOfDigits() == 0 ? 0 : (m_negative ? -digit(0) : digit(0)); } // Comparison static int NaturalOrder(const Integer & i, const Integer & j); @@ -100,23 +136,14 @@ public: static Integer Factorial(const Integer & i); constexpr static int k_maxNumberOfDigits = 32; - constexpr static int k_maxNumberOfIntegerSimutaneously = 16; private: constexpr static int k_maxNumberOfDigitsBase10 = 308; // (2^32)^k_maxNumberOfDigits ~ 1E308 - - Integer(native_uint_t * digits, uint16_t numberOfDigits, bool negative, bool enableOverflow = false); - - // Dynamic allocation - /* In order to guarantee the potential existence of 16 Integers simutaneously, - * we keep a table uint32_t that can contain up to 16 Integers with the - * maximal numbers of digits. We also give them one extra digit to be able to - * perform complex operations (like division) which involve Integers with one - * additional digit. */ - static native_uint_t * allocDigits(int numberOfDigits); - static void freeDigits(native_uint_t * digits); + static constexpr int OverflowIdentifier = TreeNode::NoNodeIdentifier - 1; // Constructors - void releaseDynamicIvars(); + Integer(native_uint_t * digits, uint16_t numberOfDigits, bool negative); + Integer(int identifier, bool negative) : TreeHandle(identifier), m_negative(negative) {} + IntegerNode * node() const { return static_cast(TreeHandle::node()); } // Arithmetic static Integer addition(const Integer & a, const Integer & b, bool inverseBNegative, bool enableOneDigitOverflow = false); @@ -133,36 +160,33 @@ private: // HalfDigits uint16_t numberOfHalfDigits() const { - if (m_numberOfDigits == 0) { return 0; } - native_uint_t d = digit(m_numberOfDigits-1); + if (numberOfDigits() == 0) { return 0; } + native_uint_t d = digit(numberOfDigits()-1); native_uint_t halfBase = 1 << (8*sizeof(half_native_uint_t)); - return (d >= halfBase ? 2*m_numberOfDigits : 2*m_numberOfDigits-1); + return (d >= halfBase ? 2*numberOfDigits() : 2*numberOfDigits()-1); } half_native_uint_t halfDigit(int i) const { assert(i >= 0); if (i >= numberOfHalfDigits()) { return 0; } - return (usesImmediateDigit() ? ((half_native_uint_t *)&m_digit)[i] : ((half_native_uint_t *)m_digits)[i]); + return (usesImmediateDigit() ? ((half_native_uint_t *)&m_digit)[i] : ((half_native_uint_t *)digits())[i]); } - bool usesImmediateDigit() const { return m_numberOfDigits == 1; } native_uint_t digit(uint8_t i) const { - assert(i >= 0 && i < m_numberOfDigits); - return (usesImmediateDigit() ? m_digit : m_digits[i]); + assert(!isOverflow()); + assert(i >= 0 && i < numberOfDigits()); + return (usesImmediateDigit() ? m_digit : digits()[i]); } + bool usesImmediateDigit() const { return m_identifier == TreeNode::NoNodeIdentifier; } /* An integer can have (k_maxNumberOfDigits + 1) digits: either when it is an * overflow, or when we want to have one more digit than usual to compute a * big division. */ - bool isOverflow() const { return m_numberOfDigits == k_maxNumberOfDigits + 1 && m_digits == nullptr; } + bool isOverflow() const { return m_identifier == OverflowIdentifier; } bool m_negative; - uint8_t m_numberOfDigits; // In base native_uint_t - union { - native_uint_t * m_digits; // Little-endian - native_uint_t m_digit; - }; + native_uint_t m_digit; }; struct IntegerDivision { diff --git a/poincare/src/init.cpp b/poincare/src/init.cpp index 0e4b1bbe7..9c9b6141b 100644 --- a/poincare/src/init.cpp +++ b/poincare/src/init.cpp @@ -12,9 +12,6 @@ void Init() { } void Tidy() { - // Clean Integer - Integer::TidyIntegerBuffer(); - // Clean Expression (reset the SymbolReplacementsLock) Expression::Tidy(); } diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index d69cd9617..39e46d8aa 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -34,119 +34,95 @@ static inline int8_t sign(bool negative) { return 1 - 2*(int8_t)negative; } +void IntegerNode::initToMatchSize(size_t goalSize) { + assert(goalSize != sizeof(IntegerNode)); + int digitsSize = goalSize - sizeof(IntegerNode); + assert(digitsSize%sizeof(native_uint_t) == 0); + /* We are initing the Integer to match a specific size. The built integer + * is dummy. */ + m_numberOfDigits = digitsSize/sizeof(native_uint_t); + assert(size() == goalSize); +} + +static size_t IntegerSize(uint8_t numberOfDigits) { + return sizeof(IntegerNode) + sizeof(native_uint_t)*(numberOfDigits); +} + +size_t IntegerNode::size() const { + return IntegerSize(m_numberOfDigits); +} + #if POINCARE_TREE_LOG -void Integer::log(std::ostream & stream) const { - if (m_numberOfDigits > k_maxNumberOfDigits) { - stream << "Integer: overflow"; +void IntegerNode::logAttributes(std::ostream & stream) const { + stream << " value=\""; + log(stream); + stream << "\""; +} + +void IntegerNode::log(std::ostream & stream) const { + if (m_numberOfDigits > Integer::k_maxNumberOfDigits) { + stream << "overflow"; return; } double d = 0.0; double base = 1.0; for (int i = 0; i < m_numberOfDigits; i++) { - d += digit(i)*base; + d += m_digits[i]*base; base *= std::pow(2.0,32.0); } - stream << "Integer: " << d; + stream << d; } #endif -/* new operator */ - -// This bit buffer indicates which cases of the sIntegerBuffer are already allocated -static uint16_t sbusyIntegerBuffer = 0; -static native_uint_t sIntegerBuffer[(Integer::k_maxNumberOfDigits+1)*Integer::k_maxNumberOfIntegerSimutaneously]; - -void Integer::TidyIntegerBuffer() { - sbusyIntegerBuffer = 0; -} - -native_uint_t * Integer::allocDigits(int numberOfDigits) { - assert(numberOfDigits <= k_maxNumberOfDigits+1); - uint16_t bitIndex = 1 << (16-1); - int index = 0; - while (sbusyIntegerBuffer & bitIndex) { - bitIndex >>= 1; - index++; - } - if (bitIndex == 0) { // we overflow the sIntegerBuffer - assert(false); - return nullptr; - } - sbusyIntegerBuffer |= bitIndex; - return sIntegerBuffer+index*(Integer::k_maxNumberOfDigits+1); -} - -void Integer::freeDigits(native_uint_t * digits) { - int index = (digits - sIntegerBuffer)/(Integer::k_maxNumberOfDigits+1); - assert(index < 16); - sbusyIntegerBuffer &= ~((uint16_t)1 << (16-1-index)); +void IntegerNode::setDigits(const native_uint_t * digits, uint8_t numberOfDigits) { + m_numberOfDigits = numberOfDigits; + memcpy(m_digits, digits, numberOfDigits*sizeof(native_uint_t)); } // Constructor Integer Integer::BuildInteger(native_uint_t * digits, uint16_t numberOfDigits, bool negative, bool enableOverflow) { - if ((!digits || !enableOverflow) && numberOfDigits == k_maxNumberOfDigits+1) { + if ((!digits || !enableOverflow) && numberOfDigits >= k_maxNumberOfDigits+1) { return Overflow(negative); } - native_uint_t * newDigits = allocDigits(numberOfDigits); - for (uint8_t i = 0; i < numberOfDigits; i++) { - newDigits[i] = digits[i]; + // 0 can't be negative + negative = numberOfDigits == 0 ? false : negative; + if (numberOfDigits <= 1) { + Integer i(TreeNode::NoNodeIdentifier, negative); + i.m_digit = numberOfDigits == 0 ? 0 : digits[0]; + return i; } - return Integer(newDigits, numberOfDigits, negative, enableOverflow); + return Integer(digits, numberOfDigits, negative); } -/* WARNING: This constructor takes ownership of the digits array! */ -Integer::Integer(native_uint_t * digits, uint16_t numberOfDigits, bool negative, bool enableOverflow) : - m_negative(numberOfDigits == 0 ? false : negative), - m_numberOfDigits(!enableOverflow && numberOfDigits > k_maxNumberOfDigits ? k_maxNumberOfDigits+1 : numberOfDigits), - m_digits(digits) +// Private constructor +Integer::Integer(native_uint_t * digits, uint16_t numberOfDigits, bool negative) : + TreeHandle(TreePool::sharedPool()->createTreeNode(IntegerSize(numberOfDigits))), + m_negative(negative) { - if ((m_numberOfDigits <= 1 || (!enableOverflow && m_numberOfDigits > k_maxNumberOfDigits)) && m_digits) { - freeDigits(m_digits); - if (m_numberOfDigits == 1) { - m_digit = digits[0]; - } else { - m_digits = nullptr; - } - } - m_negative = m_numberOfDigits == 0 ? false : m_negative; + node()->setDigits(digits, numberOfDigits); } -Integer::Integer(native_int_t i) { - if (i == 0) { - m_digits = nullptr; - m_numberOfDigits = 0; - m_negative = false; - return; - } - m_numberOfDigits = 1; +Integer::Integer(native_int_t i) : TreeHandle(TreeNode::NoNodeIdentifier) { m_digit = i > 0 ? i : -i; m_negative = i < 0; } Integer::Integer(double_native_int_t i) { - if (i == 0) { - m_digits = nullptr; - m_numberOfDigits = 0; - m_negative = false; - return; - } double_native_uint_t j = i < 0 ? -i : i; native_uint_t * d = (native_uint_t *)&j; native_uint_t leastSignificantDigit = *d; native_uint_t mostSignificantDigit = *(d+1); - m_numberOfDigits = (mostSignificantDigit == 0) ? 1 : 2; - if (m_numberOfDigits == 1) { + uint8_t numberOfDigits = (mostSignificantDigit == 0) ? 1 : 2; + if (numberOfDigits == 1) { + m_identifier = TreeNode::NoNodeIdentifier; + m_negative = i < 0; m_digit = leastSignificantDigit; } else { - native_uint_t * digits = allocDigits(m_numberOfDigits); - digits[0] = leastSignificantDigit; - digits[1] = mostSignificantDigit; - m_digits = digits; + new (this) Integer(d, 2, i < 0); } - m_negative = i < 0; } Integer::Integer(const char * digits, size_t length, bool negative) : @@ -165,90 +141,9 @@ Integer::Integer(const char * digits, size_t length, bool negative) : digits++; } } - setNegative(isZero() ? false : negative); } -void Integer::releaseDynamicIvars() { - if (!usesImmediateDigit() && m_digits) { - freeDigits(m_digits); - } -} - -Integer::~Integer() { - releaseDynamicIvars(); -} - -Integer::Integer(Integer && other) { - // Pilfer other's data - if (other.usesImmediateDigit()) { - m_digit = other.m_digit; - } else { - m_digits = other.m_digits; - } - m_numberOfDigits = other.m_numberOfDigits; - m_negative = other.m_negative; - - // Reset other - other.m_digits = nullptr; - other.m_numberOfDigits = 1; - other.m_negative = 0; -} - -Integer::Integer(const Integer& other) { - // Copy other's data - if (other.usesImmediateDigit() || other.isOverflow()) { - m_digit = other.m_digit; - } else { - native_uint_t * newDigits = allocDigits(other.m_numberOfDigits); - for (uint8_t i = 0; i < other.m_numberOfDigits; i++) { - newDigits[i] = other.m_digits[i]; - } - m_digits = newDigits; - } - m_numberOfDigits = other.m_numberOfDigits; - m_negative = other.m_negative; -} - -Integer& Integer::operator=(Integer && other) { - if (this != &other) { - releaseDynamicIvars(); - // Pilfer other's ivars - if (other.usesImmediateDigit()) { - m_digit = other.m_digit; - } else { - m_digits = other.m_digits; - } - m_numberOfDigits = other.m_numberOfDigits; - m_negative = other.m_negative; - - // Reset other - other.m_digits = nullptr; - other.m_numberOfDigits = 1; - other.m_negative = 0; - } - return *this; -} - -Integer& Integer::operator=(const Integer& other) { - if (this != &other) { - releaseDynamicIvars(); - // Copy other's ivars - if (other.usesImmediateDigit() || other.isOverflow()) { - m_digit = other.m_digit; - } else { - native_uint_t * digits = allocDigits(other.m_numberOfDigits); - for (uint8_t i = 0; i < other.m_numberOfDigits; i++) { - digits[i] = other.m_digits[i]; - } - m_digits = digits; - } - m_numberOfDigits = other.m_numberOfDigits; - m_negative = other.m_negative; - } - return *this; -} - // Serialization int Integer::serialize(char * buffer, int bufferSize) const { @@ -306,7 +201,7 @@ HorizontalLayout Integer::createLayout() const { template T Integer::approximate() const { - if (m_numberOfDigits == 0) { + if (numberOfDigits() == 0) { /* This special case for 0 is needed, because the current algorithm assumes * that the big integer is non zero, thus puts the exponent to 126 (integer * area), the issue is that when the mantissa is 0, a "shadow bit" is @@ -326,17 +221,18 @@ T Integer::approximate() const { return m_negative ? -INFINITY : INFINITY; } - native_uint_t lastDigit = m_numberOfDigits > 0 ? digit(m_numberOfDigits-1) : 0; + assert(numberOfDigits() > 0); + native_uint_t lastDigit = digit(numberOfDigits()-1); uint8_t numberOfBitsInLastDigit = log2(lastDigit); bool sign = m_negative; uint16_t exponent = IEEE754::exponentOffset(); /* Escape case if the exponent is too big to be stored */ - assert(m_numberOfDigits > 0); - if (((int)m_numberOfDigits-1)*32+numberOfBitsInLastDigit-1> IEEE754::maxExponent()-IEEE754::exponentOffset()) { + assert(numberOfDigits() > 0); + if (((int)numberOfDigits()-1)*32+numberOfBitsInLastDigit-1> IEEE754::maxExponent()-IEEE754::exponentOffset()) { return m_negative ? -INFINITY : INFINITY; } - exponent += (m_numberOfDigits-1)*32; + exponent += (numberOfDigits()-1)*32; exponent += numberOfBitsInLastDigit-1; uint64_t mantissa = 0; @@ -352,8 +248,8 @@ T Integer::approximate() const { * the mantissa is complete to avoid undefined right shifting (Shift operator * behavior is undefined if the right operand is negative, or greater than or * equal to the length in bits of the promoted left operand). */ - while (m_numberOfDigits >= digitIndex && numberOfBits < IEEE754::size()) { - lastDigit = digit(m_numberOfDigits-digitIndex); + while (numberOfDigits() >= digitIndex && numberOfBits < IEEE754::size()) { + lastDigit = digit(numberOfDigits()-digitIndex); numberOfBits += 32; if (IEEE754::size() > numberOfBits) { assert(IEEE754::size()-numberOfBits > 0 && IEEE754::size()-numberOfBits < 64); @@ -473,16 +369,16 @@ Integer Integer::multiplication(const Integer & a, const Integer & b, bool oneDi return Integer::Overflow(a.m_negative != b.m_negative); } - uint8_t size = min(a.m_numberOfDigits + b.m_numberOfDigits, k_maxNumberOfDigits + oneDigitOverflow); // Enable overflowing of 1 digit + uint8_t size = min(a.numberOfDigits() + b.numberOfDigits(), k_maxNumberOfDigits + oneDigitOverflow); // Enable overflowing of 1 digit - native_uint_t * digits = allocDigits(size); + native_uint_t digits[k_maxNumberOfDigits + 1]; memset(digits, 0, size*sizeof(native_uint_t)); double_native_uint_t carry = 0; - for (uint8_t i = 0; i < a.m_numberOfDigits; i++) { + for (uint8_t i = 0; i < a.numberOfDigits(); i++) { double_native_uint_t aDigit = a.digit(i); carry = 0; - for (uint8_t j = 0; j < b.m_numberOfDigits; j++) { + for (uint8_t j = 0; j < b.numberOfDigits(); j++) { double_native_uint_t bDigit = b.digit(j); /* The fact that aDigit and bDigit are double_native is very important, * otherwise the product might end up being computed on single_native size @@ -494,17 +390,16 @@ Integer Integer::multiplication(const Integer & a, const Integer & b, bool oneDi } else { if (l[0] != 0) { // Overflow the largest Integer - freeDigits(digits); return Integer::Overflow(a.m_negative != b.m_negative); - } } + } + } carry = l[1]; } - if (i+b.m_numberOfDigits < (uint8_t) k_maxNumberOfDigits+oneDigitOverflow) { - digits[i+b.m_numberOfDigits] += carry; + if (i+b.numberOfDigits() < (uint8_t) k_maxNumberOfDigits+oneDigitOverflow) { + digits[i+b.numberOfDigits()] += carry; } else { if (carry != 0) { // Overflow the largest Integer - freeDigits(digits); return Integer::Overflow(a.m_negative != b.m_negative); } } @@ -512,13 +407,13 @@ Integer Integer::multiplication(const Integer & a, const Integer & b, bool oneDi while (size>0 && digits[size-1] == 0) { size--; } - return Integer(digits, size, a.m_negative != b.m_negative, oneDigitOverflow); + return BuildInteger(digits, size, a.m_negative != b.m_negative, oneDigitOverflow); } int8_t Integer::ucmp(const Integer & a, const Integer & b) { - if (a.m_numberOfDigits < b.m_numberOfDigits) { + if (a.numberOfDigits() < b.numberOfDigits()) { return -1; - } else if (a.m_numberOfDigits > b.m_numberOfDigits) { + } else if (a.numberOfDigits() > b.numberOfDigits()) { return 1; } if (a.isOverflow() && b.isOverflow()) { @@ -526,10 +421,10 @@ int8_t Integer::ucmp(const Integer & a, const Integer & b) { } assert(!a.isOverflow()); assert(!b.isOverflow()); - for (uint16_t i = 0; i < a.m_numberOfDigits; i++) { + for (uint16_t i = 0; i < a.numberOfDigits(); i++) { // Digits are stored most-significant last - native_uint_t aDigit = a.digit(a.m_numberOfDigits-i-1); - native_uint_t bDigit = b.digit(b.m_numberOfDigits-i-1); + native_uint_t aDigit = a.digit(a.numberOfDigits()-i-1); + native_uint_t bDigit = b.digit(b.numberOfDigits()-i-1); if (aDigit < bDigit) { return -1; } else if (aDigit > bDigit) { @@ -541,27 +436,26 @@ int8_t Integer::ucmp(const Integer & a, const Integer & b) { Integer Integer::usum(const Integer & a, const Integer & b, bool subtract, bool oneDigitOverflow) { if (a.isOverflow() || b.isOverflow()) { - return Integer::Overflow(a.m_negative != b.m_negative); + return Overflow(a.m_negative != b.m_negative); } - uint8_t size = max(a.m_numberOfDigits, b.m_numberOfDigits); + uint8_t size = max(a.numberOfDigits(), b.numberOfDigits()); if (!subtract) { // Addition can overflow size++; } - native_uint_t * digits = allocDigits(max(size, k_maxNumberOfDigits+oneDigitOverflow)); + native_uint_t digits[k_maxNumberOfDigits+1]; bool carry = false; for (uint8_t i = 0; i < size; i++) { - native_uint_t aDigit = (i >= a.m_numberOfDigits ? 0 : a.digit(i)); - native_uint_t bDigit = (i >= b.m_numberOfDigits ? 0 : b.digit(i)); + native_uint_t aDigit = (i >= a.numberOfDigits() ? 0 : a.digit(i)); + native_uint_t bDigit = (i >= b.numberOfDigits() ? 0 : b.digit(i)); native_uint_t result = (subtract ? aDigit - bDigit - carry : aDigit + bDigit + carry); if (i < (uint8_t) (k_maxNumberOfDigits + oneDigitOverflow)) { digits[i] = result; } else { if (result != 0) { // Overflow the largest Integer - freeDigits(digits); - return Integer::Overflow(false); + return Overflow(false); } } if (subtract) { @@ -574,50 +468,53 @@ Integer Integer::usum(const Integer & a, const Integer & b, bool subtract, bool while (size>0 && digits[size-1] == 0) { size--; } - return Integer(digits, size, false, oneDigitOverflow); + return BuildInteger(digits, size, false, oneDigitOverflow); } Integer Integer::multiplyByPowerOf2(uint8_t pow) const { assert(pow < 32); - native_uint_t * digits = allocDigits(m_numberOfDigits+1); + native_uint_t digits[k_maxNumberOfDigits+1]; native_uint_t carry = 0; - for (uint8_t i = 0; i < m_numberOfDigits; i++) { + for (uint8_t i = 0; i < numberOfDigits(); i++) { digits[i] = digit(i) << pow | carry; carry = pow == 0 ? 0 : digit(i) >> (32-pow); } - digits[m_numberOfDigits] = carry; - return Integer(digits, carry ? m_numberOfDigits + 1 : m_numberOfDigits, false, true); + digits[numberOfDigits()] = carry; + return BuildInteger(digits, carry ? numberOfDigits() + 1 : numberOfDigits(), false, true); } Integer Integer::divideByPowerOf2(uint8_t pow) const { assert(pow < 32); - native_uint_t * digits = allocDigits(m_numberOfDigits); + native_uint_t digits[k_maxNumberOfDigits+1]; native_uint_t carry = 0; - for (int i = m_numberOfDigits - 1; i >= 0; i--) { + for (int i = numberOfDigits() - 1; i >= 0; i--) { digits[i] = digit(i) >> pow | carry; carry = pow == 0 ? 0 : digit(i) << (32-pow); } - return Integer(digits, digits[m_numberOfDigits-1] > 0 ? m_numberOfDigits : m_numberOfDigits-1, false, true); + return BuildInteger(digits, digits[numberOfDigits()-1] > 0 ? numberOfDigits() : numberOfDigits()-1, false, true); } // return this*(2^16)^pow Integer Integer::multiplyByPowerOfBase(uint8_t pow) const { int nbOfHalfDigits = numberOfHalfDigits(); - half_native_uint_t * digits = (half_native_uint_t *)allocDigits(m_numberOfDigits+(pow+1)/2); - memset(digits, 0, sizeof(native_uint_t)*(m_numberOfDigits+(pow+1)/2)); + half_native_uint_t digits[2*(k_maxNumberOfDigits+1)]; + /* The number of half digits of the built integer is nbOfHalfDigits+pow. + * Still, we set an extra half digit to 0 to easily convert half digits to + * digits. */ + memset(digits, 0, sizeof(half_native_uint_t)*(nbOfHalfDigits+pow+1)); for (uint8_t i = 0; i < nbOfHalfDigits; i++) { digits[i+pow] = halfDigit(i); } nbOfHalfDigits += pow; - return Integer((native_uint_t *)digits, nbOfHalfDigits%2 == 1 ? nbOfHalfDigits/2+1 : nbOfHalfDigits/2, false, true); + return BuildInteger((native_uint_t *)digits, nbOfHalfDigits%2 == 1 ? nbOfHalfDigits/2+1 : nbOfHalfDigits/2, false, true); } IntegerDivision Integer::udiv(const Integer & numerator, const Integer & denominator) { if (denominator.isOverflow()) { - return {.quotient = Integer::Overflow(false), .remainder = Integer::Overflow(false)}; + return {.quotient = Overflow(false), .remainder = Integer::Overflow(false)}; } if (numerator.isOverflow()) { - return {.quotient = Integer::Overflow(false), .remainder = Integer::Overflow(false)}; + return {.quotient = Overflow(false), .remainder = Integer::Overflow(false)}; } /* Modern Computer Arithmetic, Richard P. Brent and Paul Zimmermann * (Algorithm 1.6) */ @@ -646,8 +543,9 @@ IntegerDivision Integer::udiv(const Integer & numerator, const Integer & denomin int n = B.numberOfHalfDigits(); int m = A.numberOfHalfDigits()-n; // qDigits is a half_native_uint_t array and enable one digit overflow - half_native_uint_t * qDigits = (half_native_uint_t *)allocDigits(m/2+1); - memset(qDigits, 0, (m/2+1)*sizeof(native_uint_t)); + half_native_uint_t qDigits[2*k_maxNumberOfDigits]; + // The quotient q has at maximum m+1 half digits but we set an extra half digit to 0 to enable to easily convert it from half digits to digits + memset(qDigits, 0, max(m+1+1,2*k_maxNumberOfDigits)*sizeof(half_native_uint_t)); // betaMB = B*beta^m Integer betaMB = B.multiplyByPowerOfBase(m); if (Integer::NaturalOrder(A,betaMB) >= 0) { // A >= B*beta^m @@ -660,10 +558,12 @@ IntegerDivision Integer::udiv(const Integer & numerator, const Integer & denomin half_native_uint_t baseMinus1 = (1 << 16) -1; // beta-1 qDigits[j] = qj2 < (native_uint_t)baseMinus1 ? (half_native_uint_t)qj2 : baseMinus1; // min(qj2, beta -1) A = Integer::addition(A, multiplication(qDigits[j], B.multiplyByPowerOfBase(j), true), true, true); // A-q[j]*beta^j*B - Integer betaJM = B.multiplyByPowerOfBase(j); // betaJM = B*beta^j - while (A.isNegative()) { - qDigits[j] = qDigits[j]-1; // q[j] = q[j]-1 - A = addition(A, betaJM, false, true); // A = B*beta^j+A + if (A.isNegative()) { + Integer betaJM = B.multiplyByPowerOfBase(j); // betaJM = B*beta^j + while (A.isNegative()) { + qDigits[j] = qDigits[j]-1; // q[j] = q[j]-1 + A = addition(A, betaJM, false, true); // A = B*beta^j+A + } } } int qNumberOfDigits = m+1; @@ -671,7 +571,7 @@ IntegerDivision Integer::udiv(const Integer & numerator, const Integer & denomin qNumberOfDigits--; } int qNumberOfDigitsInBase32 = qNumberOfDigits%2 == 1 ? qNumberOfDigits/2+1 : qNumberOfDigits/2; - IntegerDivision div = {.quotient = Integer((native_uint_t *)qDigits, qNumberOfDigitsInBase32, false), .remainder = A}; + IntegerDivision div = {.quotient = BuildInteger((native_uint_t *)qDigits, qNumberOfDigitsInBase32, false), .remainder = A}; if (pow > 0 && !div.remainder.isZero()) { div.remainder = div.remainder.divideByPowerOf2(pow); } diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index 705c5b010..623908d31 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -71,10 +71,10 @@ size_t RationalNode::size() const { void RationalNode::logAttributes(std::ostream & stream) const { stream << " negative=\"" << m_negative << "\""; stream << " numerator=\""; - this->signedNumerator().log(stream); + this->signedNumerator().logInteger(stream); stream << "\""; stream << " denominator=\""; - this->denominator().log(stream); + this->denominator().logInteger(stream); stream << "\""; } #endif diff --git a/poincare/src/tree_pool.cpp b/poincare/src/tree_pool.cpp index 346768071..56f928125 100644 --- a/poincare/src/tree_pool.cpp +++ b/poincare/src/tree_pool.cpp @@ -256,6 +256,7 @@ template MatrixNode * Poincare::TreePool::createTreeNode(size_t size template FloatNode * Poincare::TreePool::createTreeNode >(size_t size); template GreatCommonDivisorNode * Poincare::TreePool::createTreeNode(size_t size); template ImaginaryPartNode * Poincare::TreePool::createTreeNode(size_t size); +template IntegerNode * Poincare::TreePool::createTreeNode(size_t size); template IntegralNode * Poincare::TreePool::createTreeNode(size_t size); template LeastCommonMultipleNode * Poincare::TreePool::createTreeNode(size_t size); template MatrixDimensionNode * Poincare::TreePool::createTreeNode(size_t size); From 02b27124f4af33b4c173f99257453c6179b49e16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 5 Feb 2019 12:16:05 +0100 Subject: [PATCH 278/373] [poincare] Integer: remove duplicate method: isInfinite is equivalent to isOverflow --- poincare/include/poincare/integer.h | 9 ++++----- poincare/src/arithmetic.cpp | 4 ++-- poincare/src/ceiling.cpp | 4 ++-- poincare/src/decimal.cpp | 6 +++--- poincare/src/division_quotient.cpp | 2 +- poincare/src/division_remainder.cpp | 2 +- poincare/src/floor.cpp | 2 +- poincare/src/frac_part.cpp | 2 +- poincare/src/great_common_divisor.cpp | 2 +- poincare/src/integer.cpp | 6 +++--- poincare/src/least_common_multiple.cpp | 2 +- poincare/src/logarithm.cpp | 2 +- poincare/src/multiplication.cpp | 2 +- poincare/src/number.cpp | 2 +- poincare/src/permute_coefficient.cpp | 2 +- poincare/src/power.cpp | 8 ++++---- poincare/src/print_float.cpp | 2 +- poincare/src/rational.cpp | 10 +++++----- poincare/src/trigonometry.cpp | 2 +- poincare/test/integer.cpp | 6 +++--- 20 files changed, 38 insertions(+), 39 deletions(-) diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index ec6009b1e..61ebcf47e 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -106,13 +106,16 @@ public: // Sign // Properties + /* An integer can have (k_maxNumberOfDigits + 1) digits: either when it is an + * overflow, or when we want to have one more digit than usual to compute a + * big division. */ + bool isOverflow() const { return m_identifier == OverflowIdentifier; } static int NumberOfBase10DigitsWithoutSign(const Integer & i); bool isOne() const { return (numberOfDigits() == 1 && digit(0) == 1 && !m_negative); }; bool isTwo() const { return (numberOfDigits() == 1 && digit(0) == 2 && !m_negative); }; bool isTen() const { return (numberOfDigits() == 1 && digit(0) == 10 && !m_negative); }; bool isMinusOne() const { return (numberOfDigits() == 1 && digit(0) == 1 && m_negative); }; bool isZero() const { return (numberOfDigits() == 0); }; - bool isInfinity() const { return numberOfDigits() > k_maxNumberOfDigits; } bool isEven() const { return ((digit(0) & 1) == 0); } constexpr static int k_maxExtractableInteger = 0x7FFFFFFF; @@ -180,10 +183,6 @@ private: } bool usesImmediateDigit() const { return m_identifier == TreeNode::NoNodeIdentifier; } - /* An integer can have (k_maxNumberOfDigits + 1) digits: either when it is an - * overflow, or when we want to have one more digit than usual to compute a - * big division. */ - bool isOverflow() const { return m_identifier == OverflowIdentifier; } bool m_negative; native_uint_t m_digit; diff --git a/poincare/src/arithmetic.cpp b/poincare/src/arithmetic.cpp index 7f13e49cd..f4563db79 100644 --- a/poincare/src/arithmetic.cpp +++ b/poincare/src/arithmetic.cpp @@ -13,7 +13,7 @@ Integer Arithmetic::LCM(const Integer & a, const Integer & b) { } Integer Arithmetic::GCD(const Integer & a, const Integer & b) { - if (a.isInfinity() || b.isInfinity()) { + if (a.isOverflow() || b.isOverflow()) { return Integer::Overflow(false); } @@ -41,7 +41,7 @@ const short primeFactors[Arithmetic::k_numberOfPrimeFactors] = {2, 3, 5, 7, 11, // we can go to 7907*7907 = 62 520 649 int Arithmetic::PrimeFactorization(const Integer & n, Integer outputFactors[], Integer outputCoefficients[], int outputLength) { - assert(!n.isInfinity()); + assert(!n.isOverflow()); // Compute the absolute value of n Integer m = n; diff --git a/poincare/src/ceiling.cpp b/poincare/src/ceiling.cpp index 7233b0af3..8c28d54d2 100644 --- a/poincare/src/ceiling.cpp +++ b/poincare/src/ceiling.cpp @@ -68,14 +68,14 @@ Expression Ceiling::shallowReduce() { } Rational r = c.convert(); IntegerDivision div = Integer::Division(r.signedIntegerNumerator(), r.integerDenominator()); - assert(!div.remainder.isInfinity()); + assert(!div.remainder.isOverflow()); if (div.remainder.isZero()) { Expression result = Rational(div.quotient); replaceWithInPlace(result); return result; } Integer result = Integer::Addition(div.quotient, Integer(1)); - if (result.isInfinity()) { + if (result.isOverflow()) { return *this; } Expression rationalResult = Rational(result); diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index bbcca8d56..ebb6e2246 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -22,7 +22,7 @@ void removeZeroAtTheEnd(Integer * i) { *i = d.quotient; d = Integer::Division(*i, base); } - assert(!i->isInfinity()); + assert(!i->isOverflow()); } void DecimalNode::setValue(const native_uint_t * mantissaDigits, uint8_t mantissaSize, int exponent, bool negative) { @@ -283,7 +283,7 @@ Decimal::Decimal(const char * integralPart, int integralPartLength, const char * // Cap the length of the integralPart integralPartLength = integralPartLength > PrintFloat::k_numberOfStoredSignificantDigits ? PrintFloat::k_numberOfStoredSignificantDigits : integralPartLength; Integer numerator(integralPart, integralPartLength, false); - assert(!numerator.isInfinity()); + assert(!numerator.isOverflow()); // Special case for 0.??? : get rid of useless 0s in front of the integralPartLength if (fractionalPart != nullptr && integralPartLength == 1 && integralPart[0] == '0') { integralPartLength = 0; @@ -366,7 +366,7 @@ Expression Decimal::shallowReduce() { denominator = Integer::Power(Integer(10), Integer(numberOfDigits-1-exp)); } Expression result; - if (numerator.isInfinity() || denominator.isInfinity()) { + if (numerator.isOverflow() || denominator.isOverflow()) { result = Number::FloatNumber(node()->signedMantissa().template approximate()*std::pow(10.0, (double)exp)); } else { result = Rational(numerator, denominator); diff --git a/poincare/src/division_quotient.cpp b/poincare/src/division_quotient.cpp index 0a4d995ec..f5ca4f543 100644 --- a/poincare/src/division_quotient.cpp +++ b/poincare/src/division_quotient.cpp @@ -81,7 +81,7 @@ Expression DivisionQuotient::shallowReduce() { return result; } Integer result = Integer::Division(a, b).quotient; - assert(!result.isInfinity()); + assert(!result.isOverflow()); Expression rationalResult = Rational(result); replaceWithInPlace(rationalResult); return rationalResult; diff --git a/poincare/src/division_remainder.cpp b/poincare/src/division_remainder.cpp index 6afdfe8ca..976d2f16f 100644 --- a/poincare/src/division_remainder.cpp +++ b/poincare/src/division_remainder.cpp @@ -80,7 +80,7 @@ Expression DivisionRemainder::shallowReduce() { return result; } Integer result = Integer::Division(a, b).remainder; - assert(!result.isInfinity()); + assert(!result.isOverflow()); Expression rationalResult = Rational(result); replaceWithInPlace(rationalResult); return rationalResult; diff --git a/poincare/src/floor.cpp b/poincare/src/floor.cpp index 052011fd6..94ef4d3f4 100644 --- a/poincare/src/floor.cpp +++ b/poincare/src/floor.cpp @@ -68,7 +68,7 @@ Expression Floor::shallowReduce() { } Rational r = static_cast(c); IntegerDivision div = Integer::Division(r.signedIntegerNumerator(), r.integerDenominator()); - assert(!div.quotient.isInfinity()); + assert(!div.quotient.isOverflow()); Expression result = Rational(div.quotient); replaceWithInPlace(result); return result; diff --git a/poincare/src/frac_part.cpp b/poincare/src/frac_part.cpp index 244a0384a..1e1702760 100644 --- a/poincare/src/frac_part.cpp +++ b/poincare/src/frac_part.cpp @@ -49,7 +49,7 @@ Expression FracPart::shallowReduce() { } Rational r = static_cast(c); IntegerDivision div = Integer::Division(r.signedIntegerNumerator(), r.integerDenominator()); - assert(!div.remainder.isInfinity()); + assert(!div.remainder.isOverflow()); Integer rDenominator = r.integerDenominator(); Expression result = Rational(div.remainder, rDenominator); replaceWithInPlace(result); diff --git a/poincare/src/great_common_divisor.cpp b/poincare/src/great_common_divisor.cpp index 073318946..3697690de 100644 --- a/poincare/src/great_common_divisor.cpp +++ b/poincare/src/great_common_divisor.cpp @@ -87,7 +87,7 @@ Expression GreatCommonDivisor::shallowReduce() { Integer a = r0.signedIntegerNumerator(); Integer b = r1.signedIntegerNumerator(); Integer gcd = Arithmetic::GCD(a, b); - assert(!gcd.isInfinity()); + assert(!gcd.isOverflow()); Expression result = Rational(gcd); replaceWithInPlace(result); return result; diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 39e46d8aa..72c828fc6 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -151,7 +151,7 @@ int Integer::serialize(char * buffer, int bufferSize) const { return -1; } buffer[bufferSize-1] = 0; - if (isInfinity()) { + if (isOverflow()) { return PrintFloat::convertFloatToText(m_negative ? -INFINITY : INFINITY, buffer, bufferSize, PrintFloat::k_numberOfStoredSignificantDigits, Preferences::PrintFloatMode::Decimal); } @@ -217,7 +217,7 @@ T Integer::approximate() const { * - the mantissa is the beginning of our BigInt, discarding the first bit */ - if (isInfinity()) { + if (isOverflow()) { return m_negative ? -INFINITY : INFINITY; } @@ -273,7 +273,7 @@ T Integer::approximate() const { // Properties int Integer::NumberOfBase10DigitsWithoutSign(const Integer & i) { - assert(!i.isInfinity()); + assert(!i.isOverflow()); int numberOfDigits = 1; Integer base(10); IntegerDivision d = udiv(i, base); diff --git a/poincare/src/least_common_multiple.cpp b/poincare/src/least_common_multiple.cpp index a0679c494..0549f0a75 100644 --- a/poincare/src/least_common_multiple.cpp +++ b/poincare/src/least_common_multiple.cpp @@ -92,7 +92,7 @@ Expression LeastCommonMultiple::shallowReduce() { Integer a = r0.signedIntegerNumerator(); Integer b = r1.signedIntegerNumerator(); Integer lcm = Arithmetic::LCM(a, b); - if (lcm.isInfinity()) { + if (lcm.isOverflow()) { return *this; } Expression result = Rational(lcm); diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 8256aab9e..e812c4a39 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -295,7 +295,7 @@ Integer Logarithm::simplifyLogarithmIntegerBaseInteger(Integer i, Integer & base assert(!i.isNegative() && !base.isNegative()); assert(!i.isZero() && !base.isZero() && !base.isOne()); IntegerDivision div = Integer::Division(i, base); - while (!div.quotient.isInfinity() && div.remainder.isZero()) { + while (!div.quotient.isOverflow() && div.remainder.isZero()) { i = div.quotient; a.addChildAtIndexInPlace(isDenominator ? Rational(-1) : Rational(1), a.numberOfChildren(), a.numberOfChildren()); // a++ div = Integer::Division(i, base); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 801297f39..ac04919e1 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -623,7 +623,7 @@ void Multiplication::addMissingFactors(Expression factor, Context & context, Pre assert(static_cast(factor).integerDenominator().isOne()); assert(childAtIndex(0).convert().integerDenominator().isOne()); Integer lcm = Arithmetic::LCM(static_cast(factor).unsignedIntegerNumerator(), childAtIndex(0).convert().unsignedIntegerNumerator()); - if (lcm.isInfinity()) { + if (lcm.isOverflow()) { addChildAtIndexInPlace(Rational(static_cast(factor).unsignedIntegerNumerator()), 1, numberOfChildren()); return; } diff --git a/poincare/src/number.cpp b/poincare/src/number.cpp index d228d9d15..16e8501db 100644 --- a/poincare/src/number.cpp +++ b/poincare/src/number.cpp @@ -41,7 +41,7 @@ Number Number::ParseNumber(const char * integralPart, size_t integralLength, con // Integer if (exponentLength == 0 && decimalLenght == 0) { Integer i(integralPart, integralLength, false); - if (!i.isInfinity()) { + if (!i.isOverflow()) { return Rational(i); } } diff --git a/poincare/src/permute_coefficient.cpp b/poincare/src/permute_coefficient.cpp index b54bb81e2..61b77a357 100644 --- a/poincare/src/permute_coefficient.cpp +++ b/poincare/src/permute_coefficient.cpp @@ -103,7 +103,7 @@ Expression PermuteCoefficient::shallowReduce() { Integer factor = Integer::Subtraction(n, Integer(i)); result = Integer::Multiplication(result, factor); } - assert(!result.isInfinity()); // < permute(k_maxNValue, k_maxNValue-1)~10^158 + assert(!result.isOverflow()); // < permute(k_maxNValue, k_maxNValue-1)~10^158 Expression rationalResult = Rational(result); replaceWithInPlace(rationalResult); return rationalResult; diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 26a660c36..f9c85211e 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -37,7 +37,7 @@ ExpressionNode::Sign PowerNode::sign(Context * context) const { if (childAtIndex(0)->sign(context) == Sign::Negative && childAtIndex(1)->type() == ExpressionNode::Type::Rational) { RationalNode * r = static_cast(childAtIndex(1)); if (r->denominator().isOne()) { - assert(!Integer::Division(r->signedNumerator(), Integer(2)).remainder.isInfinity()); + assert(!Integer::Division(r->signedNumerator(), Integer(2)).remainder.isOverflow()); if (Integer::Division(r->signedNumerator(), Integer(2)).remainder.isZero()) { return Sign::Positive; } else { @@ -897,7 +897,7 @@ Expression Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational r, bo r1 = Integer::Multiplication(r1, Integer::Power(factors[index], div.quotient)); r2 = Integer::Multiplication(r2, Integer::Power(factors[index], div.remainder)); } - if (r2.isInfinity() || r1.isInfinity()) { + if (r2.isOverflow() || r1.isOverflow()) { // we overflow Integer at one point: we abort return Power(Rational(i), r.clone()); } @@ -956,7 +956,7 @@ Expression Power::removeSquareRootsFromDenominator(Context & context, Preference // We do nothing for terms of the form sqrt(p) if (!q.isOne() || castedChild1.isMinusHalf()) { Integer pq = Integer::Multiplication(p, q); - if (pq.isInfinity()) { + if (pq.isOverflow()) { return result; } Power sqrt = Power(Rational(pq), Rational(1, 2)); @@ -1031,7 +1031,7 @@ Expression Power::removeSquareRootsFromDenominator(Context & context, Preference } else { numerator = Subtraction(m1, m2); } - if (denominator.isInfinity() || factor1.isInfinity() || factor2.isInfinity() || pq1.isInfinity() || pq2.isInfinity()) { + if (denominator.isOverflow() || factor1.isOverflow() || factor2.isOverflow() || pq1.isOverflow() || pq2.isOverflow()) { return result; // Escape } numerator = numerator.deepReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); diff --git a/poincare/src/print_float.cpp b/poincare/src/print_float.cpp index d6a3e3fdc..10171fe93 100644 --- a/poincare/src/print_float.cpp +++ b/poincare/src/print_float.cpp @@ -179,7 +179,7 @@ int PrintFloat::convertFloatToTextPrivate(T f, char * buffer, int numberOfSignif /* Part III: print mantissa*10^exponent*/ int numberOfCharsForMantissaWithSign = f >= 0 ? numberOfCharsForMantissaWithoutSign : numberOfCharsForMantissaWithoutSign + 1; // Print mantissa - assert(!dividend.isInfinity()); + assert(!dividend.isOverflow()); if (numberOfCharsForMantissaWithSign >= PrintFloat::k_maxFloatBufferLength) { /* Exception 3: if we are about to overflow the buffer, we escape by * returning a big int. This will be caught by 'convertFloatToText' which diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index 623908d31..bccd82fb1 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -203,7 +203,7 @@ Rational::Rational(const char * iString, const char * jString) : Number() { } bool Rational::numeratorOrDenominatorIsInfinity() const { - return signedIntegerNumerator().isInfinity() || integerDenominator().isInfinity(); + return signedIntegerNumerator().isOverflow() || integerDenominator().isOverflow(); } // Basic operations @@ -244,17 +244,17 @@ Expression Rational::shallowReduce() { * the right behaviour would be to find the right float to represent them. * However at that point, it is too late to find it. The issue is earlier... */ #if 0 - if (unsignedIntegerNumerator().isInfinity() && integerDenominator().isInfinity()) { + if (unsignedIntegerNumerator().isOverflow() && integerDenominator().isOverflow()) { assert(false); return Undefined(); } // Turn into Infinite if the numerator is too big. - if (unsignedIntegerNumerator().isInfinity()) { + if (unsignedIntegerNumerator().isOverflow()) { assert(false); return Infinity(sign(&context) == ExpressionNode::Sign::Negative); } // Turn into 0 if the denominator is too big. - if (integerDenominator().isInfinity()) { + if (integerDenominator().isOverflow()) { assert(false); return Rational(0); } @@ -279,7 +279,7 @@ Expression Rational::denominator(Context & context, Preferences::ComplexFormat c if (d.isOne()) { return Expression(); } - if (d.isInfinity()) { + if (d.isOverflow()) { return Infinity(false); } return Rational(d); diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 832ca5f4a..a3832d366 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -215,7 +215,7 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& co unaryCoefficient *= -1; } } - if (div.remainder.isInfinity()) { + if (div.remainder.isOverflow()) { return e; } // Step 4.5. Build the new result. diff --git a/poincare/test/integer.cpp b/poincare/test/integer.cpp index c5a19f493..2d1cf098e 100644 --- a/poincare/test/integer.cpp +++ b/poincare/test/integer.cpp @@ -68,9 +68,9 @@ QUIZ_CASE(poincare_integer_properties) { quiz_assert(Integer(1).isOne()); quiz_assert(!Integer(-1).isOne()); quiz_assert(!Integer(0).isOne()); - quiz_assert(OverflowedInteger().isInfinity()); // 2^32^k_maxNumberOfDigits - quiz_assert(!MaxInteger().isInfinity()); // 2^32^k_maxNumberOfDigits-1 - quiz_assert(!Integer(0).isInfinity()); + quiz_assert(OverflowedInteger().isOverflow()); // 2^32^k_maxNumberOfDigits + quiz_assert(!MaxInteger().isOverflow()); // 2^32^k_maxNumberOfDigits-1 + quiz_assert(!Integer(0).isOverflow()); quiz_assert(Integer(8).isEven()); quiz_assert(!Integer(7).isEven()); quiz_assert(Integer(-8).isEven()); From 2b19a02b6a7b9030a08e957534306c03cde6914b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 5 Feb 2019 14:55:11 +0100 Subject: [PATCH 279/373] [poincare] Integer: avoid easy stack overflow by using static working buffer for integer operations --- poincare/src/integer.cpp | 45 ++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 72c828fc6..624cb0062 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -15,6 +15,15 @@ namespace Poincare { static inline int max(int x, int y) { return (x>y ? x : y); } +/* To compute operations between Integers, we need an array where to store the + * result digits. Instead of allocating it on the stack which would eventually + * lead to a stack overflow, we keep a static working buffer. We actually need + * two of them because division involves inner multiplications and additions + * (which would override the division digits if there were using the same + * buffer). */ +static native_uint_t s_workingBuffer[Integer::k_maxNumberOfDigits + 1]; +static native_uint_t s_workingBufferDivision[Integer::k_maxNumberOfDigits + 1]; + uint8_t log2(native_uint_t v) { constexpr int nativeUnsignedIntegerBitCount = 8*sizeof(native_uint_t); static_assert(nativeUnsignedIntegerBitCount < 256, "uint8_t cannot contain the log2 of a native_uint_t"); @@ -371,8 +380,7 @@ Integer Integer::multiplication(const Integer & a, const Integer & b, bool oneDi uint8_t size = min(a.numberOfDigits() + b.numberOfDigits(), k_maxNumberOfDigits + oneDigitOverflow); // Enable overflowing of 1 digit - native_uint_t digits[k_maxNumberOfDigits + 1]; - memset(digits, 0, size*sizeof(native_uint_t)); + memset(s_workingBuffer, 0, size*sizeof(native_uint_t)); double_native_uint_t carry = 0; for (uint8_t i = 0; i < a.numberOfDigits(); i++) { @@ -383,10 +391,10 @@ Integer Integer::multiplication(const Integer & a, const Integer & b, bool oneDi /* The fact that aDigit and bDigit are double_native is very important, * otherwise the product might end up being computed on single_native size * and then zero-padded. */ - double_native_uint_t p = aDigit*bDigit + carry + (double_native_uint_t)(digits[i+j]); // TODO: Prove it cannot overflow double_native type + double_native_uint_t p = aDigit*bDigit + carry + (double_native_uint_t)(s_workingBuffer[i+j]); // TODO: Prove it cannot overflow double_native type native_uint_t * l = (native_uint_t *)&p; if (i+j < (uint8_t) k_maxNumberOfDigits+oneDigitOverflow) { - digits[i+j] = l[0]; + s_workingBuffer[i+j] = l[0]; } else { if (l[0] != 0) { // Overflow the largest Integer @@ -396,7 +404,7 @@ Integer Integer::multiplication(const Integer & a, const Integer & b, bool oneDi carry = l[1]; } if (i+b.numberOfDigits() < (uint8_t) k_maxNumberOfDigits+oneDigitOverflow) { - digits[i+b.numberOfDigits()] += carry; + s_workingBuffer[i+b.numberOfDigits()] += carry; } else { if (carry != 0) { // Overflow the largest Integer @@ -404,10 +412,10 @@ Integer Integer::multiplication(const Integer & a, const Integer & b, bool oneDi } } } - while (size>0 && digits[size-1] == 0) { + while (size>0 && s_workingBuffer[size-1] == 0) { size--; } - return BuildInteger(digits, size, a.m_negative != b.m_negative, oneDigitOverflow); + return BuildInteger(s_workingBuffer, size, a.m_negative != b.m_negative, oneDigitOverflow); } int8_t Integer::ucmp(const Integer & a, const Integer & b) { @@ -444,14 +452,13 @@ Integer Integer::usum(const Integer & a, const Integer & b, bool subtract, bool // Addition can overflow size++; } - native_uint_t digits[k_maxNumberOfDigits+1]; bool carry = false; for (uint8_t i = 0; i < size; i++) { native_uint_t aDigit = (i >= a.numberOfDigits() ? 0 : a.digit(i)); native_uint_t bDigit = (i >= b.numberOfDigits() ? 0 : b.digit(i)); native_uint_t result = (subtract ? aDigit - bDigit - carry : aDigit + bDigit + carry); if (i < (uint8_t) (k_maxNumberOfDigits + oneDigitOverflow)) { - digits[i] = result; + s_workingBuffer[i] = result; } else { if (result != 0) { // Overflow the largest Integer @@ -465,39 +472,37 @@ Integer Integer::usum(const Integer & a, const Integer & b, bool subtract, bool } } size = min(size, k_maxNumberOfDigits+oneDigitOverflow); - while (size>0 && digits[size-1] == 0) { + while (size>0 && s_workingBuffer[size-1] == 0) { size--; } - return BuildInteger(digits, size, false, oneDigitOverflow); + return BuildInteger(s_workingBuffer, size, false, oneDigitOverflow); } Integer Integer::multiplyByPowerOf2(uint8_t pow) const { assert(pow < 32); - native_uint_t digits[k_maxNumberOfDigits+1]; native_uint_t carry = 0; for (uint8_t i = 0; i < numberOfDigits(); i++) { - digits[i] = digit(i) << pow | carry; + s_workingBuffer[i] = digit(i) << pow | carry; carry = pow == 0 ? 0 : digit(i) >> (32-pow); } - digits[numberOfDigits()] = carry; - return BuildInteger(digits, carry ? numberOfDigits() + 1 : numberOfDigits(), false, true); + s_workingBuffer[numberOfDigits()] = carry; + return BuildInteger(s_workingBuffer, carry ? numberOfDigits() + 1 : numberOfDigits(), false, true); } Integer Integer::divideByPowerOf2(uint8_t pow) const { assert(pow < 32); - native_uint_t digits[k_maxNumberOfDigits+1]; native_uint_t carry = 0; for (int i = numberOfDigits() - 1; i >= 0; i--) { - digits[i] = digit(i) >> pow | carry; + s_workingBuffer[i] = digit(i) >> pow | carry; carry = pow == 0 ? 0 : digit(i) << (32-pow); } - return BuildInteger(digits, digits[numberOfDigits()-1] > 0 ? numberOfDigits() : numberOfDigits()-1, false, true); + return BuildInteger(s_workingBuffer, s_workingBuffer[numberOfDigits()-1] > 0 ? numberOfDigits() : numberOfDigits()-1, false, true); } // return this*(2^16)^pow Integer Integer::multiplyByPowerOfBase(uint8_t pow) const { int nbOfHalfDigits = numberOfHalfDigits(); - half_native_uint_t digits[2*(k_maxNumberOfDigits+1)]; + half_native_uint_t * digits = reinterpret_cast(s_workingBuffer); /* The number of half digits of the built integer is nbOfHalfDigits+pow. * Still, we set an extra half digit to 0 to easily convert half digits to * digits. */ @@ -543,7 +548,7 @@ IntegerDivision Integer::udiv(const Integer & numerator, const Integer & denomin int n = B.numberOfHalfDigits(); int m = A.numberOfHalfDigits()-n; // qDigits is a half_native_uint_t array and enable one digit overflow - half_native_uint_t qDigits[2*k_maxNumberOfDigits]; + half_native_uint_t * qDigits = reinterpret_cast(s_workingBufferDivision); // The quotient q has at maximum m+1 half digits but we set an extra half digit to 0 to enable to easily convert it from half digits to digits memset(qDigits, 0, max(m+1+1,2*k_maxNumberOfDigits)*sizeof(half_native_uint_t)); // betaMB = B*beta^m From 535dee8220a79359c48ca2c2d1a60c131b502a81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 5 Feb 2019 16:17:43 +0100 Subject: [PATCH 280/373] [poincare] Integer: add TODO --- poincare/src/integer.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 624cb0062..361ce2955 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -21,6 +21,8 @@ static inline int max(int x, int y) { return (x>y ? x : y); } * two of them because division involves inner multiplications and additions * (which would override the division digits if there were using the same * buffer). */ +// TODO: we might want to go back to allocating the native_uint_t arrays on the stack once we increase the stack size from 32k to? + static native_uint_t s_workingBuffer[Integer::k_maxNumberOfDigits + 1]; static native_uint_t s_workingBufferDivision[Integer::k_maxNumberOfDigits + 1]; From 4a8c0a6bd0258f5959d13bb6b4de132a2da050e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 5 Feb 2019 15:29:42 +0100 Subject: [PATCH 281/373] [apps/code] Do not change the responders in autoImportScript if sandbox This fixes the following scenario: create a script that draws at importation (for instance, add "squares()" at the end of squares.py) and execute this script. The sandbox is displayed but events are handled by the underneath text field, thus leading to the display of the variable box and other bugs. --- apps/code/console_controller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/code/console_controller.cpp b/apps/code/console_controller.cpp index a316aab68..926e7d92e 100644 --- a/apps/code/console_controller.cpp +++ b/apps/code/console_controller.cpp @@ -386,7 +386,7 @@ void ConsoleController::autoImportScript(Script script, bool force) { // Step 2 - Run the command runAndPrintForCommand(command); } - if (force) { + if (!sandboxIsDisplayed() && force) { m_selectableTableView.reloadData(); m_selectableTableView.selectCellAtLocation(0, m_consoleStore.numberOfLines()); m_editCell.setEditing(true); From a021af46fe1f5294fab946790a4b62075000248b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 5 Feb 2019 16:15:41 +0100 Subject: [PATCH 282/373] [apps/code] Hide the sandbox between script importations --- apps/code/console_controller.cpp | 13 +++++++++++++ apps/code/console_controller.h | 1 + apps/code/sandbox_controller.cpp | 4 ++++ apps/code/sandbox_controller.h | 1 + python/port/port.h | 1 + 5 files changed, 20 insertions(+) diff --git a/apps/code/console_controller.cpp b/apps/code/console_controller.cpp index 926e7d92e..d325669be 100644 --- a/apps/code/console_controller.cpp +++ b/apps/code/console_controller.cpp @@ -332,6 +332,13 @@ void ConsoleController::displaySandbox() { stackViewController()->push(&m_sandboxController); } +void ConsoleController::hideSandbox() { + if (!sandboxIsDisplayed()) { + return; + } + m_sandboxController.hide(); +} + void ConsoleController::resetSandbox() { if (!sandboxIsDisplayed()) { return; @@ -364,6 +371,12 @@ void ConsoleController::printText(const char * text, size_t length) { } void ConsoleController::autoImportScript(Script script, bool force) { + if (sandboxIsDisplayed()) { + /* The sandbox might be displayed, for instance if we are auto-importing + * several scripts that draw at importation. In this case, we want to remove + * the sandbox. */ + hideSandbox(); + } if (script.importationStatus() || force) { // Step 1 - Create the command "from scriptName import *". diff --git a/apps/code/console_controller.h b/apps/code/console_controller.h index 2a672ba33..d39f6edfe 100644 --- a/apps/code/console_controller.h +++ b/apps/code/console_controller.h @@ -62,6 +62,7 @@ public: // MicroPython::ExecutionEnvironment void displaySandbox() override; + void hideSandbox() override; void resetSandbox() override; void printText(const char * text, size_t length) override; const char * inputText(const char * prompt) override; diff --git a/apps/code/sandbox_controller.cpp b/apps/code/sandbox_controller.cpp index ce49f38b4..12b5f0332 100644 --- a/apps/code/sandbox_controller.cpp +++ b/apps/code/sandbox_controller.cpp @@ -20,6 +20,10 @@ void SandboxController::reset() { redrawWindow(); } +void SandboxController::hide() { + stackViewController()->pop(); +} + void SandboxController::viewWillAppear() { assert(m_executionEnvironment != nullptr); m_executionEnvironment->setSandboxIsDisplayed(true); diff --git a/apps/code/sandbox_controller.h b/apps/code/sandbox_controller.h index df0b81999..c50725789 100644 --- a/apps/code/sandbox_controller.h +++ b/apps/code/sandbox_controller.h @@ -14,6 +14,7 @@ public: SandboxController(Responder * parentResponder, MicroPython::ExecutionEnvironment * executionEnvironment); StackViewController * stackViewController(); void reset(); + void hide(); // ViewController View * view() override { return &m_solidColorView; } diff --git a/python/port/port.h b/python/port/port.h index 29219d073..f0b3a0407 100644 --- a/python/port/port.h +++ b/python/port/port.h @@ -19,6 +19,7 @@ public: void runCode(const char * ); virtual const char * inputText(const char * prompt) { return nullptr; } virtual void displaySandbox() {} + virtual void hideSandbox() {} virtual void resetSandbox() {} virtual void printText(const char * text, size_t length) {} void interrupt(); From a25b2a8ce5fe8d94183de6ccfaf620c301f06568 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 5 Feb 2019 16:54:50 +0100 Subject: [PATCH 283/373] [python/turtle] Fix unwanted dotted lines Script: fd(200) left(90) fd(10) left(90) fd(600) The final line should be continuous but is dotted --- python/port/mod/turtle/turtle.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/python/port/mod/turtle/turtle.cpp b/python/port/mod/turtle/turtle.cpp index 3a3499750..f7cd49c5c 100644 --- a/python/port/mod/turtle/turtle.cpp +++ b/python/port/mod/turtle/turtle.cpp @@ -76,16 +76,23 @@ void Turtle::circle(mp_int_t radius, mp_float_t angle) { bool Turtle::goTo(mp_float_t x, mp_float_t y) { mp_float_t oldx = m_x; mp_float_t oldy = m_y; - mp_float_t length = maxF(absF(floor(x) - floor(oldx)), absF(floor(y) - floor(oldy))); + mp_float_t xLength = absF(floor(x) - floor(oldx)); + mp_float_t yLength = absF(floor(y) - floor(oldy)); + bool principalDirectionIsX = xLength >= yLength; + mp_float_t length = principalDirectionIsX ? xLength : yLength; if (length > 1) { // Tweening function for (int i = 1; i < length; i++) { mp_float_t progress = i / length; erase(); - if (dot(x * progress + oldx * (1 - progress), y * progress + oldy * (1 - progress)) - || draw(false)) - { + /* We make sure that each pixel along the principal direction is drawn. If + * the computation of the position on the principal coordinate is done + * using a barycenter, roundings might skip some pixels, which results in + * a dotted line. */ + mp_float_t currentX = principalDirectionIsX ? oldx + (x > oldx ? i : -i) : x * progress + oldx * (1 - progress); + mp_float_t currentY = principalDirectionIsX ? y * progress + oldy * (1 - progress) : oldy + (y > oldy ? i : -i); + if (dot(currentX, currentY) || draw(false)) { // Keyboard interruption. Return now to let MicroPython process it. return true; } From 287dedabc014305c37551958c3e0eef475a149f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 5 Feb 2019 17:32:55 +0100 Subject: [PATCH 284/373] [python/turtle] The turtle heading is in [0;360[ --- python/port/mod/turtle/turtle.cpp | 7 +++++++ python/port/mod/turtle/turtle.h | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/python/port/mod/turtle/turtle.cpp b/python/port/mod/turtle/turtle.cpp index f7cd49c5c..98d0c6330 100644 --- a/python/port/mod/turtle/turtle.cpp +++ b/python/port/mod/turtle/turtle.cpp @@ -175,6 +175,13 @@ void Turtle::viewDidDisappear() { // Private functions +void Turtle::setHeadingPrivate(mp_float_t angle) { + // Put the angle in [0; 360[ + mp_float_t angleLimit = 360; + m_heading = angle - ((angle >= 0 && angle < angleLimit) ? 0 : std::floor(angle/angleLimit) * angleLimit); + assert(m_heading >= 0 && m_heading < angleLimit); +} + KDPoint Turtle::position(mp_float_t x, mp_float_t y) const { return KDPoint(floor(x + k_xOffset), floor(k_invertedYAxisCoefficient * y + k_yOffset)); } diff --git a/python/port/mod/turtle/turtle.h b/python/port/mod/turtle/turtle.h index 987d73a90..2b9d83b9c 100644 --- a/python/port/mod/turtle/turtle.h +++ b/python/port/mod/turtle/turtle.h @@ -115,7 +115,7 @@ private: KDColor m_color; }; - void setHeadingPrivate(mp_float_t angle) { m_heading = angle; } + void setHeadingPrivate(mp_float_t angle); KDPoint position(mp_float_t x, mp_float_t y) const; KDPoint position() const { return position(m_x, m_y); } From b5e278526fdb184380e0809d9ada5c1927510278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 6 Feb 2019 10:21:51 +0100 Subject: [PATCH 285/373] [python/turtle] Use namespace std --- python/port/mod/turtle/turtle.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/port/mod/turtle/turtle.cpp b/python/port/mod/turtle/turtle.cpp index 98d0c6330..d1268bdb5 100644 --- a/python/port/mod/turtle/turtle.cpp +++ b/python/port/mod/turtle/turtle.cpp @@ -76,8 +76,8 @@ void Turtle::circle(mp_int_t radius, mp_float_t angle) { bool Turtle::goTo(mp_float_t x, mp_float_t y) { mp_float_t oldx = m_x; mp_float_t oldy = m_y; - mp_float_t xLength = absF(floor(x) - floor(oldx)); - mp_float_t yLength = absF(floor(y) - floor(oldy)); + mp_float_t xLength = absF(std::floor(x) - std::floor(oldx)); + mp_float_t yLength = absF(std::floor(y) - std::floor(oldy)); bool principalDirectionIsX = xLength >= yLength; mp_float_t length = principalDirectionIsX ? xLength : yLength; @@ -183,7 +183,7 @@ void Turtle::setHeadingPrivate(mp_float_t angle) { } KDPoint Turtle::position(mp_float_t x, mp_float_t y) const { - return KDPoint(floor(x + k_xOffset), floor(k_invertedYAxisCoefficient * y + k_yOffset)); + return KDPoint(std::floor(x + k_xOffset), std::floor(k_invertedYAxisCoefficient * y + k_yOffset)); } bool Turtle::hasUnderneathPixelBuffer() { From 3faee8bcd8aba13ea055612d7932fb9cc40f0ce8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 5 Feb 2019 17:34:19 +0100 Subject: [PATCH 286/373] [python/turtle] Special case when goTo draws horizontal/vertical line --- python/port/mod/turtle/turtle.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/python/port/mod/turtle/turtle.cpp b/python/port/mod/turtle/turtle.cpp index d1268bdb5..dfc8f90fc 100644 --- a/python/port/mod/turtle/turtle.cpp +++ b/python/port/mod/turtle/turtle.cpp @@ -7,7 +7,6 @@ extern "C" { #include "../../helpers.h" #include "../../port.h" -static inline mp_float_t maxF(mp_float_t x, mp_float_t y) { return x >= y ? x : y;} static inline mp_float_t absF(mp_float_t x) { return x >= 0 ? x : -x;} static constexpr KDCoordinate k_iconSize = 15; @@ -45,6 +44,23 @@ void Turtle::reset() { } bool Turtle::forward(mp_float_t length) { + /* cos and sin use radians, we thus need to multiply m_heading by PI/180 to + * compute the new turtle position. This induces rounding errors that are + * really visible when one expects a horizontal/vertical line and it is not. + * We thus make special cases for angles in degrees creating vertical / + * horizontal lines. */ + if (m_heading == 0) { + return goTo(m_x + length, m_y); + } + if (m_heading == 180 || m_heading == -180) { + return goTo(m_x - length, m_y); + } + if (m_heading == 90 || m_heading == -270) { + return goTo(m_x, m_y + length); + } + if (m_heading == 270 || m_heading == -90) { + return goTo(m_x, m_y - length); + } return goTo( m_x + length * std::cos(m_heading * k_headingScale), m_y + length * std::sin(m_heading * k_headingScale) From a036bff2758e32a08baba9b4042c5bed9a4ddb9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 11 Feb 2019 12:05:36 +0100 Subject: [PATCH 287/373] [python/turtle] Fix setHeadingPrivate (handle big angle errors) --- python/port/mod/turtle/turtle.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/python/port/mod/turtle/turtle.cpp b/python/port/mod/turtle/turtle.cpp index dfc8f90fc..48d66c173 100644 --- a/python/port/mod/turtle/turtle.cpp +++ b/python/port/mod/turtle/turtle.cpp @@ -194,8 +194,13 @@ void Turtle::viewDidDisappear() { void Turtle::setHeadingPrivate(mp_float_t angle) { // Put the angle in [0; 360[ mp_float_t angleLimit = 360; - m_heading = angle - ((angle >= 0 && angle < angleLimit) ? 0 : std::floor(angle/angleLimit) * angleLimit); - assert(m_heading >= 0 && m_heading < angleLimit); + mp_float_t angleBetween0And360 = angle - ((angle >= 0 && angle < angleLimit) ? 0 : std::floor(angle/angleLimit) * angleLimit); + if (angleBetween0And360 >= 0 && angleBetween0And360 < angleLimit) { + m_heading = angleBetween0And360; + } else { + // When angle is too big, our formula does not put it properly in [0; 360[ + m_heading = 0; + } } KDPoint Turtle::position(mp_float_t x, mp_float_t y) const { From c901b31fded65c0a83e510ef2062af98a4291343 Mon Sep 17 00:00:00 2001 From: RomanWu <47526796+RomanWu@users.noreply.github.com> Date: Mon, 11 Feb 2019 14:00:54 +0100 Subject: [PATCH 288/373] Fix typo base.de.i18n German translation of "About" should not start with two uppercase letters. --- apps/settings/base.de.i18n | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/settings/base.de.i18n b/apps/settings/base.de.i18n index 9be89f426..b0a434359 100644 --- a/apps/settings/base.de.i18n +++ b/apps/settings/base.de.i18n @@ -9,7 +9,7 @@ ComplexFormat = "Komplex" ExamMode = "Testmodus" ActivateExamMode = "Start Testmodus" ExamModeActive = "Testmodus: aktiv" -About = "UEber" +About = "Ueber" Degres = "Grad " Radian = "Bogenmass " Decimal = "Dezimal " From dea27932d48ac83d60c20e4a2852634f175ed684 Mon Sep 17 00:00:00 2001 From: Roman Wueest <47526796+RomanWu@users.noreply.github.com> Date: Tue, 12 Feb 2019 13:35:16 +0100 Subject: [PATCH 289/373] Fix for German typos in variables.de.i18n "Expressions" was not German so far, I suggest "Ausdruecke" The correct plural of function in German is "Funktionen". "Namen" is a noun, and therefore written uppercase in German. --- apps/variables.de.i18n | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/variables.de.i18n b/apps/variables.de.i18n index ffe0c55c7..60817027e 100644 --- a/apps/variables.de.i18n +++ b/apps/variables.de.i18n @@ -1,10 +1,10 @@ Variables = "Variablen" -Expressions = "Expressions" -Functions = "Funktions" +Expressions = "Ausdruecke" +Functions = "Funktionen" EmptyExpressionBox0 = "Sie haben keine Variable definiert." EmptyFunctionBox0 = "Sie haben keine Funktion definiert." EmptyExpressionBox1 = "Um eine Variable zu definieren:" EmptyFunctionBox1 = "Um eine Funktion zu definieren:" -EmptyExpressionBox2 = "Erlaubte Zeichen im namen:" -EmptyFunctionBox2 = "Erlaubte Zeichen im namen:" +EmptyExpressionBox2 = "Erlaubte Zeichen im Namen:" +EmptyFunctionBox2 = "Erlaubte Zeichen im Namen:" EnableCharacters = "A..Z, a..z, 0..9 und _" From 3402721069d8f34ea21697d3af2e9ae7b3d231f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 13 Feb 2019 15:19:18 +0100 Subject: [PATCH 290/373] [poincare] Test: Add a parameter ReductionTarget (User or System) in Helper::assert_parsed_expression_evaluates_to and Helper::assert_parsed_expression_simplify_to --- poincare/test/complex.cpp | 246 +++++------ poincare/test/complex_to_expression.cpp | 70 ++-- poincare/test/function.cpp | 14 +- poincare/test/helper.cpp | 45 +- poincare/test/helper.h | 6 +- poincare/test/parser.cpp | 8 +- poincare/test/power.cpp | 10 +- poincare/test/trigo.cpp | 520 ++++++++++++------------ 8 files changed, 468 insertions(+), 451 deletions(-) diff --git a/poincare/test/complex.cpp b/poincare/test/complex.cpp index 469fce7d9..f72f26bb5 100644 --- a/poincare/test/complex.cpp +++ b/poincare/test/complex.cpp @@ -8,172 +8,172 @@ using namespace Poincare; QUIZ_CASE(poincare_complex_evaluate) { // Real - assert_parsed_expression_evaluates_to("I", "unreal", Radian, Real); - assert_parsed_expression_evaluates_to("R(-1)", "unreal", Radian, Real); - assert_parsed_expression_evaluates_to("R(-1)*R(-1)", "unreal", Radian, Real); - assert_parsed_expression_evaluates_to("ln(-2)", "unreal", Radian, Real); - assert_parsed_expression_evaluates_to("(-8)^(1/3)", "-2", Radian, Real); - assert_parsed_expression_evaluates_to("8^(1/3)", "2", Radian, Real); - assert_parsed_expression_evaluates_to("(-8)^(2/3)", "4", Radian, Real); + assert_parsed_expression_evaluates_to("I", "unreal", System, Radian, Real); + assert_parsed_expression_evaluates_to("R(-1)", "unreal", System, Radian, Real); + assert_parsed_expression_evaluates_to("R(-1)*R(-1)", "unreal", System, Radian, Real); + assert_parsed_expression_evaluates_to("ln(-2)", "unreal", System, Radian, Real); + assert_parsed_expression_evaluates_to("(-8)^(1/3)", "-2", System, Radian, Real); + assert_parsed_expression_evaluates_to("8^(1/3)", "2", System, Radian, Real); + assert_parsed_expression_evaluates_to("(-8)^(2/3)", "4", System, Radian, Real); assert_parsed_expression_evaluates_without_simplifying_to("root(-8,3)", "-2", Radian, Real); // Cartesian - assert_parsed_expression_evaluates_to("I", "I", Radian, Cartesian); - assert_parsed_expression_evaluates_to("R(-1)", "I", Radian, Cartesian); - assert_parsed_expression_evaluates_to("R(-1)*R(-1)", "-1", Radian, Cartesian); - assert_parsed_expression_evaluates_to("ln(-2)", "6.9314718055995E-1+3.1415926535898*I", Radian, Cartesian); - assert_parsed_expression_evaluates_to("(-8)^(1/3)", "1+1.7320508075689*I", Radian, Cartesian); - assert_parsed_expression_evaluates_to("(-8)^(2/3)", "-2+3.464102*I", Radian, Cartesian); + assert_parsed_expression_evaluates_to("I", "I", System, Radian, Cartesian); + assert_parsed_expression_evaluates_to("R(-1)", "I", System, Radian, Cartesian); + assert_parsed_expression_evaluates_to("R(-1)*R(-1)", "-1", System, Radian, Cartesian); + assert_parsed_expression_evaluates_to("ln(-2)", "6.9314718055995E-1+3.1415926535898*I", System, Radian, Cartesian); + assert_parsed_expression_evaluates_to("(-8)^(1/3)", "1+1.7320508075689*I", System, Radian, Cartesian); + assert_parsed_expression_evaluates_to("(-8)^(2/3)", "-2+3.464102*I", System, Radian, Cartesian); assert_parsed_expression_evaluates_without_simplifying_to("root(-8,3)", "1+1.7320508075689*I", Radian, Cartesian); // Polar - assert_parsed_expression_evaluates_to("I", "X^(1.570796*I)", Radian, Polar); - assert_parsed_expression_evaluates_to("R(-1)", "X^(1.5707963267949*I)", Radian, Polar); - assert_parsed_expression_evaluates_to("R(-1)*R(-1)", "X^(3.1415926535898*I)", Radian, Polar); - assert_parsed_expression_evaluates_to("(-8)^(1/3)", "2*X^(1.0471975511966*I)", Radian, Polar); - assert_parsed_expression_evaluates_to("(-8)^(2/3)", "4*X^(2.094395*I)", Radian, Polar); + assert_parsed_expression_evaluates_to("I", "X^(1.570796*I)", System, Radian, Polar); + assert_parsed_expression_evaluates_to("R(-1)", "X^(1.5707963267949*I)", System, Radian, Polar); + assert_parsed_expression_evaluates_to("R(-1)*R(-1)", "X^(3.1415926535898*I)", System, Radian, Polar); + assert_parsed_expression_evaluates_to("(-8)^(1/3)", "2*X^(1.0471975511966*I)", System, Radian, Polar); + assert_parsed_expression_evaluates_to("(-8)^(2/3)", "4*X^(2.094395*I)", System, Radian, Polar); assert_parsed_expression_evaluates_without_simplifying_to("root(-8,3)", "2*X^(1.0471975511966*I)", Radian, Polar); } QUIZ_CASE(poincare_complex_simplify) { // Real - assert_parsed_expression_simplify_to("I", "unreal", Radian, Real); - assert_parsed_expression_simplify_to("R(-1)", "unreal", Radian, Real); - assert_parsed_expression_simplify_to("R(-1)*R(-1)", "unreal", Radian, Real); - assert_parsed_expression_simplify_to("ln(-2)", "ln(-2)", Radian, Real); - assert_parsed_expression_simplify_to("(-8)^(2/3)", "4", Radian, Real); - assert_parsed_expression_simplify_to("(-8)^(2/5)", "2*root(2,5)", Radian, Real); - assert_parsed_expression_simplify_to("(-8)^(1/5)", "-root(8,5)", Radian, Real); - assert_parsed_expression_simplify_to("(-8)^(1/4)", "unreal", Radian, Real); - assert_parsed_expression_simplify_to("(-8)^(1/3)", "-2", Radian, Real); + assert_parsed_expression_simplify_to("I", "unreal", User, Radian, Real); + assert_parsed_expression_simplify_to("R(-1)", "unreal", User, Radian, Real); + assert_parsed_expression_simplify_to("R(-1)*R(-1)", "unreal", User, Radian, Real); + assert_parsed_expression_simplify_to("ln(-2)", "ln(-2)", User, Radian, Real); + assert_parsed_expression_simplify_to("(-8)^(2/3)", "4", User, Radian, Real); + assert_parsed_expression_simplify_to("(-8)^(2/5)", "2*root(2,5)", User, Radian, Real); + assert_parsed_expression_simplify_to("(-8)^(1/5)", "-root(8,5)", User, Radian, Real); + assert_parsed_expression_simplify_to("(-8)^(1/4)", "unreal", User, Radian, Real); + assert_parsed_expression_simplify_to("(-8)^(1/3)", "-2", User, Radian, Real); // Cartesian - assert_parsed_expression_simplify_to("-2.3E3", "-2300", Radian, Cartesian); - assert_parsed_expression_simplify_to("3", "3", Radian, Cartesian); - assert_parsed_expression_simplify_to("inf", "inf", Radian, Cartesian); - assert_parsed_expression_simplify_to("1+2+I", "3+I", Radian, Cartesian); - assert_parsed_expression_simplify_to("-(5+2*I)", "-5-2*I", Radian, Cartesian); - assert_parsed_expression_simplify_to("(5+2*I)", "5+2*I", Radian, Cartesian); - assert_parsed_expression_simplify_to("I+I", "2*I", Radian, Cartesian); - assert_parsed_expression_simplify_to("-2+2*I", "-2+2*I", Radian, Cartesian); - assert_parsed_expression_simplify_to("(3+I)-(2+4*I)", "1-3*I", Radian, Cartesian); - assert_parsed_expression_simplify_to("(2+3*I)*(4-2*I)", "14+8*I", Radian, Cartesian); - assert_parsed_expression_simplify_to("(3+I)/2", "3/2+1/2*I", Radian, Cartesian); - assert_parsed_expression_simplify_to("(3+I)/(2+I)", "7/5-1/5*I", Radian, Cartesian); + assert_parsed_expression_simplify_to("-2.3E3", "-2300", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("3", "3", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("inf", "inf", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("1+2+I", "3+I", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("-(5+2*I)", "-5-2*I", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("(5+2*I)", "5+2*I", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("I+I", "2*I", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("-2+2*I", "-2+2*I", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("(3+I)-(2+4*I)", "1-3*I", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("(2+3*I)*(4-2*I)", "14+8*I", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("(3+I)/2", "3/2+1/2*I", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("(3+I)/(2+I)", "7/5-1/5*I", User, Radian, Cartesian); // The simplification of (3+I)^(2+I) in a Cartesian complex form generates to many nodes - //assert_parsed_expression_simplify_to("(3+I)^(2+I)", "10*cos((-4*atan(3)+ln(2)+ln(5)+2*P)/2)*X^((2*atan(3)-P)/2)+10*sin((-4*atan(3)+ln(2)+ln(5)+2*P)/2)*X^((2*atan(3)-P)/2)*I", Radian, Cartesian); - assert_parsed_expression_simplify_to("(3+I)^(2+I)", "(I+3)^(I+2)", Radian, Cartesian); - assert_parsed_expression_simplify_to("R(1+6I)", "R(2*R(37)+2)/2+R(2*R(37)-2)/2*I", Radian, Cartesian); - assert_parsed_expression_simplify_to("(1+I)^2", "2*I", Radian, Cartesian); - assert_parsed_expression_simplify_to("2*I", "2*I", Radian, Cartesian); - assert_parsed_expression_simplify_to("I!", "I!", Radian, Cartesian); - assert_parsed_expression_simplify_to("3!", "6", Radian, Cartesian); - assert_parsed_expression_simplify_to("x!", "x!", Radian, Cartesian); - assert_parsed_expression_simplify_to("X", "X", Radian, Cartesian); - assert_parsed_expression_simplify_to("P", "P", Radian, Cartesian); - assert_parsed_expression_simplify_to("I", "I", Radian, Cartesian); + //assert_parsed_expression_simplify_to("(3+I)^(2+I)", "10*cos((-4*atan(3)+ln(2)+ln(5)+2*P)/2)*X^((2*atan(3)-P)/2)+10*sin((-4*atan(3)+ln(2)+ln(5)+2*P)/2)*X^((2*atan(3)-P)/2)*I", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("(3+I)^(2+I)", "(I+3)^(I+2)", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("R(1+6I)", "R(2*R(37)+2)/2+R(2*R(37)-2)/2*I", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("(1+I)^2", "2*I", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("2*I", "2*I", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("I!", "I!", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("3!", "6", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("x!", "x!", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("X", "X", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("P", "P", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("I", "I", User, Radian, Cartesian); - assert_parsed_expression_simplify_to("abs(-3)", "3", Radian, Cartesian); - assert_parsed_expression_simplify_to("abs(-3+I)", "R(10)", Radian, Cartesian); - assert_parsed_expression_simplify_to("atan(2)", "atan(2)", Radian, Cartesian); - assert_parsed_expression_simplify_to("atan(2+I)", "atan(2+I)", Radian, Cartesian); - assert_parsed_expression_simplify_to("binomial(10, 4)", "210", Radian, Cartesian); - assert_parsed_expression_simplify_to("ceil(-1.3)", "-1", Radian, Cartesian); - assert_parsed_expression_simplify_to("arg(-2)", "P", Radian, Cartesian); + assert_parsed_expression_simplify_to("abs(-3)", "3", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("abs(-3+I)", "R(10)", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("atan(2)", "atan(2)", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("atan(2+I)", "atan(2+I)", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("binomial(10, 4)", "210", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("ceil(-1.3)", "-1", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("arg(-2)", "P", User, Radian, Cartesian); // TODO: confidence is not simplified yet - //assert_parsed_expression_simplify_to("confidence(-2,-3)", "confidence(-2)", Radian, Cartesian); - assert_parsed_expression_simplify_to("conj(-2)", "-2", Radian, Cartesian); - assert_parsed_expression_simplify_to("conj(-2+2*I+I)", "-2-3*I", Radian, Cartesian); - assert_parsed_expression_simplify_to("cos(12)", "cos(12)", Radian, Cartesian); - assert_parsed_expression_simplify_to("cos(12+I)", "cos(12+I)", Radian, Cartesian); - assert_parsed_expression_simplify_to("diff(3*x, x, 3)", "diff(3*x,x,3)", Radian, Cartesian); - assert_parsed_expression_simplify_to("quo(34,x)", "quo(34,x)", Radian, Cartesian); - assert_parsed_expression_simplify_to("rem(5,3)", "2", Radian, Cartesian); - assert_parsed_expression_simplify_to("floor(x)", "floor(x)", Radian, Cartesian); - assert_parsed_expression_simplify_to("frac(x)", "frac(x)", Radian, Cartesian); - assert_parsed_expression_simplify_to("gcd(x,y)", "gcd(x,y)", Radian, Cartesian); - assert_parsed_expression_simplify_to("im(1+I)", "1", Radian, Cartesian); - assert_parsed_expression_simplify_to("int(x^2, x, 1, 2)", "int(x^2,x,1,2)", Radian, Cartesian); - assert_parsed_expression_simplify_to("lcm(x,y)", "lcm(x,y)", Radian, Cartesian); + //assert_parsed_expression_simplify_to("confidence(-2,-3)", "confidence(-2)", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("conj(-2)", "-2", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("conj(-2+2*I+I)", "-2-3*I", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("cos(12)", "cos(12)", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("cos(12+I)", "cos(12+I)", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("diff(3*x, x, 3)", "diff(3*x,x,3)", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("quo(34,x)", "quo(34,x)", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("rem(5,3)", "2", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("floor(x)", "floor(x)", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("frac(x)", "frac(x)", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("gcd(x,y)", "gcd(x,y)", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("im(1+I)", "1", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("int(x^2, x, 1, 2)", "int(x^2,x,1,2)", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("lcm(x,y)", "lcm(x,y)", User, Radian, Cartesian); // TODO: dim is not simplified yet - //assert_parsed_expression_simplify_to("dim(x)", "dim(x)", Radian, Cartesian); + //assert_parsed_expression_simplify_to("dim(x)", "dim(x)", User, Radian, Cartesian); - assert_parsed_expression_simplify_to("root(2,I)", "cos(ln(2))-sin(ln(2))*I", Radian, Cartesian); - assert_parsed_expression_simplify_to("root(2,I+1)", "R(2)*cos((90*ln(2))/P)-R(2)*sin((90*ln(2))/P)*I", Degree, Cartesian); - assert_parsed_expression_simplify_to("root(2,I+1)", "R(2)*cos(ln(2)/2)-R(2)*sin(ln(2)/2)*I", Radian, Cartesian); - assert_parsed_expression_simplify_to("permute(10, 4)", "5040", Radian, Cartesian); + assert_parsed_expression_simplify_to("root(2,I)", "cos(ln(2))-sin(ln(2))*I", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("root(2,I+1)", "R(2)*cos((90*ln(2))/P)-R(2)*sin((90*ln(2))/P)*I", User, Degree, Cartesian); + assert_parsed_expression_simplify_to("root(2,I+1)", "R(2)*cos(ln(2)/2)-R(2)*sin(ln(2)/2)*I", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("permute(10, 4)", "5040", User, Radian, Cartesian); // TODO: prediction is not simplified yet - //assert_parsed_expression_simplify_to("prediction(-2,-3)", "prediction(-2)", Radian, Cartesian); - assert_parsed_expression_simplify_to("randint(2,4)", "randint(2,4)", Radian, Cartesian); - assert_parsed_expression_simplify_to("random()", "random()", Radian, Cartesian); - assert_parsed_expression_simplify_to("re(x)", "x", Radian, Cartesian); - assert_parsed_expression_simplify_to("round(x,y)", "round(x,y)", Radian, Cartesian); - assert_parsed_expression_simplify_to("sign(x)", "sign(x)", Radian, Cartesian); - assert_parsed_expression_simplify_to("sin(23)", "sin(23)", Radian, Cartesian); - assert_parsed_expression_simplify_to("sin(23+I)", "sin(23+I)", Radian, Cartesian); - assert_parsed_expression_simplify_to("R(1-I)", "R(2*R(2)+2)/2-R(2*R(2)-2)/2*I", Radian, Cartesian); - assert_parsed_expression_simplify_to("tan(23)", "tan(23)", Radian, Cartesian); - assert_parsed_expression_simplify_to("tan(23+I)", "tan(23+I)", Radian, Cartesian); + //assert_parsed_expression_simplify_to("prediction(-2,-3)", "prediction(-2)", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("randint(2,4)", "randint(2,4)", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("random()", "random()", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("re(x)", "x", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("round(x,y)", "round(x,y)", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("sign(x)", "sign(x)", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("sin(23)", "sin(23)", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("sin(23+I)", "sin(23+I)", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("R(1-I)", "R(2*R(2)+2)/2-R(2*R(2)-2)/2*I", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("tan(23)", "tan(23)", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("tan(23+I)", "tan(23+I)", User, Radian, Cartesian); // User defined variable - assert_parsed_expression_simplify_to("a", "a", Radian, Cartesian); + assert_parsed_expression_simplify_to("a", "a", User, Radian, Cartesian); // a = 2+i assert_simplify("2+I>a"); - assert_parsed_expression_simplify_to("a", "2+I", Radian, Cartesian); + assert_parsed_expression_simplify_to("a", "2+I", User, Radian, Cartesian); // Clean the storage for other tests Ion::Storage::sharedStorage()->recordNamed("a.exp").destroy(); // User defined function - assert_parsed_expression_simplify_to("f(3)", "f(3)", Radian, Cartesian); + assert_parsed_expression_simplify_to("f(3)", "f(3)", User, Radian, Cartesian); // f: x -> x+1 assert_simplify("x+1+I>f(x)"); - assert_parsed_expression_simplify_to("f(3)", "4+I", Radian, Cartesian); + assert_parsed_expression_simplify_to("f(3)", "4+I", User, Radian, Cartesian); // Clean the storage for other tests Ion::Storage::sharedStorage()->recordNamed("f.func").destroy(); // Polar - assert_parsed_expression_simplify_to("-2.3E3", "2300*X^(P*I)", Radian, Polar); - assert_parsed_expression_simplify_to("3", "3", Radian, Polar); - assert_parsed_expression_simplify_to("inf", "inf", Radian, Polar); - assert_parsed_expression_simplify_to("1+2+I", "R(10)*X^((-2*atan(3)+P)/2*I)", Radian, Polar); - assert_parsed_expression_simplify_to("1+2+I", "R(10)*X^((-P*atan(3)+90*P)/180*I)", Degree, Polar); - assert_parsed_expression_simplify_to("-(5+2*I)", "R(29)*X^((-2*atan(5/2)-P)/2*I)", Radian, Polar); - assert_parsed_expression_simplify_to("(5+2*I)", "R(29)*X^((-2*atan(5/2)+P)/2*I)", Radian, Polar); - assert_parsed_expression_simplify_to("I+I", "2*X^(P/2*I)", Radian, Polar); - assert_parsed_expression_simplify_to("I+I", "2*X^(P/2*I)", Radian, Polar); - assert_parsed_expression_simplify_to("-2+2*I", "2*R(2)*X^((3*P)/4*I)", Radian, Polar); - assert_parsed_expression_simplify_to("(3+I)-(2+4*I)", "R(10)*X^((2*atan(1/3)-P)/2*I)", Radian, Polar); - assert_parsed_expression_simplify_to("(2+3*I)*(4-2*I)", "2*R(65)*X^((-2*atan(7/4)+P)/2*I)", Radian, Polar); - assert_parsed_expression_simplify_to("(3+I)/2", "R(10)/2*X^((-2*atan(3)+P)/2*I)", Radian, Polar); - assert_parsed_expression_simplify_to("(3+I)/(2+I)", "R(2)*X^((2*atan(7)-P)/2*I)", Radian, Polar); + assert_parsed_expression_simplify_to("-2.3E3", "2300*X^(P*I)", User, Radian, Polar); + assert_parsed_expression_simplify_to("3", "3", User, Radian, Polar); + assert_parsed_expression_simplify_to("inf", "inf", User, Radian, Polar); + assert_parsed_expression_simplify_to("1+2+I", "R(10)*X^((-2*atan(3)+P)/2*I)", User, Radian, Polar); + assert_parsed_expression_simplify_to("1+2+I", "R(10)*X^((-P*atan(3)+90*P)/180*I)", User, Degree, Polar); + assert_parsed_expression_simplify_to("-(5+2*I)", "R(29)*X^((-2*atan(5/2)-P)/2*I)", User, Radian, Polar); + assert_parsed_expression_simplify_to("(5+2*I)", "R(29)*X^((-2*atan(5/2)+P)/2*I)", User, Radian, Polar); + assert_parsed_expression_simplify_to("I+I", "2*X^(P/2*I)", User, Radian, Polar); + assert_parsed_expression_simplify_to("I+I", "2*X^(P/2*I)", User, Radian, Polar); + assert_parsed_expression_simplify_to("-2+2*I", "2*R(2)*X^((3*P)/4*I)", User, Radian, Polar); + assert_parsed_expression_simplify_to("(3+I)-(2+4*I)", "R(10)*X^((2*atan(1/3)-P)/2*I)", User, Radian, Polar); + assert_parsed_expression_simplify_to("(2+3*I)*(4-2*I)", "2*R(65)*X^((-2*atan(7/4)+P)/2*I)", User, Radian, Polar); + assert_parsed_expression_simplify_to("(3+I)/2", "R(10)/2*X^((-2*atan(3)+P)/2*I)", User, Radian, Polar); + assert_parsed_expression_simplify_to("(3+I)/(2+I)", "R(2)*X^((2*atan(7)-P)/2*I)", User, Radian, Polar); // TODO: simplify atan(tan(x)) = x±k*pi? - //assert_parsed_expression_simplify_to("(3+I)^(2+I)", "10*X^((2*atan(3)-P)/2)*X^((-4*atan(3)+ln(2)+ln(5)+2*P)/2*I)", Radian, Polar); + //assert_parsed_expression_simplify_to("(3+I)^(2+I)", "10*X^((2*atan(3)-P)/2)*X^((-4*atan(3)+ln(2)+ln(5)+2*P)/2*I)", User, Radian, Polar); // The simplification of (3+I)^(2+I) in a Polar complex form generates to many nodes - //assert_parsed_expression_simplify_to("(3+I)^(2+I)", "10*X^((2*atan(3)-P)/2)*X^((atan(tan((-4*atan(3)+ln(2)+ln(5)+2*P)/2))+P)*I)", Radian, Polar); - assert_parsed_expression_simplify_to("(3+I)^(2+I)", "(I+3)^(I+2)", Radian, Polar); - assert_parsed_expression_simplify_to("(1+I)^2", "2*X^(P/2*I)", Radian, Polar); - assert_parsed_expression_simplify_to("2*I", "2*X^(P/2*I)", Radian, Polar); - assert_parsed_expression_simplify_to("3!", "6", Radian, Polar); - assert_parsed_expression_simplify_to("x!", "x!", Radian, Polar); - assert_parsed_expression_simplify_to("X", "X", Radian, Polar); - assert_parsed_expression_simplify_to("P", "P", Radian, Polar); - assert_parsed_expression_simplify_to("I", "X^(P/2*I)", Radian, Polar); - assert_parsed_expression_simplify_to("abs(-3)", "3", Radian, Polar); - assert_parsed_expression_simplify_to("abs(-3+I)", "R(10)", Radian, Polar); - assert_parsed_expression_simplify_to("conj(2*X^(I*P/2))", "2*X^(-P/2*I)", Radian, Polar); - assert_parsed_expression_simplify_to("-2*X^(I*P/2)", "2*X^(-P/2*I)", Radian, Polar); + //assert_parsed_expression_simplify_to("(3+I)^(2+I)", "10*X^((2*atan(3)-P)/2)*X^((atan(tan((-4*atan(3)+ln(2)+ln(5)+2*P)/2))+P)*I)", User, Radian, Polar); + assert_parsed_expression_simplify_to("(3+I)^(2+I)", "(I+3)^(I+2)", User, Radian, Polar); + assert_parsed_expression_simplify_to("(1+I)^2", "2*X^(P/2*I)", User, Radian, Polar); + assert_parsed_expression_simplify_to("2*I", "2*X^(P/2*I)", User, Radian, Polar); + assert_parsed_expression_simplify_to("3!", "6", User, Radian, Polar); + assert_parsed_expression_simplify_to("x!", "x!", User, Radian, Polar); + assert_parsed_expression_simplify_to("X", "X", User, Radian, Polar); + assert_parsed_expression_simplify_to("P", "P", User, Radian, Polar); + assert_parsed_expression_simplify_to("I", "X^(P/2*I)", User, Radian, Polar); + assert_parsed_expression_simplify_to("abs(-3)", "3", User, Radian, Polar); + assert_parsed_expression_simplify_to("abs(-3+I)", "R(10)", User, Radian, Polar); + assert_parsed_expression_simplify_to("conj(2*X^(I*P/2))", "2*X^(-P/2*I)", User, Radian, Polar); + assert_parsed_expression_simplify_to("-2*X^(I*P/2)", "2*X^(-P/2*I)", User, Radian, Polar); // User defined variable - assert_parsed_expression_simplify_to("a", "R(a^2)*X^((-P*sign(a)+P)/2*I)", Radian, Polar); + assert_parsed_expression_simplify_to("a", "R(a^2)*X^((-P*sign(a)+P)/2*I)", User, Radian, Polar); // a = 2+i assert_simplify("2+I>a"); - assert_parsed_expression_simplify_to("a", "R(5)*X^((-2*atan(2)+P)/2*I)", Radian, Polar); + assert_parsed_expression_simplify_to("a", "R(5)*X^((-2*atan(2)+P)/2*I)", User, Radian, Polar); // Clean the storage for other tests Ion::Storage::sharedStorage()->recordNamed("a.exp").destroy(); // User defined function - assert_parsed_expression_simplify_to("f(3)", "R(f(3)^2)*X^((-P*sign(f(3))+P)/2*I)", Radian, Polar); + assert_parsed_expression_simplify_to("f(3)", "R(f(3)^2)*X^((-P*sign(f(3))+P)/2*I)", User, Radian, Polar); // f: x -> x+1 assert_simplify("x+1+I>f(x)"); - assert_parsed_expression_simplify_to("f(3)", "R(17)*X^((-2*atan(4)+P)/2*I)", Radian, Polar); + assert_parsed_expression_simplify_to("f(3)", "R(17)*X^((-2*atan(4)+P)/2*I)", User, Radian, Polar); // Clean the storage for other tests Ion::Storage::sharedStorage()->recordNamed("f.func").destroy(); } diff --git a/poincare/test/complex_to_expression.cpp b/poincare/test/complex_to_expression.cpp index 4d278800c..669669586 100644 --- a/poincare/test/complex_to_expression.cpp +++ b/poincare/test/complex_to_expression.cpp @@ -7,9 +7,9 @@ using namespace Poincare; QUIZ_CASE(poincare_complex_to_expression) { assert_parsed_expression_evaluates_to("0", "0"); - assert_parsed_expression_evaluates_to("0", "0", Radian, Polar); + assert_parsed_expression_evaluates_to("0", "0", System, Radian, Polar); assert_parsed_expression_evaluates_to("0", "0"); - assert_parsed_expression_evaluates_to("0", "0", Radian, Polar); + assert_parsed_expression_evaluates_to("0", "0", System, Radian, Polar); assert_parsed_expression_evaluates_to("10", "10"); assert_parsed_expression_evaluates_to("-10", "-10"); @@ -25,19 +25,19 @@ QUIZ_CASE(poincare_complex_to_expression) { assert_parsed_expression_evaluates_to("3-I", "3-I"); assert_parsed_expression_evaluates_to("3-I-3", "-I"); - assert_parsed_expression_evaluates_to("10", "10", Radian, Polar); - assert_parsed_expression_evaluates_to("-10", "10*X^(3.141593*I)", Radian, Polar); - assert_parsed_expression_evaluates_to("100", "100", Radian, Polar); - assert_parsed_expression_evaluates_to("0.1", "0.1", Radian, Polar); - assert_parsed_expression_evaluates_to("0.1234567", "0.1234567", Radian, Polar); - assert_parsed_expression_evaluates_to("0.12345678", "0.1234568", Radian, Polar); - assert_parsed_expression_evaluates_to("1+2*I", "2.236068*X^(1.107149*I)", Radian, Polar); - assert_parsed_expression_evaluates_to("1+I-I", "1", Radian, Polar); - assert_parsed_expression_evaluates_to("1+I-1", "X^(1.570796*I)", Radian, Polar); - assert_parsed_expression_evaluates_to("1+I", "1.414214*X^(0.7853982*I)", Radian, Polar); - assert_parsed_expression_evaluates_to("3+I", "3.162278*X^(0.3217506*I)", Radian, Polar); - assert_parsed_expression_evaluates_to("3-I", "3.162278*X^(-0.3217506*I)", Radian, Polar); - assert_parsed_expression_evaluates_to("3-I-3", "X^(-1.570796*I)", Radian, Polar); + assert_parsed_expression_evaluates_to("10", "10", System, Radian, Polar); + assert_parsed_expression_evaluates_to("-10", "10*X^(3.141593*I)", System, Radian, Polar); + assert_parsed_expression_evaluates_to("100", "100", System, Radian, Polar); + assert_parsed_expression_evaluates_to("0.1", "0.1", System, Radian, Polar); + assert_parsed_expression_evaluates_to("0.1234567", "0.1234567", System, Radian, Polar); + assert_parsed_expression_evaluates_to("0.12345678", "0.1234568", System, Radian, Polar); + assert_parsed_expression_evaluates_to("1+2*I", "2.236068*X^(1.107149*I)", System, Radian, Polar); + assert_parsed_expression_evaluates_to("1+I-I", "1", System, Radian, Polar); + assert_parsed_expression_evaluates_to("1+I-1", "X^(1.570796*I)", System, Radian, Polar); + assert_parsed_expression_evaluates_to("1+I", "1.414214*X^(0.7853982*I)", System, Radian, Polar); + assert_parsed_expression_evaluates_to("3+I", "3.162278*X^(0.3217506*I)", System, Radian, Polar); + assert_parsed_expression_evaluates_to("3-I", "3.162278*X^(-0.3217506*I)", System, Radian, Polar); + assert_parsed_expression_evaluates_to("3-I-3", "X^(-1.570796*I)", System, Radian, Polar); assert_parsed_expression_evaluates_to("10", "10"); assert_parsed_expression_evaluates_to("-10", "-10"); @@ -53,27 +53,27 @@ QUIZ_CASE(poincare_complex_to_expression) { assert_parsed_expression_evaluates_to("3-I", "3-I"); assert_parsed_expression_evaluates_to("3-I-3", "-I"); - assert_parsed_expression_evaluates_to("10", "10", Radian, Polar); - assert_parsed_expression_evaluates_to("-10", "10*X^(3.1415926535898*I)", Radian, Polar); - assert_parsed_expression_evaluates_to("100", "100", Radian, Polar); - assert_parsed_expression_evaluates_to("0.1", "0.1", Radian, Polar); - assert_parsed_expression_evaluates_to("0.1234567", "0.1234567", Radian, Polar); - assert_parsed_expression_evaluates_to("0.12345678", "0.12345678", Radian, Polar); - assert_parsed_expression_evaluates_to("1+2*I", "2.2360679775*X^(1.10714871779*I)", Radian, Polar, 12); - assert_parsed_expression_evaluates_to("1+I-I", "1", Radian, Polar); - assert_parsed_expression_evaluates_to("1+I-1", "X^(1.57079632679*I)", Radian, Polar, 12); - assert_parsed_expression_evaluates_to("1+I", "1.41421356237*X^(0.785398163397*I)", Radian, Polar, 12); - assert_parsed_expression_evaluates_to("3+I", "3.16227766017*X^(0.321750554397*I)", Radian, Polar,12); - assert_parsed_expression_evaluates_to("3-I", "3.16227766017*X^(-0.321750554397*I)", Radian, Polar,12); - assert_parsed_expression_evaluates_to("3-I-3", "X^(-1.57079632679*I)", Radian, Polar,12); + assert_parsed_expression_evaluates_to("10", "10", System, Radian, Polar); + assert_parsed_expression_evaluates_to("-10", "10*X^(3.1415926535898*I)", System, Radian, Polar); + assert_parsed_expression_evaluates_to("100", "100", System, Radian, Polar); + assert_parsed_expression_evaluates_to("0.1", "0.1", System, Radian, Polar); + assert_parsed_expression_evaluates_to("0.1234567", "0.1234567", System, Radian, Polar); + assert_parsed_expression_evaluates_to("0.12345678", "0.12345678", System, Radian, Polar); + assert_parsed_expression_evaluates_to("1+2*I", "2.2360679775*X^(1.10714871779*I)", System, Radian, Polar, 12); + assert_parsed_expression_evaluates_to("1+I-I", "1", System, Radian, Polar); + assert_parsed_expression_evaluates_to("1+I-1", "X^(1.57079632679*I)", System, Radian, Polar, 12); + assert_parsed_expression_evaluates_to("1+I", "1.41421356237*X^(0.785398163397*I)", System, Radian, Polar, 12); + assert_parsed_expression_evaluates_to("3+I", "3.16227766017*X^(0.321750554397*I)", System, Radian, Polar,12); + assert_parsed_expression_evaluates_to("3-I", "3.16227766017*X^(-0.321750554397*I)", System, Radian, Polar,12); + assert_parsed_expression_evaluates_to("3-I-3", "X^(-1.57079632679*I)", System, Radian, Polar,12); - assert_parsed_expression_evaluates_to("2+3*I", "3.60555127546*X^(0.982793723247*I)", Radian, Polar, 12); - assert_parsed_expression_evaluates_to("3.60555127546*X^(0.982793723247*I)", "2+3*I", Radian, Cartesian, 12); - assert_parsed_expression_evaluates_to("12.04159457879229548012824103*X^(1.4876550949*I)", "1+12*I", Radian, Cartesian, 5); + assert_parsed_expression_evaluates_to("2+3*I", "3.60555127546*X^(0.982793723247*I)", System, Radian, Polar, 12); + assert_parsed_expression_evaluates_to("3.60555127546*X^(0.982793723247*I)", "2+3*I", System, Radian, Cartesian, 12); + assert_parsed_expression_evaluates_to("12.04159457879229548012824103*X^(1.4876550949*I)", "1+12*I", System, Radian, Cartesian, 5); assert_parsed_expression_evaluates_to("-2E20+2E20*I", "-2E20+2E20*I"); - assert_parsed_expression_evaluates_to("-2E20+2E20*I", "2.828427E20*X^(2.356194*I)", Radian, Polar); + assert_parsed_expression_evaluates_to("-2E20+2E20*I", "2.828427E20*X^(2.356194*I)", System, Radian, Polar); assert_parsed_expression_evaluates_to("1E155-1E155*I", "1E155-1E155*I"); - assert_parsed_expression_evaluates_to("1E155-1E155*I", "1.41421356237E155*X^(-0.785398163397*I)", Radian, Polar,12); + assert_parsed_expression_evaluates_to("1E155-1E155*I", "1.41421356237E155*X^(-0.785398163397*I)", System, Radian, Polar,12); assert_parsed_expression_evaluates_to("-2E100+2E100*I", Undefined::Name()); assert_parsed_expression_evaluates_to("-2E360+2E360*I", Undefined::Name()); @@ -82,6 +82,6 @@ QUIZ_CASE(poincare_complex_to_expression) { assert_parsed_expression_evaluates_to("undef+2E100*I", Undefined::Name()); assert_parsed_expression_evaluates_to("-2E360+undef*I", Undefined::Name()); - assert_parsed_expression_evaluates_to("2*X^(I)", "2*X^I", Radian, Polar, 5); - assert_parsed_expression_evaluates_to("2*X^(-I)", "2*X^(-I)", Radian, Polar, 5); + assert_parsed_expression_evaluates_to("2*X^(I)", "2*X^I", System, Radian, Polar, 5); + assert_parsed_expression_evaluates_to("2*X^(-I)", "2*X^(-I)", System, Radian, Polar, 5); } diff --git a/poincare/test/function.cpp b/poincare/test/function.cpp index f85359c1c..9b7d343c7 100644 --- a/poincare/test/function.cpp +++ b/poincare/test/function.cpp @@ -84,9 +84,9 @@ QUIZ_CASE(poincare_function_evaluate) { assert_parsed_expression_evaluates_to("ceil(0.2)", "1"); #if MATRICES_ARE_DEFINED - assert_parsed_expression_evaluates_to("det([[1,23,3][4,5,6][7,8,9]])", "126", Degree, Cartesian, 6); // FIXME: the determinant computation is not precised enough to be displayed with 7 significant digits + assert_parsed_expression_evaluates_to("det([[1,23,3][4,5,6][7,8,9]])", "126", System, Degree, Cartesian, 6); // FIXME: the determinant computation is not precised enough to be displayed with 7 significant digits assert_parsed_expression_evaluates_to("det([[1,23,3][4,5,6][7,8,9]])", "126"); - assert_parsed_expression_evaluates_to("det([[I,23-2I,3*I][4+I,5*I,6][7,8*I+2,9]])", "126-231*I", Degree, Cartesian, 6); // FIXME: the determinant computation is not precised enough to be displayed with 7 significant digits + assert_parsed_expression_evaluates_to("det([[I,23-2I,3*I][4+I,5*I,6][7,8*I+2,9]])", "126-231*I", System, Degree, Cartesian, 6); // FIXME: the determinant computation is not precised enough to be displayed with 7 significant digits assert_parsed_expression_evaluates_to("det([[I,23-2I,3*I][4+I,5*I,6][7,8*I+2,9]])", "126-231*I"); #endif assert_parsed_expression_evaluates_to("diff(2*x, x, 2)", "2"); @@ -165,10 +165,10 @@ QUIZ_CASE(poincare_function_evaluate) { assert_parsed_expression_evaluates_to("factor(-123/24)", "-5.125"); #if MATRICES_ARE_DEFINED - assert_parsed_expression_evaluates_to("inverse([[1,2,3][4,5,-6][7,8,9]])", "[[-1.2917,-0.083333,0.375][1.0833,0.16667,-0.25][0.041667,-0.083333,0.041667]]", Degree, Cartesian, 5); // inverse is not precise enough to display 7 significative digits + assert_parsed_expression_evaluates_to("inverse([[1,2,3][4,5,-6][7,8,9]])", "[[-1.2917,-0.083333,0.375][1.0833,0.16667,-0.25][0.041667,-0.083333,0.041667]]", System, Degree, Cartesian, 5); // inverse is not precise enough to display 7 significative digits assert_parsed_expression_evaluates_to("inverse([[1,2,3][4,5,-6][7,8,9]])", "[[-1.2916666666667,-8.3333333333333E-2,0.375][1.0833333333333,1.6666666666667E-1,-0.25][4.1666666666667E-2,-8.3333333333333E-2,4.1666666666667E-2]]"); - assert_parsed_expression_evaluates_to("inverse([[I,23-2I,3*I][4+I,5*I,6][7,8*I+2,9]])", "[[-0.0118-0.0455*I,-0.5-0.727*I,0.318+0.489*I][0.0409+0.00364*I,0.04-0.0218*I,-0.0255+0.00091*I][0.00334-0.00182*I,0.361+0.535*I,-0.13-0.358*I]]", Degree, Cartesian, 3); // inverse is not precise enough to display 7 significative digits - assert_parsed_expression_evaluates_to("inverse([[I,23-2I,3*I][4+I,5*I,6][7,8*I+2,9]])", "[[-0.0118289353958-0.0454959053685*I,-0.500454959054-0.727024567789*I,0.31847133758+0.488626023658*I][0.0409463148317+3.63967242948E-3*I,0.0400363967243-0.0218380345769*I,-0.0254777070064+9.0991810737E-4*I][3.33636639369E-3-1.81983621474E-3*I,0.36093418259+0.534728541098*I,-0.130118289354-0.357597816197*I]]", Degree, Cartesian, 12); // FIXME: inverse is not precise enough to display 14 significative digits + assert_parsed_expression_evaluates_to("inverse([[I,23-2I,3*I][4+I,5*I,6][7,8*I+2,9]])", "[[-0.0118-0.0455*I,-0.5-0.727*I,0.318+0.489*I][0.0409+0.00364*I,0.04-0.0218*I,-0.0255+0.00091*I][0.00334-0.00182*I,0.361+0.535*I,-0.13-0.358*I]]", System, Degree, Cartesian, 3); // inverse is not precise enough to display 7 significative digits + assert_parsed_expression_evaluates_to("inverse([[I,23-2I,3*I][4+I,5*I,6][7,8*I+2,9]])", "[[-0.0118289353958-0.0454959053685*I,-0.500454959054-0.727024567789*I,0.31847133758+0.488626023658*I][0.0409463148317+3.63967242948E-3*I,0.0400363967243-0.0218380345769*I,-0.0254777070064+9.0991810737E-4*I][3.33636639369E-3-1.81983621474E-3*I,0.36093418259+0.534728541098*I,-0.130118289354-0.357597816197*I]]", System, Degree, Cartesian, 12); // FIXME: inverse is not precise enough to display 14 significative digits #endif assert_parsed_expression_evaluates_to("prediction(0.1, 100)", "[[0,0.2]]"); @@ -186,8 +186,8 @@ QUIZ_CASE(poincare_function_evaluate) { assert_parsed_expression_evaluates_to("root(3, 3+I)", "1.382007-0.1524428*I"); assert_parsed_expression_evaluates_to("root(3, 3+I)", "1.3820069623326-0.1524427794159*I"); - assert_parsed_expression_evaluates_to("root(5^((-I)3^9),I)", "3.504", Degree, Cartesian, 4); - assert_parsed_expression_evaluates_to("root(5^((-I)3^9),I)", "3.5039410843", Degree, Cartesian, 11); + assert_parsed_expression_evaluates_to("root(5^((-I)3^9),I)", "3.504", System, Degree, Cartesian, 4); + assert_parsed_expression_evaluates_to("root(5^((-I)3^9),I)", "3.5039410843", System, Degree, Cartesian, 11); assert_parsed_expression_evaluates_to("R(3+I)", "1.755317+0.2848488*I"); assert_parsed_expression_evaluates_to("R(3+I)", "1.7553173018244+2.8484878459314E-1*I"); diff --git a/poincare/test/helper.cpp b/poincare/test/helper.cpp index 16051552c..e0e6d41be 100644 --- a/poincare/test/helper.cpp +++ b/poincare/test/helper.cpp @@ -125,9 +125,9 @@ void assert_simplify(const char * expression) { quiz_assert(!(parse_and_simplify(expression).isUninitialized())); } -typedef Expression (*ProcessExpression)(Expression, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); +typedef Expression (*ProcessExpression)(Expression, Context & context, ExpressionNode::ReductionTarget target, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); -void assert_parsed_expression_process_to(const char * expression, const char * result, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ProcessExpression process, int numberOfSignifiantDigits = PrintFloat::k_numberOfStoredSignificantDigits) { +void assert_parsed_expression_process_to(const char * expression, const char * result, ExpressionNode::ReductionTarget target, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ProcessExpression process, int numberOfSignifiantDigits = PrintFloat::k_numberOfStoredSignificantDigits) { Shared::GlobalContext globalContext; Expression e = parse_expression(expression); @@ -135,7 +135,7 @@ void assert_parsed_expression_process_to(const char * expression, const char * r cout << " Entry expression: " << expression << "----" << endl; print_expression(e, 0); #endif - Expression m = process(e, globalContext, complexFormat, angleUnit); + Expression m = process(e, globalContext, target, complexFormat, angleUnit); char buffer[500]; m.serialize(buffer, sizeof(buffer), DecimalMode, numberOfSignifiantDigits); translate_in_ASCII_chars(buffer); @@ -147,18 +147,29 @@ void assert_parsed_expression_process_to(const char * expression, const char * r } template -void assert_parsed_expression_evaluates_to(const char * expression, const char * approximation, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat, int numberOfSignificantDigits) { +void assert_parsed_expression_evaluates_to(const char * expression, const char * approximation, ExpressionNode::ReductionTarget target, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat, int numberOfSignificantDigits) { #if POINCARE_TESTS_PRINT_EXPRESSIONS cout << "--------- Approximation ---------" << endl; #endif int numberOfDigits = sizeof(T) == sizeof(double) ? PrintFloat::k_numberOfStoredSignificantDigits : PrintFloat::k_numberOfPrintedSignificantDigits; numberOfDigits = numberOfSignificantDigits > 0 ? numberOfSignificantDigits : numberOfDigits; - assert_parsed_expression_process_to(expression, approximation, complexFormat, angleUnit, [](Expression e, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { - Expression result = e.clone().simplify(context, complexFormat, angleUnit); - if (result.isUninitialized()) { - result = e; + + assert_parsed_expression_process_to(expression, approximation, target, complexFormat, angleUnit, [](Expression e, Context & context, ExpressionNode::ReductionTarget target, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { + Expression simplified = e.clone(); + Expression result; + if (target == ExpressionNode::ReductionTarget::User) { + // When the reduction target is the User, we always approximate in double + assert(sizeof(T) == sizeof(double)); + simplified.simplifyAndApproximate(&simplified, &result, context, complexFormat, angleUnit); + } else { + simplified = simplified.simplify(context, complexFormat, angleUnit); + result = simplified.approximate(context, complexFormat, angleUnit); } - return result.approximate(context, complexFormat, angleUnit); + // Simplification was interrupted + if (simplified.isUninitialized()) { + return e.approximate(context, complexFormat, angleUnit); + } + return result; }, numberOfDigits); } @@ -166,7 +177,7 @@ template void assert_parsed_expression_evaluates_without_simplifying_to(const char * expression, const char * approximation, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat, int numberOfSignificantDigits) { int numberOfDigits = sizeof(T) == sizeof(double) ? PrintFloat::k_numberOfStoredSignificantDigits : PrintFloat::k_numberOfPrintedSignificantDigits; numberOfDigits = numberOfSignificantDigits > 0 ? numberOfSignificantDigits : numberOfDigits; - assert_parsed_expression_process_to(expression, approximation, complexFormat, angleUnit, [](Expression e, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { + assert_parsed_expression_process_to(expression, approximation, ExpressionNode::ReductionTarget::System, complexFormat, angleUnit, [](Expression e, Context & context, ExpressionNode::ReductionTarget target, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { return e.approximate(context, complexFormat, angleUnit); }, numberOfDigits); } @@ -179,13 +190,17 @@ void assert_parsed_expression_approximates_with_value_for_symbol(Expression expr quiz_assert((std::isnan(result) && std::isnan(approximation)) || std::fabs(result - approximation) < 10.0*Expression::Epsilon()); } -void assert_parsed_expression_simplify_to(const char * expression, const char * simplifiedExpression, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) { +void assert_parsed_expression_simplify_to(const char * expression, const char * simplifiedExpression, ExpressionNode::ReductionTarget target, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) { #if POINCARE_TESTS_PRINT_EXPRESSIONS cout << "--------- Simplification ---------" << endl; #endif - assert_parsed_expression_process_to(expression, simplifiedExpression, complexFormat, angleUnit, [](Expression e, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { + assert_parsed_expression_process_to(expression, simplifiedExpression, target, complexFormat, angleUnit, [](Expression e, Context & context, ExpressionNode::ReductionTarget target, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { Expression copy = e.clone(); - copy.simplifyAndApproximate(©, nullptr, context, complexFormat, angleUnit); + if (target == ExpressionNode::ReductionTarget::User) { + copy.simplifyAndApproximate(©, nullptr, context, complexFormat, angleUnit); + } else { + copy = copy.simplify(context, complexFormat, angleUnit); + } if (copy.isUninitialized()) { return e; } @@ -231,8 +246,8 @@ void assert_expression_layout_serialize_to(Poincare::Layout layout, const char * quiz_assert(strcmp(serialization, buffer) == 0); } -template void assert_parsed_expression_evaluates_to(char const*, char const *, Poincare::Preferences::AngleUnit, Poincare::Preferences::ComplexFormat, int); -template void assert_parsed_expression_evaluates_to(char const*, char const *, Poincare::Preferences::AngleUnit, Poincare::Preferences::ComplexFormat, int); +template void assert_parsed_expression_evaluates_to(char const*, char const *, Poincare::ExpressionNode::ReductionTarget, Poincare::Preferences::AngleUnit, Poincare::Preferences::ComplexFormat, int); +template void assert_parsed_expression_evaluates_to(char const*, char const *, Poincare::ExpressionNode::ReductionTarget, Poincare::Preferences::AngleUnit, Poincare::Preferences::ComplexFormat, int); template void assert_parsed_expression_evaluates_without_simplifying_to(char const*, char const *, Poincare::Preferences::AngleUnit, Poincare::Preferences::ComplexFormat, int); template void assert_parsed_expression_evaluates_without_simplifying_to(char const*, char const *, Poincare::Preferences::AngleUnit, Poincare::Preferences::ComplexFormat, int); template void assert_parsed_expression_approximates_with_value_for_symbol(Poincare::Expression, const char *, float, float, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit); diff --git a/poincare/test/helper.h b/poincare/test/helper.h index 42fd24c92..de0205017 100644 --- a/poincare/test/helper.h +++ b/poincare/test/helper.h @@ -8,6 +8,8 @@ const char * MaxIntegerString(); // (2^32)^k_maxNumberOfDigits-1 const char * OverflowedIntegerString(); // (2^32)^k_maxNumberOfDigits const char * BigOverflowedIntegerString(); // OverflowedIntegerString with a 2 on first digit +constexpr Poincare::ExpressionNode::ReductionTarget System = Poincare::ExpressionNode::ReductionTarget::System; +constexpr Poincare::ExpressionNode::ReductionTarget User = Poincare::ExpressionNode::ReductionTarget::User; constexpr Poincare::Preferences::AngleUnit Degree = Poincare::Preferences::AngleUnit::Degree; constexpr Poincare::Preferences::AngleUnit Radian = Poincare::Preferences::AngleUnit::Radian; constexpr Poincare::Preferences::ComplexFormat Cartesian = Poincare::Preferences::ComplexFormat::Cartesian; @@ -29,7 +31,7 @@ void assert_parsed_expression_polynomial_degree(const char * expression, int deg void assert_simplify(const char * expression); template -void assert_parsed_expression_evaluates_to(const char * expression, const char * approximation, Poincare::Preferences::AngleUnit angleUnit = Degree, Poincare::Preferences::ComplexFormat complexFormat = Cartesian, int numberOfSignificantDigits = -1); +void assert_parsed_expression_evaluates_to(const char * expression, const char * approximation, Poincare::ExpressionNode::ReductionTarget target = System, Poincare::Preferences::AngleUnit angleUnit = Degree, Poincare::Preferences::ComplexFormat complexFormat = Cartesian, int numberOfSignificantDigits = -1); template void assert_parsed_expression_evaluates_without_simplifying_to(const char * expression, const char * approximation, Poincare::Preferences::AngleUnit angleUnit = Degree, Poincare::Preferences::ComplexFormat complexFormat = Cartesian, int numberOfSignificantDigits = -1); @@ -37,7 +39,7 @@ void assert_parsed_expression_evaluates_without_simplifying_to(const char * expr template void assert_parsed_expression_approximates_with_value_for_symbol(Poincare::Expression expression, const char * symbol, T value, T approximation, Poincare::Preferences::ComplexFormat complexFormat = Cartesian, Poincare::Preferences::AngleUnit angleUnit = Degree); -void assert_parsed_expression_simplify_to(const char * expression, const char * simplifiedExpression, Poincare::Preferences::AngleUnit angleUnit = Poincare::Preferences::AngleUnit::Radian, Poincare::Preferences::ComplexFormat complexFormat = Poincare::Preferences::ComplexFormat::Cartesian); +void assert_parsed_expression_simplify_to(const char * expression, const char * simplifiedExpression, Poincare::ExpressionNode::ReductionTarget target = Poincare::ExpressionNode::ReductionTarget::User, Poincare::Preferences::AngleUnit angleUnit = Poincare::Preferences::AngleUnit::Radian, Poincare::Preferences::ComplexFormat complexFormat = Poincare::Preferences::ComplexFormat::Cartesian); void assert_parsed_expression_serialize_to(Poincare::Expression expression, const char * serializedExpression, Poincare::Preferences::PrintFloatMode mode = DecimalMode, int numberOfSignifiantDigits = 7); diff --git a/poincare/test/parser.cpp b/poincare/test/parser.cpp index 53c1690db..c2f313e25 100644 --- a/poincare/test/parser.cpp +++ b/poincare/test/parser.cpp @@ -407,18 +407,18 @@ QUIZ_CASE(poincare_parser_expression_evaluation) { assert_parsed_expression_evaluates_to("-2-3", "-5"); assert_parsed_expression_evaluates_to("1.2*X^(1)", "3.261938"); - assert_parsed_expression_evaluates_to("2X^(3)", "40.1711", Radian, Cartesian, 6); // WARNING: the 7th significant digit is wrong on blackbos simulator - assert_parsed_expression_evaluates_to("X^2*X^(1)", "20.0855", Radian, Cartesian, 6); // WARNING: the 7th significant digit is wrong on simulator + assert_parsed_expression_evaluates_to("2X^(3)", "40.1711", System, Radian, Cartesian, 6); // WARNING: the 7th significant digit is wrong on blackbos simulator + assert_parsed_expression_evaluates_to("X^2*X^(1)", "20.0855", System, Radian, Cartesian, 6); // WARNING: the 7th significant digit is wrong on simulator assert_parsed_expression_evaluates_to("X^2*X^(1)", "20.085536923188"); assert_parsed_expression_evaluates_to("2*3^4+2", "164"); assert_parsed_expression_evaluates_to("-2*3^4+2", "-160"); - assert_parsed_expression_evaluates_to("-sin(3)*2-3", "-3.2822400161197", Radian); + assert_parsed_expression_evaluates_to("-sin(3)*2-3", "-3.2822400161197", System, Radian); assert_parsed_expression_evaluates_to("-.003", "-0.003"); assert_parsed_expression_evaluates_to(".02E2", "2"); assert_parsed_expression_evaluates_to("5-2/3", "4.333333"); assert_parsed_expression_evaluates_to("2/3-5", "-4.3333333333333"); assert_parsed_expression_evaluates_to("-2/3-5", "-5.666667"); - assert_parsed_expression_evaluates_to("sin(3)2(4+2)", "1.6934400967184", Radian); + assert_parsed_expression_evaluates_to("sin(3)2(4+2)", "1.6934400967184", System, Radian); assert_parsed_expression_evaluates_to("4/2*(2+3)", "10"); assert_parsed_expression_evaluates_to("4/2*(2+3)", "10"); } diff --git a/poincare/test/power.cpp b/poincare/test/power.cpp index 956dcc997..6a8e9c479 100644 --- a/poincare/test/power.cpp +++ b/poincare/test/power.cpp @@ -15,19 +15,19 @@ QUIZ_CASE(poincare_power_evaluate) { assert_parsed_expression_evaluates_to("0^0", Undefined::Name()); assert_parsed_expression_evaluates_to("0^2", "0"); assert_parsed_expression_evaluates_to("0^(-2)", Undefined::Name()); - assert_parsed_expression_evaluates_to("(-2)^4.2", "14.8690638497+10.8030072384*I", Radian, Cartesian, 12); - assert_parsed_expression_evaluates_to("(-0.1)^4", "0.0001", Radian, Cartesian, 12); + assert_parsed_expression_evaluates_to("(-2)^4.2", "14.8690638497+10.8030072384*I", System, Radian, Cartesian, 12); + assert_parsed_expression_evaluates_to("(-0.1)^4", "0.0001", System, Radian, Cartesian, 12); #if MATRICES_ARE_DEFINED - assert_parsed_expression_evaluates_to("[[1,2][3,4]]^(-3)", "[[-14.75,6.75][10.125,-4.625]]", Degree, Cartesian, 6); + assert_parsed_expression_evaluates_to("[[1,2][3,4]]^(-3)", "[[-14.75,6.75][10.125,-4.625]]", System, Degree, Cartesian, 6); assert_parsed_expression_evaluates_to("[[1,2][3,4]]^3", "[[37,54][81,118]]"); #endif assert_parsed_expression_evaluates_to("0^2", "0"); assert_parsed_expression_evaluates_to("I^I", "2.0787957635076E-1"); - assert_parsed_expression_evaluates_to("1.0066666666667^60", "1.48985", Radian, Cartesian, 6); + assert_parsed_expression_evaluates_to("1.0066666666667^60", "1.48985", System, Radian, Cartesian, 6); assert_parsed_expression_evaluates_to("1.0066666666667^60", "1.4898457083046"); assert_parsed_expression_evaluates_to("X^(I*P)", "-1"); assert_parsed_expression_evaluates_to("X^(I*P)", "-1"); - assert_parsed_expression_evaluates_to("X^(I*P+2)", "-7.38906", Radian, Cartesian, 6); + assert_parsed_expression_evaluates_to("X^(I*P+2)", "-7.38906", System, Radian, Cartesian, 6); assert_parsed_expression_evaluates_to("X^(I*P+2)", "-7.3890560989307"); assert_parsed_expression_evaluates_to("(-1)^(1/3)", "0.5+0.8660254*I"); assert_parsed_expression_evaluates_to("(-1)^(1/3)", "0.5+8.6602540378444E-1*I"); diff --git a/poincare/test/trigo.cpp b/poincare/test/trigo.cpp index a1467a794..bef58efdc 100644 --- a/poincare/test/trigo.cpp +++ b/poincare/test/trigo.cpp @@ -26,65 +26,65 @@ QUIZ_CASE(poincare_trigo_evaluate) { * Ri -> R (even) */ // On R - assert_parsed_expression_evaluates_to("cos(2)", "-4.1614683654714E-1", Radian); - assert_parsed_expression_evaluates_to("cos(2)", "0.9993908270191", Degree); + assert_parsed_expression_evaluates_to("cos(2)", "-4.1614683654714E-1", System, Radian); + assert_parsed_expression_evaluates_to("cos(2)", "0.9993908270191", System, Degree); // Oscillator - assert_parsed_expression_evaluates_to("cos(P/2)", "0", Radian); - assert_parsed_expression_evaluates_to("cos(3*P/2)", "0", Radian); - assert_parsed_expression_evaluates_to("cos(3*P)", "-1", Radian); - assert_parsed_expression_evaluates_to("cos(-540)", "-1", Degree); + assert_parsed_expression_evaluates_to("cos(P/2)", "0", System, Radian); + assert_parsed_expression_evaluates_to("cos(3*P/2)", "0", System, Radian); + assert_parsed_expression_evaluates_to("cos(3*P)", "-1", System, Radian); + assert_parsed_expression_evaluates_to("cos(-540)", "-1", System, Degree); // On R*i - assert_parsed_expression_evaluates_to("cos(-2*I)", "3.7621956910836", Radian); - assert_parsed_expression_evaluates_to("cos(-2*I)", "1.0006092967033", Degree); + assert_parsed_expression_evaluates_to("cos(-2*I)", "3.7621956910836", System, Radian); + assert_parsed_expression_evaluates_to("cos(-2*I)", "1.0006092967033", System, Degree); // Symmetry: even - assert_parsed_expression_evaluates_to("cos(2*I)", "3.7621956910836", Radian); - assert_parsed_expression_evaluates_to("cos(2*I)", "1.0006092967033", Degree); + assert_parsed_expression_evaluates_to("cos(2*I)", "3.7621956910836", System, Radian); + assert_parsed_expression_evaluates_to("cos(2*I)", "1.0006092967033", System, Degree); // On C - assert_parsed_expression_evaluates_to("cos(I-4)", "-1.008625-0.8893952*I", Radian); - assert_parsed_expression_evaluates_to("cos(I-4)", "0.997716+0.00121754*I", Degree, Cartesian, 6); + assert_parsed_expression_evaluates_to("cos(I-4)", "-1.008625-0.8893952*I", System, Radian); + assert_parsed_expression_evaluates_to("cos(I-4)", "0.997716+0.00121754*I", System, Degree, Cartesian, 6); /* sin: R -> R (oscillator) * Ri -> Ri (odd) */ // On R - assert_parsed_expression_evaluates_to("sin(2)", "9.0929742682568E-1", Radian); - assert_parsed_expression_evaluates_to("sin(2)", "3.4899496702501E-2", Degree); + assert_parsed_expression_evaluates_to("sin(2)", "9.0929742682568E-1", System, Radian); + assert_parsed_expression_evaluates_to("sin(2)", "3.4899496702501E-2", System, Degree); // Oscillator - assert_parsed_expression_evaluates_to("sin(P/2)", "1", Radian); - assert_parsed_expression_evaluates_to("sin(3*P/2)", "-1", Radian); - assert_parsed_expression_evaluates_to("sin(3*P)", "0", Radian); - assert_parsed_expression_evaluates_to("sin(-540)", "0", Degree); + assert_parsed_expression_evaluates_to("sin(P/2)", "1", System, Radian); + assert_parsed_expression_evaluates_to("sin(3*P/2)", "-1", System, Radian); + assert_parsed_expression_evaluates_to("sin(3*P)", "0", System, Radian); + assert_parsed_expression_evaluates_to("sin(-540)", "0", System, Degree); // On R*i - assert_parsed_expression_evaluates_to("sin(3*I)", "10.01787492741*I", Radian); - assert_parsed_expression_evaluates_to("sin(3*I)", "0.05238381*I", Degree); + assert_parsed_expression_evaluates_to("sin(3*I)", "10.01787492741*I", System, Radian); + assert_parsed_expression_evaluates_to("sin(3*I)", "0.05238381*I", System, Degree); // Symmetry: odd - assert_parsed_expression_evaluates_to("sin(-3*I)", "-10.01787492741*I", Radian); - assert_parsed_expression_evaluates_to("sin(-3*I)", "-0.05238381*I", Degree); + assert_parsed_expression_evaluates_to("sin(-3*I)", "-10.01787492741*I", System, Radian); + assert_parsed_expression_evaluates_to("sin(-3*I)", "-0.05238381*I", System, Degree); // On: C - assert_parsed_expression_evaluates_to("sin(I-4)", "1.16781-0.768163*I", Radian, Cartesian, 6); - assert_parsed_expression_evaluates_to("sin(I-4)", "-0.0697671+0.0174117*I", Degree, Cartesian, 6); - assert_parsed_expression_evaluates_to("sin(1.234567890123456E-15)", "1.23457E-15", Radian, Cartesian, 6); + assert_parsed_expression_evaluates_to("sin(I-4)", "1.16781-0.768163*I", System, Radian, Cartesian, 6); + assert_parsed_expression_evaluates_to("sin(I-4)", "-0.0697671+0.0174117*I", System, Degree, Cartesian, 6); + assert_parsed_expression_evaluates_to("sin(1.234567890123456E-15)", "1.23457E-15", System, Radian, Cartesian, 6); /* tan: R -> R (tangent-style) * Ri -> Ri (odd) */ // On R - assert_parsed_expression_evaluates_to("tan(2)", "-2.1850398632615", Radian); - assert_parsed_expression_evaluates_to("tan(2)", "3.4920769491748E-2", Degree); + assert_parsed_expression_evaluates_to("tan(2)", "-2.1850398632615", System, Radian); + assert_parsed_expression_evaluates_to("tan(2)", "3.4920769491748E-2", System, Degree); // Tangent-style - assert_parsed_expression_evaluates_to("tan(P/2)", Undefined::Name(), Radian); - assert_parsed_expression_evaluates_to("tan(3*P/2)", Undefined::Name(), Radian); - assert_parsed_expression_evaluates_to("tan(3*P)", "0", Radian); - assert_parsed_expression_evaluates_to("tan(-540)", "0", Degree); + assert_parsed_expression_evaluates_to("tan(P/2)", Undefined::Name(), System, Radian); + assert_parsed_expression_evaluates_to("tan(3*P/2)", Undefined::Name(), System, Radian); + assert_parsed_expression_evaluates_to("tan(3*P)", "0", System, Radian); + assert_parsed_expression_evaluates_to("tan(-540)", "0", System, Degree); // On R*i - assert_parsed_expression_evaluates_to("tan(-2*I)", "-9.6402758007582E-1*I", Radian); - assert_parsed_expression_evaluates_to("tan(-2*I)", "-0.03489241*I", Degree); + assert_parsed_expression_evaluates_to("tan(-2*I)", "-9.6402758007582E-1*I", System, Radian); + assert_parsed_expression_evaluates_to("tan(-2*I)", "-0.03489241*I", System, Degree); // Symmetry: odd - assert_parsed_expression_evaluates_to("tan(2*I)", "9.6402758007582E-1*I", Radian); - assert_parsed_expression_evaluates_to("tan(2*I)", "0.03489241*I", Degree); + assert_parsed_expression_evaluates_to("tan(2*I)", "9.6402758007582E-1*I", System, Radian); + assert_parsed_expression_evaluates_to("tan(2*I)", "0.03489241*I", System, Degree); // On C - assert_parsed_expression_evaluates_to("tan(I-4)", "-0.273553+1.00281*I", Radian, Cartesian, 6); - assert_parsed_expression_evaluates_to("tan(I-4)", "-0.0699054+0.0175368*I", Degree, Cartesian, 6); + assert_parsed_expression_evaluates_to("tan(I-4)", "-0.273553+1.00281*I", System, Radian, Cartesian, 6); + assert_parsed_expression_evaluates_to("tan(I-4)", "-0.0699054+0.0175368*I", System, Degree, Cartesian, 6); /* acos: [-1,1] -> R * ]-inf,-1[ -> Pi+R*i (odd imaginary) @@ -92,31 +92,31 @@ QUIZ_CASE(poincare_trigo_evaluate) { * R*i -> Pi/2+R*i (odd imaginary) */ // On [-1, 1] - assert_parsed_expression_evaluates_to("acos(0.5)", "1.0471975511966", Radian); - assert_parsed_expression_evaluates_to("acos(0.03)", "1.5407918249714", Radian); - assert_parsed_expression_evaluates_to("acos(0.5)", "60", Degree); + assert_parsed_expression_evaluates_to("acos(0.5)", "1.0471975511966", System, Radian); + assert_parsed_expression_evaluates_to("acos(0.03)", "1.5407918249714", System, Radian); + assert_parsed_expression_evaluates_to("acos(0.5)", "60", System, Degree); // On [1, inf[ - assert_parsed_expression_evaluates_to("acos(2)", "1.3169578969248*I", Radian); - assert_parsed_expression_evaluates_to("acos(2)", "75.456129290217*I", Degree); + assert_parsed_expression_evaluates_to("acos(2)", "1.3169578969248*I", System, Radian); + assert_parsed_expression_evaluates_to("acos(2)", "75.456129290217*I", System, Degree); // Symmetry: odd on imaginary - assert_parsed_expression_evaluates_to("acos(-2)", "3.1415926535898-1.3169578969248*I", Radian); - assert_parsed_expression_evaluates_to("acos(-2)", "180-75.456129290217*I", Degree); + assert_parsed_expression_evaluates_to("acos(-2)", "3.1415926535898-1.3169578969248*I", System, Radian); + assert_parsed_expression_evaluates_to("acos(-2)", "180-75.456129290217*I", System, Degree); // On ]-inf, -1[ - assert_parsed_expression_evaluates_to("acos(-32)", "3.1415926535898-4.1586388532792*I", Radian); - assert_parsed_expression_evaluates_to("acos(-32)", "180-238.2725*I", Degree); + assert_parsed_expression_evaluates_to("acos(-32)", "3.1415926535898-4.1586388532792*I", System, Radian); + assert_parsed_expression_evaluates_to("acos(-32)", "180-238.2725*I", System, Degree); // On R*i - assert_parsed_expression_evaluates_to("acos(3*I)", "1.5708-1.8184*I", Radian, Cartesian, 5); - assert_parsed_expression_evaluates_to("acos(3*I)", "90-104.19*I", Degree, Cartesian, 5); + assert_parsed_expression_evaluates_to("acos(3*I)", "1.5708-1.8184*I", System, Radian, Cartesian, 5); + assert_parsed_expression_evaluates_to("acos(3*I)", "90-104.19*I", System, Degree, Cartesian, 5); // Symmetry: odd on imaginary - assert_parsed_expression_evaluates_to("acos(-3*I)", "1.5708+1.8184*I", Radian, Cartesian, 5); - assert_parsed_expression_evaluates_to("acos(-3*I)", "90+104.19*I", Degree, Cartesian, 5); + assert_parsed_expression_evaluates_to("acos(-3*I)", "1.5708+1.8184*I", System, Radian, Cartesian, 5); + assert_parsed_expression_evaluates_to("acos(-3*I)", "90+104.19*I", System, Degree, Cartesian, 5); // On C - assert_parsed_expression_evaluates_to("acos(I-4)", "2.8894-2.0966*I", Radian, Cartesian, 5); - assert_parsed_expression_evaluates_to("acos(I-4)", "165.551-120.126*I", Degree, Cartesian, 6); + assert_parsed_expression_evaluates_to("acos(I-4)", "2.8894-2.0966*I", System, Radian, Cartesian, 5); + assert_parsed_expression_evaluates_to("acos(I-4)", "165.551-120.126*I", System, Degree, Cartesian, 6); // Key values - assert_parsed_expression_evaluates_to("acos(0)", "90", Degree); - assert_parsed_expression_evaluates_to("acos(-1)", "180", Degree); - assert_parsed_expression_evaluates_to("acos(1)", "0", Degree); + assert_parsed_expression_evaluates_to("acos(0)", "90", System, Degree); + assert_parsed_expression_evaluates_to("acos(-1)", "180", System, Degree); + assert_parsed_expression_evaluates_to("acos(1)", "0", System, Degree); /* asin: [-1,1] -> R * ]-inf,-1[ -> -Pi/2+R*i (odd) @@ -124,29 +124,29 @@ QUIZ_CASE(poincare_trigo_evaluate) { * R*i -> R*i (odd) */ // On [-1, 1] - assert_parsed_expression_evaluates_to("asin(0.5)", "0.5235987755983", Radian); - assert_parsed_expression_evaluates_to("asin(0.03)", "3.0004501823477E-2", Radian); - assert_parsed_expression_evaluates_to("asin(0.5)", "30", Degree); + assert_parsed_expression_evaluates_to("asin(0.5)", "0.5235987755983", System, Radian); + assert_parsed_expression_evaluates_to("asin(0.03)", "3.0004501823477E-2", System, Radian); + assert_parsed_expression_evaluates_to("asin(0.5)", "30", System, Degree); // On [1, inf[ - assert_parsed_expression_evaluates_to("asin(2)", "1.5707963267949-1.3169578969248*I", Radian); - assert_parsed_expression_evaluates_to("asin(2)", "90-75.456129290217*I", Degree); + assert_parsed_expression_evaluates_to("asin(2)", "1.5707963267949-1.3169578969248*I", System, Radian); + assert_parsed_expression_evaluates_to("asin(2)", "90-75.456129290217*I", System, Degree); // Symmetry: odd - assert_parsed_expression_evaluates_to("asin(-2)", "-1.5707963267949+1.3169578969248*I", Radian); - assert_parsed_expression_evaluates_to("asin(-2)", "-90+75.456129290217*I", Degree); + assert_parsed_expression_evaluates_to("asin(-2)", "-1.5707963267949+1.3169578969248*I", System, Radian); + assert_parsed_expression_evaluates_to("asin(-2)", "-90+75.456129290217*I", System, Degree); // On ]-inf, -1[ - assert_parsed_expression_evaluates_to("asin(-32)", "-1.571+4.159*I", Radian, Cartesian, 4); - assert_parsed_expression_evaluates_to("asin(-32)", "-90+238*I", Degree, Cartesian, 3); + assert_parsed_expression_evaluates_to("asin(-32)", "-1.571+4.159*I", System, Radian, Cartesian, 4); + assert_parsed_expression_evaluates_to("asin(-32)", "-90+238*I", System, Degree, Cartesian, 3); // On R*i - assert_parsed_expression_evaluates_to("asin(3*I)", "1.8184464592321*I", Radian); + assert_parsed_expression_evaluates_to("asin(3*I)", "1.8184464592321*I", System, Radian); // Symmetry: odd - assert_parsed_expression_evaluates_to("asin(-3*I)", "-1.8184464592321*I", Radian); + assert_parsed_expression_evaluates_to("asin(-3*I)", "-1.8184464592321*I", System, Radian); // On C - assert_parsed_expression_evaluates_to("asin(I-4)", "-1.3186+2.0966*I", Radian, Cartesian, 5); - assert_parsed_expression_evaluates_to("asin(I-4)", "-75.551+120.13*I", Degree, Cartesian, 5); + assert_parsed_expression_evaluates_to("asin(I-4)", "-1.3186+2.0966*I", System, Radian, Cartesian, 5); + assert_parsed_expression_evaluates_to("asin(I-4)", "-75.551+120.13*I", System, Degree, Cartesian, 5); // Key values - assert_parsed_expression_evaluates_to("asin(0)", "0", Degree); - assert_parsed_expression_evaluates_to("asin(-1)", "-90", Degree); - assert_parsed_expression_evaluates_to("asin(1)", "90", Degree); + assert_parsed_expression_evaluates_to("asin(0)", "0", System, Degree); + assert_parsed_expression_evaluates_to("asin(-1)", "-90", System, Degree); + assert_parsed_expression_evaluates_to("asin(1)", "90", System, Degree); /* atan: R -> R (odd) * [-i,i] -> R*i (odd) @@ -154,91 +154,91 @@ QUIZ_CASE(poincare_trigo_evaluate) { * ]i, inf*i[ -> Pi/2+R*i (odd) */ // On R - assert_parsed_expression_evaluates_to("atan(2)", "1.1071487177941", Radian); - assert_parsed_expression_evaluates_to("atan(0.01)", "9.9996666866652E-3", Radian); - assert_parsed_expression_evaluates_to("atan(2)", "63.434948822922", Degree); - assert_parsed_expression_evaluates_to("atan(0.5)", "0.4636476", Radian); + assert_parsed_expression_evaluates_to("atan(2)", "1.1071487177941", System, Radian); + assert_parsed_expression_evaluates_to("atan(0.01)", "9.9996666866652E-3", System, Radian); + assert_parsed_expression_evaluates_to("atan(2)", "63.434948822922", System, Degree); + assert_parsed_expression_evaluates_to("atan(0.5)", "0.4636476", System, Radian); // Symmetry: odd - assert_parsed_expression_evaluates_to("atan(-2)", "-1.1071487177941", Radian); + assert_parsed_expression_evaluates_to("atan(-2)", "-1.1071487177941", System, Radian); // On [-i, i] - assert_parsed_expression_evaluates_to("atan(0.2*I)", "0.202733*I", Radian, Cartesian, 6); + assert_parsed_expression_evaluates_to("atan(0.2*I)", "0.202733*I", System, Radian, Cartesian, 6); // Symmetry: odd - assert_parsed_expression_evaluates_to("atan(-0.2*I)", "-0.202733*I", Radian, Cartesian, 6); + assert_parsed_expression_evaluates_to("atan(-0.2*I)", "-0.202733*I", System, Radian, Cartesian, 6); // On [i, inf*i[ - assert_parsed_expression_evaluates_to("atan(26*I)", "1.5707963267949+3.8480520568064E-2*I", Radian); - assert_parsed_expression_evaluates_to("atan(26*I)", "90+2.2047714220164*I", Degree); + assert_parsed_expression_evaluates_to("atan(26*I)", "1.5707963267949+3.8480520568064E-2*I", System, Radian); + assert_parsed_expression_evaluates_to("atan(26*I)", "90+2.2047714220164*I", System, Degree); // Symmetry: odd - assert_parsed_expression_evaluates_to("atan(-26*I)", "-1.5707963267949-3.8480520568064E-2*I", Radian); + assert_parsed_expression_evaluates_to("atan(-26*I)", "-1.5707963267949-3.8480520568064E-2*I", System, Radian); // On ]-inf*i, -i[ - assert_parsed_expression_evaluates_to("atan(-3.4*I)", "-1.570796-0.3030679*I", Radian); - assert_parsed_expression_evaluates_to("atan(-3.4*I)", "-90-17.3645*I", Degree, Cartesian, 6); + assert_parsed_expression_evaluates_to("atan(-3.4*I)", "-1.570796-0.3030679*I", System, Radian); + assert_parsed_expression_evaluates_to("atan(-3.4*I)", "-90-17.3645*I", System, Degree, Cartesian, 6); // On C - assert_parsed_expression_evaluates_to("atan(I-4)", "-1.338973+0.05578589*I", Radian); - assert_parsed_expression_evaluates_to("atan(I-4)", "-76.7175+3.1963*I", Degree, Cartesian, 6); + assert_parsed_expression_evaluates_to("atan(I-4)", "-1.338973+0.05578589*I", System, Radian); + assert_parsed_expression_evaluates_to("atan(I-4)", "-76.7175+3.1963*I", System, Degree, Cartesian, 6); // Key values - assert_parsed_expression_evaluates_to("atan(0)", "0", Degree); - assert_parsed_expression_evaluates_to("atan(-I)", "-inf*I", Radian); - assert_parsed_expression_evaluates_to("atan(I)", "inf*I", Radian); + assert_parsed_expression_evaluates_to("atan(0)", "0", System, Degree); + assert_parsed_expression_evaluates_to("atan(-I)", "-inf*I", System, Radian); + assert_parsed_expression_evaluates_to("atan(I)", "inf*I", System, Radian); /* cosh: R -> R (even) * R*i -> R (oscillator) */ // On R - assert_parsed_expression_evaluates_to("cosh(2)", "3.7621956910836", Radian); - assert_parsed_expression_evaluates_to("cosh(2)", "3.7621956910836", Degree); + assert_parsed_expression_evaluates_to("cosh(2)", "3.7621956910836", System, Radian); + assert_parsed_expression_evaluates_to("cosh(2)", "3.7621956910836", System, Degree); // Symmetry: even - assert_parsed_expression_evaluates_to("cosh(-2)", "3.7621956910836", Radian); - assert_parsed_expression_evaluates_to("cosh(-2)", "3.7621956910836", Degree); + assert_parsed_expression_evaluates_to("cosh(-2)", "3.7621956910836", System, Radian); + assert_parsed_expression_evaluates_to("cosh(-2)", "3.7621956910836", System, Degree); // On R*i - assert_parsed_expression_evaluates_to("cosh(43*I)", "5.5511330152063E-1", Radian); + assert_parsed_expression_evaluates_to("cosh(43*I)", "5.5511330152063E-1", System, Radian); // Oscillator - assert_parsed_expression_evaluates_to("cosh(P*I/2)", "0", Radian); - assert_parsed_expression_evaluates_to("cosh(5*P*I/2)", "0", Radian); - assert_parsed_expression_evaluates_to("cosh(8*P*I/2)", "1", Radian); - assert_parsed_expression_evaluates_to("cosh(9*P*I/2)", "0", Radian); + assert_parsed_expression_evaluates_to("cosh(P*I/2)", "0", System, Radian); + assert_parsed_expression_evaluates_to("cosh(5*P*I/2)", "0", System, Radian); + assert_parsed_expression_evaluates_to("cosh(8*P*I/2)", "1", System, Radian); + assert_parsed_expression_evaluates_to("cosh(9*P*I/2)", "0", System, Radian); // On C - assert_parsed_expression_evaluates_to("cosh(I-4)", "14.7547-22.9637*I", Radian, Cartesian, 6); - assert_parsed_expression_evaluates_to("cosh(I-4)", "14.7547-22.9637*I", Degree, Cartesian, 6); + assert_parsed_expression_evaluates_to("cosh(I-4)", "14.7547-22.9637*I", System, Radian, Cartesian, 6); + assert_parsed_expression_evaluates_to("cosh(I-4)", "14.7547-22.9637*I", System, Degree, Cartesian, 6); /* sinh: R -> R (odd) * R*i -> R*i (oscillator) */ // On R - assert_parsed_expression_evaluates_to("sinh(2)", "3.626860407847", Radian); - assert_parsed_expression_evaluates_to("sinh(2)", "3.626860407847", Degree); + assert_parsed_expression_evaluates_to("sinh(2)", "3.626860407847", System, Radian); + assert_parsed_expression_evaluates_to("sinh(2)", "3.626860407847", System, Degree); // Symmetry: odd - assert_parsed_expression_evaluates_to("sinh(-2)", "-3.626860407847", Radian); + assert_parsed_expression_evaluates_to("sinh(-2)", "-3.626860407847", System, Radian); // On R*i - assert_parsed_expression_evaluates_to("sinh(43*I)", "-0.8317747426286*I", Radian); + assert_parsed_expression_evaluates_to("sinh(43*I)", "-0.8317747426286*I", System, Radian); // Oscillator - assert_parsed_expression_evaluates_to("sinh(P*I/2)", "I", Radian); - assert_parsed_expression_evaluates_to("sinh(5*P*I/2)", "I", Radian); - assert_parsed_expression_evaluates_to("sinh(7*P*I/2)", "-I", Radian); - assert_parsed_expression_evaluates_to("sinh(8*P*I/2)", "0", Radian); - assert_parsed_expression_evaluates_to("sinh(9*P*I/2)", "I", Radian); + assert_parsed_expression_evaluates_to("sinh(P*I/2)", "I", System, Radian); + assert_parsed_expression_evaluates_to("sinh(5*P*I/2)", "I", System, Radian); + assert_parsed_expression_evaluates_to("sinh(7*P*I/2)", "-I", System, Radian); + assert_parsed_expression_evaluates_to("sinh(8*P*I/2)", "0", System, Radian); + assert_parsed_expression_evaluates_to("sinh(9*P*I/2)", "I", System, Radian); // On C - assert_parsed_expression_evaluates_to("sinh(I-4)", "-14.7448+22.9791*I", Radian, Cartesian, 6); - assert_parsed_expression_evaluates_to("sinh(I-4)", "-14.7448+22.9791*I", Degree, Cartesian, 6); + assert_parsed_expression_evaluates_to("sinh(I-4)", "-14.7448+22.9791*I", System, Radian, Cartesian, 6); + assert_parsed_expression_evaluates_to("sinh(I-4)", "-14.7448+22.9791*I", System, Degree, Cartesian, 6); /* tanh: R -> R (odd) * R*i -> R*i (tangent-style) */ // On R - assert_parsed_expression_evaluates_to("tanh(2)", "9.6402758007582E-1", Radian); + assert_parsed_expression_evaluates_to("tanh(2)", "9.6402758007582E-1", System, Radian); // Symmetry: odd - assert_parsed_expression_evaluates_to("tanh(-2)", "-9.6402758007582E-1", Degree); + assert_parsed_expression_evaluates_to("tanh(-2)", "-9.6402758007582E-1", System, Degree); // On R*i - assert_parsed_expression_evaluates_to("tanh(43*I)", "-1.4983873388552*I", Radian); + assert_parsed_expression_evaluates_to("tanh(43*I)", "-1.4983873388552*I", System, Radian); // Tangent-style // FIXME: this depends on the libm implementation and does not work on travis/appveyor servers - /*assert_parsed_expression_evaluates_to("tanh(P*I/2)", Undefined::Name(), Radian); - assert_parsed_expression_evaluates_to("tanh(5*P*I/2)", Undefined::Name(), Radian); - assert_parsed_expression_evaluates_to("tanh(7*P*I/2)", Undefined::Name(), Radian); - assert_parsed_expression_evaluates_to("tanh(8*P*I/2)", "0", Radian); - assert_parsed_expression_evaluates_to("tanh(9*P*I/2)", Undefined::Name(), Radian);*/ + /*assert_parsed_expression_evaluates_to("tanh(P*I/2)", Undefined::Name(), System, Radian); + assert_parsed_expression_evaluates_to("tanh(5*P*I/2)", Undefined::Name(), System, Radian); + assert_parsed_expression_evaluates_to("tanh(7*P*I/2)", Undefined::Name(), System, Radian); + assert_parsed_expression_evaluates_to("tanh(8*P*I/2)", "0", System, Radian); + assert_parsed_expression_evaluates_to("tanh(9*P*I/2)", Undefined::Name(), System, Radian);*/ // On C - assert_parsed_expression_evaluates_to("tanh(I-4)", "-1.00028+0.000610241*I", Radian, Cartesian, 6); - assert_parsed_expression_evaluates_to("tanh(I-4)", "-1.00028+0.000610241*I", Degree, Cartesian, 6); + assert_parsed_expression_evaluates_to("tanh(I-4)", "-1.00028+0.000610241*I", System, Radian, Cartesian, 6); + assert_parsed_expression_evaluates_to("tanh(I-4)", "-1.00028+0.000610241*I", System, Degree, Cartesian, 6); /* acosh: [-1,1] -> R*i * ]-inf,-1[ -> Pi*i+R (even on real) @@ -247,27 +247,27 @@ QUIZ_CASE(poincare_trigo_evaluate) { * ]0, inf*i[ -> Pi/2*i+R (even on real) */ // On [-1,1] - assert_parsed_expression_evaluates_to("acosh(2)", "1.3169578969248", Radian); - assert_parsed_expression_evaluates_to("acosh(2)", "1.3169578969248", Degree); + assert_parsed_expression_evaluates_to("acosh(2)", "1.3169578969248", System, Radian); + assert_parsed_expression_evaluates_to("acosh(2)", "1.3169578969248", System, Degree); // On ]-inf, -1[ - assert_parsed_expression_evaluates_to("acosh(-4)", "2.0634370688956+3.1415926535898*I", Radian); - assert_parsed_expression_evaluates_to("acosh(-4)", "2.06344+3.14159*I", Radian, Cartesian, 6); + assert_parsed_expression_evaluates_to("acosh(-4)", "2.0634370688956+3.1415926535898*I", System, Radian); + assert_parsed_expression_evaluates_to("acosh(-4)", "2.06344+3.14159*I", System, Radian, Cartesian, 6); // On ]1,inf[: Symmetry: even on real - assert_parsed_expression_evaluates_to("acosh(4)", "2.0634370688956", Radian); - assert_parsed_expression_evaluates_to("acosh(4)", "2.063437", Radian); + assert_parsed_expression_evaluates_to("acosh(4)", "2.0634370688956", System, Radian); + assert_parsed_expression_evaluates_to("acosh(4)", "2.063437", System, Radian); // On ]-inf*i, 0[ - assert_parsed_expression_evaluates_to("acosh(-42*I)", "4.4309584920805-1.5707963267949*I", Radian); - assert_parsed_expression_evaluates_to("acosh(-42*I)", "4.431-1.571*I", Radian, Cartesian, 4); + assert_parsed_expression_evaluates_to("acosh(-42*I)", "4.4309584920805-1.5707963267949*I", System, Radian); + assert_parsed_expression_evaluates_to("acosh(-42*I)", "4.431-1.571*I", System, Radian, Cartesian, 4); // On ]0, i*inf[: Symmetry: even on real - assert_parsed_expression_evaluates_to("acosh(42*I)", "4.4309584920805+1.5707963267949*I", Radian); - assert_parsed_expression_evaluates_to("acosh(42*I)", "4.431+1.571*I", Radian, Cartesian, 4); + assert_parsed_expression_evaluates_to("acosh(42*I)", "4.4309584920805+1.5707963267949*I", System, Radian); + assert_parsed_expression_evaluates_to("acosh(42*I)", "4.431+1.571*I", System, Radian, Cartesian, 4); // On C - assert_parsed_expression_evaluates_to("acosh(I-4)", "2.0966+2.8894*I", Radian, Cartesian, 5); - assert_parsed_expression_evaluates_to("acosh(I-4)", "2.0966+2.8894*I", Degree, Cartesian, 5); + assert_parsed_expression_evaluates_to("acosh(I-4)", "2.0966+2.8894*I", System, Radian, Cartesian, 5); + assert_parsed_expression_evaluates_to("acosh(I-4)", "2.0966+2.8894*I", System, Degree, Cartesian, 5); // Key values - //assert_parsed_expression_evaluates_to("acosh(-1)", "3.1415926535898*I", Radian); - assert_parsed_expression_evaluates_to("acosh(1)", "0", Radian); - assert_parsed_expression_evaluates_to("acosh(0)", "1.570796*I", Radian); + //assert_parsed_expression_evaluates_to("acosh(-1)", "3.1415926535898*I", System, Radian); + assert_parsed_expression_evaluates_to("acosh(1)", "0", System, Radian); + assert_parsed_expression_evaluates_to("acosh(0)", "1.570796*I", System, Radian); /* asinh: R -> R (odd) * [-i,i] -> R*i (odd) @@ -275,26 +275,26 @@ QUIZ_CASE(poincare_trigo_evaluate) { * ]i, inf*I[ -> Pi/2*I+R (odd) */ // On R - assert_parsed_expression_evaluates_to("asinh(2)", "1.4436354751788", Radian); - assert_parsed_expression_evaluates_to("asinh(2)", "1.4436354751788", Degree); + assert_parsed_expression_evaluates_to("asinh(2)", "1.4436354751788", System, Radian); + assert_parsed_expression_evaluates_to("asinh(2)", "1.4436354751788", System, Degree); // Symmetry: odd - assert_parsed_expression_evaluates_to("asinh(-2)", "-1.4436354751788", Radian); - assert_parsed_expression_evaluates_to("asinh(-2)", "-1.4436354751788", Degree); + assert_parsed_expression_evaluates_to("asinh(-2)", "-1.4436354751788", System, Radian); + assert_parsed_expression_evaluates_to("asinh(-2)", "-1.4436354751788", System, Degree); // On [-i,i] - assert_parsed_expression_evaluates_to("asinh(0.2*I)", "2.0135792079033E-1*I", Radian); - assert_parsed_expression_evaluates_to("asinh(0.2*I)", "0.2013579*I", Degree); + assert_parsed_expression_evaluates_to("asinh(0.2*I)", "2.0135792079033E-1*I", System, Radian); + assert_parsed_expression_evaluates_to("asinh(0.2*I)", "0.2013579*I", System, Degree); // Symmetry: odd - assert_parsed_expression_evaluates_to("asinh(-0.2*I)", "-2.0135792079033E-1*I", Radian); - assert_parsed_expression_evaluates_to("asinh(-0.2*I)", "-0.2013579*I", Degree); + assert_parsed_expression_evaluates_to("asinh(-0.2*I)", "-2.0135792079033E-1*I", System, Radian); + assert_parsed_expression_evaluates_to("asinh(-0.2*I)", "-0.2013579*I", System, Degree); // On ]-inf*i, -i[ - assert_parsed_expression_evaluates_to("asinh(-22*I)", "-3.7836727043295-1.5707963267949*I", Radian); - assert_parsed_expression_evaluates_to("asinh(-22*I)", "-3.784-1.571*I", Degree, Cartesian, 4); + assert_parsed_expression_evaluates_to("asinh(-22*I)", "-3.7836727043295-1.5707963267949*I", System, Radian); + assert_parsed_expression_evaluates_to("asinh(-22*I)", "-3.784-1.571*I", System, Degree, Cartesian, 4); // On ]i, inf*i[, Symmetry: odd - assert_parsed_expression_evaluates_to("asinh(22*I)", "3.7836727043295+1.5707963267949*I", Radian); - assert_parsed_expression_evaluates_to("asinh(22*I)", "3.784+1.571*I", Degree, Cartesian, 4); + assert_parsed_expression_evaluates_to("asinh(22*I)", "3.7836727043295+1.5707963267949*I", System, Radian); + assert_parsed_expression_evaluates_to("asinh(22*I)", "3.784+1.571*I", System, Degree, Cartesian, 4); // On C - assert_parsed_expression_evaluates_to("asinh(I-4)", "-2.123+0.2383*I", Radian, Cartesian, 4); - assert_parsed_expression_evaluates_to("asinh(I-4)", "-2.123+0.2383*I", Degree, Cartesian, 4); + assert_parsed_expression_evaluates_to("asinh(I-4)", "-2.123+0.2383*I", System, Radian, Cartesian, 4); + assert_parsed_expression_evaluates_to("asinh(I-4)", "-2.123+0.2383*I", System, Degree, Cartesian, 4); /* atanh: [-1,1] -> R (odd) * ]-inf,-1[ -> Pi/2*i+R (odd) @@ -302,37 +302,37 @@ QUIZ_CASE(poincare_trigo_evaluate) { * R*i -> R*i (odd) */ // On [-1,1] - assert_parsed_expression_evaluates_to("atanh(0.4)", "0.4236489301936", Radian); - assert_parsed_expression_evaluates_to("atanh(0.4)", "0.4236489301936", Degree); + assert_parsed_expression_evaluates_to("atanh(0.4)", "0.4236489301936", System, Radian); + assert_parsed_expression_evaluates_to("atanh(0.4)", "0.4236489301936", System, Degree); // Symmetry: odd - assert_parsed_expression_evaluates_to("atanh(-0.4)", "-0.4236489301936", Radian); - assert_parsed_expression_evaluates_to("atanh(-0.4)", "-0.4236489301936", Degree); + assert_parsed_expression_evaluates_to("atanh(-0.4)", "-0.4236489301936", System, Radian); + assert_parsed_expression_evaluates_to("atanh(-0.4)", "-0.4236489301936", System, Degree); // On ]1, inf[ - assert_parsed_expression_evaluates_to("atanh(4)", "0.255412811883-1.5707963267949*I", Radian); - assert_parsed_expression_evaluates_to("atanh(4)", "0.2554128-1.570796*I", Degree); + assert_parsed_expression_evaluates_to("atanh(4)", "0.255412811883-1.5707963267949*I", System, Radian); + assert_parsed_expression_evaluates_to("atanh(4)", "0.2554128-1.570796*I", System, Degree); // On ]-inf,-1[, Symmetry: odd - assert_parsed_expression_evaluates_to("atanh(-4)", "-0.255412811883+1.5707963267949*I", Radian); - assert_parsed_expression_evaluates_to("atanh(-4)", "-0.2554128+1.570796*I", Degree); + assert_parsed_expression_evaluates_to("atanh(-4)", "-0.255412811883+1.5707963267949*I", System, Radian); + assert_parsed_expression_evaluates_to("atanh(-4)", "-0.2554128+1.570796*I", System, Degree); // On R*i - assert_parsed_expression_evaluates_to("atanh(4*I)", "1.325817663668*I", Radian); - assert_parsed_expression_evaluates_to("atanh(4*I)", "1.325818*I", Radian); + assert_parsed_expression_evaluates_to("atanh(4*I)", "1.325817663668*I", System, Radian); + assert_parsed_expression_evaluates_to("atanh(4*I)", "1.325818*I", System, Radian); // Symmetry: odd - assert_parsed_expression_evaluates_to("atanh(-4*I)", "-1.325817663668*I", Radian); - assert_parsed_expression_evaluates_to("atanh(-4*I)", "-1.325818*I", Radian); + assert_parsed_expression_evaluates_to("atanh(-4*I)", "-1.325817663668*I", System, Radian); + assert_parsed_expression_evaluates_to("atanh(-4*I)", "-1.325818*I", System, Radian); // On C - assert_parsed_expression_evaluates_to("atanh(I-4)", "-0.238878+1.50862*I", Radian, Cartesian, 6); - assert_parsed_expression_evaluates_to("atanh(I-4)", "-0.238878+1.50862*I", Degree, Cartesian, 6); + assert_parsed_expression_evaluates_to("atanh(I-4)", "-0.238878+1.50862*I", System, Radian, Cartesian, 6); + assert_parsed_expression_evaluates_to("atanh(I-4)", "-0.238878+1.50862*I", System, Degree, Cartesian, 6); // WARNING: evaluate on branch cut can be multivalued - assert_parsed_expression_evaluates_to("acos(2)", "1.3169578969248*I", Radian); - assert_parsed_expression_evaluates_to("acos(2)", "75.456129290217*I", Degree); - assert_parsed_expression_evaluates_to("asin(2)", "1.5707963267949-1.3169578969248*I", Radian); - assert_parsed_expression_evaluates_to("asin(2)", "90-75.456129290217*I", Degree); - assert_parsed_expression_evaluates_to("atanh(2)", "5.4930614433405E-1-1.5707963267949*I", Radian); - assert_parsed_expression_evaluates_to("atan(2I)", "1.5707963267949+5.4930614433405E-1*I", Radian); - assert_parsed_expression_evaluates_to("atan(2I)", "90+31.472923730945*I", Degree); - assert_parsed_expression_evaluates_to("asinh(2I)", "1.3169578969248+1.5707963267949*I", Radian); - assert_parsed_expression_evaluates_to("acosh(-2)", "1.3169578969248+3.1415926535898*I", Radian); + assert_parsed_expression_evaluates_to("acos(2)", "1.3169578969248*I", System, Radian); + assert_parsed_expression_evaluates_to("acos(2)", "75.456129290217*I", System, Degree); + assert_parsed_expression_evaluates_to("asin(2)", "1.5707963267949-1.3169578969248*I", System, Radian); + assert_parsed_expression_evaluates_to("asin(2)", "90-75.456129290217*I", System, Degree); + assert_parsed_expression_evaluates_to("atanh(2)", "5.4930614433405E-1-1.5707963267949*I", System, Radian); + assert_parsed_expression_evaluates_to("atan(2I)", "1.5707963267949+5.4930614433405E-1*I", System, Radian); + assert_parsed_expression_evaluates_to("atan(2I)", "90+31.472923730945*I", System, Degree); + assert_parsed_expression_evaluates_to("asinh(2I)", "1.3169578969248+1.5707963267949*I", System, Radian); + assert_parsed_expression_evaluates_to("acosh(-2)", "1.3169578969248+3.1415926535898*I", System, Radian); } QUIZ_CASE(poincare_trigo_simplify) { @@ -368,23 +368,23 @@ QUIZ_CASE(poincare_trigo_simplify) { assert_parsed_expression_simplify_to("cos(-P/3)", "1/2"); assert_parsed_expression_simplify_to("cos(41P/5)", "(R(5)+1)/4"); assert_parsed_expression_simplify_to("cos(7P/10)", "-(R(2)*R(-R(5)+5))/4"); - assert_parsed_expression_simplify_to("cos(0)", "1", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(180)", "-1", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(720/7)", "-cos(540/7)", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(6300/29)", "-cos(1080/29)", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(-6300/29)", "-cos(1080/29)", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(61200000)", "1", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(-61200180)", "-1", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(-180*R(2))", "cos(180*R(2))", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(39330)", "0", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(15)", "(R(6)+R(2))/4", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(-15)", "(R(6)+R(2))/4", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(-765/2)", "R(R(2)+2)/2", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(7380/6)", "-R(3)/2", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(180045)", "R(2)/2", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(-60)", "1/2", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(7380/5)", "(R(5)+1)/4", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(112.5)", "-R(-R(2)+2)/2", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(0)", "1", User, Degree); + assert_parsed_expression_simplify_to("cos(180)", "-1", User, Degree); + assert_parsed_expression_simplify_to("cos(720/7)", "-cos(540/7)", User, Degree); + assert_parsed_expression_simplify_to("cos(6300/29)", "-cos(1080/29)", User, Degree); + assert_parsed_expression_simplify_to("cos(-6300/29)", "-cos(1080/29)", User, Degree); + assert_parsed_expression_simplify_to("cos(61200000)", "1", User, Degree); + assert_parsed_expression_simplify_to("cos(-61200180)", "-1", User, Degree); + assert_parsed_expression_simplify_to("cos(-180*R(2))", "cos(180*R(2))", User, Degree); + assert_parsed_expression_simplify_to("cos(39330)", "0", User, Degree); + assert_parsed_expression_simplify_to("cos(15)", "(R(6)+R(2))/4", User, Degree); + assert_parsed_expression_simplify_to("cos(-15)", "(R(6)+R(2))/4", User, Degree); + assert_parsed_expression_simplify_to("cos(-765/2)", "R(R(2)+2)/2", User, Degree); + assert_parsed_expression_simplify_to("cos(7380/6)", "-R(3)/2", User, Degree); + assert_parsed_expression_simplify_to("cos(180045)", "R(2)/2", User, Degree); + assert_parsed_expression_simplify_to("cos(-60)", "1/2", User, Degree); + assert_parsed_expression_simplify_to("cos(7380/5)", "(R(5)+1)/4", User, Degree); + assert_parsed_expression_simplify_to("cos(112.5)", "-R(-R(2)+2)/2", User, Degree); // -- sin assert_parsed_expression_simplify_to("sin(0)", "0"); assert_parsed_expression_simplify_to("sin(P)", "0"); @@ -404,23 +404,23 @@ QUIZ_CASE(poincare_trigo_simplify) { assert_parsed_expression_simplify_to("sin(-P/3)", "-R(3)/2"); assert_parsed_expression_simplify_to("sin(17P/5)", "-(R(2)*R(R(5)+5))/4"); assert_parsed_expression_simplify_to("sin(P/5)", "(R(2)*R(-R(5)+5))/4"); - assert_parsed_expression_simplify_to("sin(0)", "0", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(180)", "0", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(6300/29)", "-sin(1080/29)", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(-6300/29)", "sin(1080/29)", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(61200000)", "0", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(61200180)", "0", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(-61200180)", "0", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(15)", "(R(6)-R(2))/4", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(-15)", "(-R(6)+R(2))/4", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(-180*R(2))", "-sin(180*R(2))", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(39330)", "1", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(-765/2)", "-R(-R(2)+2)/2", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(1230)", "1/2", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(180045)", "R(2)/2", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(-60)", "-R(3)/2", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(612)", "-(R(2)*R(R(5)+5))/4", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(36)", "(R(2)*R(-R(5)+5))/4", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(0)", "0", User, Degree); + assert_parsed_expression_simplify_to("sin(180)", "0", User, Degree); + assert_parsed_expression_simplify_to("sin(6300/29)", "-sin(1080/29)", User, Degree); + assert_parsed_expression_simplify_to("sin(-6300/29)", "sin(1080/29)", User, Degree); + assert_parsed_expression_simplify_to("sin(61200000)", "0", User, Degree); + assert_parsed_expression_simplify_to("sin(61200180)", "0", User, Degree); + assert_parsed_expression_simplify_to("sin(-61200180)", "0", User, Degree); + assert_parsed_expression_simplify_to("sin(15)", "(R(6)-R(2))/4", User, Degree); + assert_parsed_expression_simplify_to("sin(-15)", "(-R(6)+R(2))/4", User, Degree); + assert_parsed_expression_simplify_to("sin(-180*R(2))", "-sin(180*R(2))", User, Degree); + assert_parsed_expression_simplify_to("sin(39330)", "1", User, Degree); + assert_parsed_expression_simplify_to("sin(-765/2)", "-R(-R(2)+2)/2", User, Degree); + assert_parsed_expression_simplify_to("sin(1230)", "1/2", User, Degree); + assert_parsed_expression_simplify_to("sin(180045)", "R(2)/2", User, Degree); + assert_parsed_expression_simplify_to("sin(-60)", "-R(3)/2", User, Degree); + assert_parsed_expression_simplify_to("sin(612)", "-(R(2)*R(R(5)+5))/4", User, Degree); + assert_parsed_expression_simplify_to("sin(36)", "(R(2)*R(-R(5)+5))/4", User, Degree); // -- tan assert_parsed_expression_simplify_to("tan(0)", "0"); assert_parsed_expression_simplify_to("tan(P)", "0"); @@ -438,21 +438,21 @@ QUIZ_CASE(poincare_trigo_simplify) { assert_parsed_expression_simplify_to("tan(P/4+1000P)", "1"); assert_parsed_expression_simplify_to("tan(-P/3)", "-R(3)"); assert_parsed_expression_simplify_to("tan(-P/10)", "-(R(5)*R(-2*R(5)+5))/5"); - assert_parsed_expression_simplify_to("tan(0)", "0", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("tan(180)", "0", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("tan(6300/29)", "tan(1080/29)", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("tan(-6300/29)", "-tan(1080/29)", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("tan(61200000)", "0", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("tan(61200180)", "0", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("tan(-61200180)", "0", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("tan(15)", "-R(3)+2", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("tan(-15)", "R(3)-2", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("tan(-180*R(2))", "-tan(180*R(2))", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("tan(39330)", Undefined::Name(), Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("tan(-382.5)", "-R(2)+1", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("tan(1230)", "-R(3)/3", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("tan(180045)", "1", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("tan(-60)", "-R(3)", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(0)", "0", User, Degree); + assert_parsed_expression_simplify_to("tan(180)", "0", User, Degree); + assert_parsed_expression_simplify_to("tan(6300/29)", "tan(1080/29)", User, Degree); + assert_parsed_expression_simplify_to("tan(-6300/29)", "-tan(1080/29)", User, Degree); + assert_parsed_expression_simplify_to("tan(61200000)", "0", User, Degree); + assert_parsed_expression_simplify_to("tan(61200180)", "0", User, Degree); + assert_parsed_expression_simplify_to("tan(-61200180)", "0", User, Degree); + assert_parsed_expression_simplify_to("tan(15)", "-R(3)+2", User, Degree); + assert_parsed_expression_simplify_to("tan(-15)", "R(3)-2", User, Degree); + assert_parsed_expression_simplify_to("tan(-180*R(2))", "-tan(180*R(2))", User, Degree); + assert_parsed_expression_simplify_to("tan(39330)", Undefined::Name(), User, Degree); + assert_parsed_expression_simplify_to("tan(-382.5)", "-R(2)+1", User, Degree); + assert_parsed_expression_simplify_to("tan(1230)", "-R(3)/3", User, Degree); + assert_parsed_expression_simplify_to("tan(180045)", "1", User, Degree); + assert_parsed_expression_simplify_to("tan(-60)", "-R(3)", User, Degree); assert_parsed_expression_simplify_to("tan(tan(tan(tan(9))))", "tan(tan(tan(tan(9))))"); // -- acos assert_parsed_expression_simplify_to("acos(-1/2)", "(2*P)/3"); @@ -464,15 +464,15 @@ QUIZ_CASE(poincare_trigo_simplify) { assert_parsed_expression_simplify_to("acos(cos(12))", "acos(cos(12))"); assert_parsed_expression_simplify_to("acos(cos(4P/7))", "(4*P)/7"); assert_parsed_expression_simplify_to("acos(-cos(2))", "P-2"); - assert_parsed_expression_simplify_to("acos(-1/2)", "120", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("acos(-1.2)", "-acos(6/5)+180", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("acos(cos(2/3))", "2/3", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("acos(cos(190))", "170", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("acos(cos(75))", "75", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(acos(190))", "190", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(acos(75))", "75", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("acos(cos(12))", "12", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("acos(cos(720/7))", "720/7", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("acos(-1/2)", "120", User, Degree); + assert_parsed_expression_simplify_to("acos(-1.2)", "-acos(6/5)+180", User, Degree); + assert_parsed_expression_simplify_to("acos(cos(2/3))", "2/3", User, Degree); + assert_parsed_expression_simplify_to("acos(cos(190))", "170", User, Degree); + assert_parsed_expression_simplify_to("acos(cos(75))", "75", User, Degree); + assert_parsed_expression_simplify_to("cos(acos(190))", "190", User, Degree); + assert_parsed_expression_simplify_to("cos(acos(75))", "75", User, Degree); + assert_parsed_expression_simplify_to("acos(cos(12))", "12", User, Degree); + assert_parsed_expression_simplify_to("acos(cos(720/7))", "720/7", User, Degree); // -- asin assert_parsed_expression_simplify_to("asin(-1/2)", "-P/6"); assert_parsed_expression_simplify_to("asin(-1.2)", "-asin(6/5)"); @@ -483,14 +483,14 @@ QUIZ_CASE(poincare_trigo_simplify) { assert_parsed_expression_simplify_to("asin(sin(12))", "asin(sin(12))"); assert_parsed_expression_simplify_to("asin(sin(-P/7))", "-P/7"); assert_parsed_expression_simplify_to("asin(sin(-R(2)))", "-R(2)"); - assert_parsed_expression_simplify_to("asin(-1/2)", "-30", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("asin(-1.2)", "-asin(6/5)", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("asin(sin(75))", "75", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(asin(75))", "75", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(asin(190))", "190", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("asin(sin(32))", "32", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("asin(sin(400))", "40", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("asin(sin(-180/7))", "-180/7", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("asin(-1/2)", "-30", User, Degree); + assert_parsed_expression_simplify_to("asin(-1.2)", "-asin(6/5)", User, Degree); + assert_parsed_expression_simplify_to("asin(sin(75))", "75", User, Degree); + assert_parsed_expression_simplify_to("sin(asin(75))", "75", User, Degree); + assert_parsed_expression_simplify_to("sin(asin(190))", "190", User, Degree); + assert_parsed_expression_simplify_to("asin(sin(32))", "32", User, Degree); + assert_parsed_expression_simplify_to("asin(sin(400))", "40", User, Degree); + assert_parsed_expression_simplify_to("asin(sin(-180/7))", "-180/7", User, Degree); // -- atan assert_parsed_expression_simplify_to("atan(-1)", "-P/4"); assert_parsed_expression_simplify_to("atan(-1.2)", "-atan(6/5)"); @@ -502,33 +502,33 @@ QUIZ_CASE(poincare_trigo_simplify) { assert_parsed_expression_simplify_to("atan(tan(-P/7))", "-P/7"); assert_parsed_expression_simplify_to("atan(R(3))", "P/3"); assert_parsed_expression_simplify_to("atan(tan(-R(2)))", "-R(2)"); - assert_parsed_expression_simplify_to("atan(-1)", "-45", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("atan(-1.2)", "-atan(6/5)", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("atan(tan(-45))", "-45", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("tan(atan(120))", "120", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("tan(atan(2293))", "2293", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("atan(tan(2293))", "-47", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("atan(tan(1808))", "8", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("atan(tan(-180/7))", "-180/7", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("atan(R(3))", "60", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("atan(1/x)", "(P*sign(x)-2*atan(x))/2", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("atan(-1)", "-45", User, Degree); + assert_parsed_expression_simplify_to("atan(-1.2)", "-atan(6/5)", User, Degree); + assert_parsed_expression_simplify_to("atan(tan(-45))", "-45", User, Degree); + assert_parsed_expression_simplify_to("tan(atan(120))", "120", User, Degree); + assert_parsed_expression_simplify_to("tan(atan(2293))", "2293", User, Degree); + assert_parsed_expression_simplify_to("atan(tan(2293))", "-47", User, Degree); + assert_parsed_expression_simplify_to("atan(tan(1808))", "8", User, Degree); + assert_parsed_expression_simplify_to("atan(tan(-180/7))", "-180/7", User, Degree); + assert_parsed_expression_simplify_to("atan(R(3))", "60", User, Degree); + assert_parsed_expression_simplify_to("atan(1/x)", "(P*sign(x)-2*atan(x))/2", User, Degree); // cos(arcsin) - assert_parsed_expression_simplify_to("cos(asin(x))", "R(-x^2+1)", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(asin(-x))", "R(-x^2+1)", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(asin(x))", "R(-x^2+1)", User, Degree); + assert_parsed_expression_simplify_to("cos(asin(-x))", "R(-x^2+1)", User, Degree); // cos(arctan) - assert_parsed_expression_simplify_to("cos(atan(x))", "1/R(x^2+1)", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(atan(-x))", "1/R(x^2+1)", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(atan(x))", "1/R(x^2+1)", User, Degree); + assert_parsed_expression_simplify_to("cos(atan(-x))", "1/R(x^2+1)", User, Degree); // sin(arccos) - assert_parsed_expression_simplify_to("sin(acos(x))", "R(-x^2+1)", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(acos(-x))", "R(-x^2+1)", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(acos(x))", "R(-x^2+1)", User, Degree); + assert_parsed_expression_simplify_to("sin(acos(-x))", "R(-x^2+1)", User, Degree); // sin(arctan) - assert_parsed_expression_simplify_to("sin(atan(x))", "x/R(x^2+1)", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(atan(-x))", "-x/R(x^2+1)", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(atan(x))", "x/R(x^2+1)", User, Degree); + assert_parsed_expression_simplify_to("sin(atan(-x))", "-x/R(x^2+1)", User, Degree); // tan(arccos) - assert_parsed_expression_simplify_to("tan(acos(x))", "R(-x^2+1)/x", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("tan(acos(-x))", "-R(-x^2+1)/x", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(acos(x))", "R(-x^2+1)/x", User, Degree); + assert_parsed_expression_simplify_to("tan(acos(-x))", "-R(-x^2+1)/x", User, Degree); // tan(arcsin) - assert_parsed_expression_simplify_to("tan(asin(x))", "x/R(-x^2+1)", Preferences::AngleUnit::Degree); - assert_parsed_expression_simplify_to("tan(asin(-x))", "-x/R(-x^2+1)", Preferences::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(asin(x))", "x/R(-x^2+1)", User, Degree); + assert_parsed_expression_simplify_to("tan(asin(-x))", "-x/R(-x^2+1)", User, Degree); } From dac9672729b85e602bc4e86313096a80afa6de69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 13 Feb 2019 15:39:44 +0100 Subject: [PATCH 291/373] [poincare] Power: Improve optional rule x^(p/q)->root(x,q)^p to handle special case p = 1 or q = 1 --- poincare/src/power.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index f9c85211e..fd512f539 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -785,11 +785,16 @@ Expression Power::shallowBeautify(Context & context, Preferences::ComplexFormat return result; } - // Optional Step 3: if the ReductionTarget is the System, turn a^(p/q) into (root(a, q))^p + /* Optional Step 3: if the ReductionTarget is the System, turn a^(p/q) into + * (root(a, q))^p + * Indeed, root(a, q) can have a real root which is not the principale angle + * but that we want to return in real complex format. This special case is + * handled in NthRoot approximation but not in Power approximation. */ if (target == ExpressionNode::ReductionTarget::System && childAtIndex(1).type() == ExpressionNode::Type::Rational) { Integer p = childAtIndex(1).convert().signedIntegerNumerator(); Integer q = childAtIndex(1).convert().integerDenominator(); - Expression result = Power(NthRoot::Builder(childAtIndex(0), Rational(q)), Rational(p)); + Expression nthRoot = q.isOne() ? childAtIndex(0) : NthRoot::Builder(childAtIndex(0), Rational(q)); + Expression result = p.isOne() ? nthRoot : Power(nthRoot, Rational(p)); replaceWithInPlace(result); return result; } From 4dc513e5c5b9cd26b538b34503b6b6f448edf821 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 13 Feb 2019 16:00:49 +0100 Subject: [PATCH 292/373] [poincare] Power: fix (x+1)^0 reduction when the Reduction target is System --- poincare/Makefile | 2 +- poincare/src/power.cpp | 3 ++ .../test/{simplify_mix.cpp => simplify.cpp} | 32 +++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) rename poincare/test/{simplify_mix.cpp => simplify.cpp} (67%) diff --git a/poincare/Makefile b/poincare/Makefile index 2d562b546..891a50338 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -170,7 +170,7 @@ tests += $(addprefix poincare/test/,\ power.cpp\ properties.cpp\ rational.cpp\ - simplify_mix.cpp\ + simplify.cpp\ store.cpp\ subtraction.cpp\ symbol.cpp\ diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index fd512f539..ddfaeb77d 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -667,6 +667,7 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co // Step 13: (a0+a1+...am)^n with n integer -> a^n+?a^(n-1)*b+?a^(n-2)*b^2+...+b^n (Multinome) if (!letPowerAtRoot && childAtIndex(1).type() == ExpressionNode::Type::Rational + && !childAtIndex(1).convert().signedIntegerNumerator().isZero() && childAtIndex(1).convert().integerDenominator().isOne() && childAtIndex(0).type() == ExpressionNode::Type::Addition) { @@ -679,6 +680,8 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co return *this; } int clippedN = n.extractedInt(); // Authorized because n < k_maxNumberOfTermsInExpandedMultinome + assert(clippedN > 0); + // Number of terms in addition m int m = childAtIndex(0).numberOfChildren(); /* The multinome (a0+a2+...+a(m-1))^n has BinomialCoefficient(n+m-1,n) terms; diff --git a/poincare/test/simplify_mix.cpp b/poincare/test/simplify.cpp similarity index 67% rename from poincare/test/simplify_mix.cpp rename to poincare/test/simplify.cpp index 6ff433b1d..e6a5e6e2f 100644 --- a/poincare/test/simplify_mix.cpp +++ b/poincare/test/simplify.cpp @@ -9,6 +9,38 @@ using namespace std; #endif using namespace Poincare; +QUIZ_CASE(poincare_reduction_target) { + assert_parsed_expression_simplify_to("1/P+1/x", "1/x+1/P", System); + assert_parsed_expression_simplify_to("1/P+1/x", "(x+P)/(P*x)", User); + + assert_parsed_expression_simplify_to("1/(1+I)", "1/(I+1)", System); + assert_parsed_expression_simplify_to("1/(1+I)", "1/2-1/2*I", User); + + assert_parsed_expression_simplify_to("sin(x)/(cos(x)*cos(x))", "sin(x)/cos(x)^2", System); + assert_parsed_expression_simplify_to("sin(x)/(cos(x)*cos(x))", "tan(x)/cos(x)", User); + + assert_parsed_expression_simplify_to("x^0", "x^0", System); + assert_parsed_expression_simplify_to("x^0", "1", User); + + assert_parsed_expression_simplify_to("x^(2/3)", "root(x,3)^2", System); + assert_parsed_expression_simplify_to("x^(2/3)", "x^(2/3)", User); + assert_parsed_expression_simplify_to("x^(1/3)", "root(x,3)", System); + assert_parsed_expression_simplify_to("x^(1/3)", "root(x,3)", System); + assert_parsed_expression_simplify_to("x^2", "x^2", System); + assert_parsed_expression_simplify_to("x^2", "x^2", User); + + assert_parsed_expression_simplify_to("1/(R(2)+R(3))", "1/(R(3)+R(2))", System); + assert_parsed_expression_simplify_to("1/(R(2)+R(3))", "R(3)-R(2)", User); + + assert_parsed_expression_simplify_to("sign(abs(x))", "sign(abs(x))", System); + assert_parsed_expression_simplify_to("sign(abs(x))", "1", User); + + assert_parsed_expression_simplify_to("atan(1/x)", "atan(1/x)", System); + assert_parsed_expression_simplify_to("atan(1/x)", "(P*sign(x)-2*atan(x))/2", User); + + assert_parsed_expression_simplify_to("(1+x)/(1+x)", "(x+1)^0", System); + assert_parsed_expression_simplify_to("(1+x)/(1+x)", "1", User); +} QUIZ_CASE(poincare_simplify_mix) { // Root at denominator From 93acf0b1a54b673b742437b4aae26baae2adf05d Mon Sep 17 00:00:00 2001 From: Roman Wueest <47526796+RomanWu@users.noreply.github.com> Date: Tue, 12 Feb 2019 13:38:16 +0100 Subject: [PATCH 293/373] Fix german typo in shared.de.i18n "Name" always uppercase. --- apps/shared.de.i18n | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/shared.de.i18n b/apps/shared.de.i18n index 06bebef52..26fed1661 100644 --- a/apps/shared.de.i18n +++ b/apps/shared.de.i18n @@ -32,7 +32,7 @@ Language = "Sprache" LowBattery = "Batterie erschoepft" Mean = "Mittelwert" Move = " Verschieben: " -NameCannotStartWithNumber = "Ein name darf nicht mit einer Zahl beginnen" +NameCannotStartWithNumber = "Ein Name darf nicht mit einer Zahl beginnen" NameTaken = "Dieser Name ist bereits vergeben" NameTooLong = "Der Name ist zu lang" Next = "Naechste" From 70b91523bcaf6094c1cabf00b6b90d715b272ca6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Da=20Costa=20Faro?= Date: Mon, 21 Jan 2019 17:29:18 +0100 Subject: [PATCH 294/373] Update .travis.yml to allow Makefile parallelization --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 07d14f852..dd49009c1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,9 @@ language: cpp +env: + global: + - MAKEFLAGS="-j 2" + addons: apt: sources: From 73bd40292afa7701de9b266c983133b5857d1006 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 15 Feb 2019 14:58:23 +0100 Subject: [PATCH 295/373] [poincare] Power: fix rule R(-x) --> i*R(x) is not true if x < 0 --- poincare/src/power.cpp | 9 ++++++--- poincare/test/power.cpp | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index ddfaeb77d..cfe491353 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -510,10 +510,13 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co return simplifyRationalRationalPower(context, complexFormat, angleUnit, target); } } - // Step 7: (a)^(1/2) with a < 0 --> i*(-a)^(1/2) - // WARNING: this rule true only if a real (ex: (-1*i)^(1/2) != i*i^(1/2) + // Step 7: (a)^(1/2) --> i*(-a)^(1/2) + // WARNING: this rule true only if: + // - a real: (-1*i)^(1/2) != i*i^(1/2) + // - a is negative: (-(-2))^(1/2) != -2^(1/2) + // We apply this rule only when a is a negative numeral if (!letPowerAtRoot - && childAtIndex(0).isReal(context) + && childAtIndex(0).isNumber() && childAtIndex(1).type() == ExpressionNode::Type::Rational && childAtIndex(1).convert().isHalf()) { diff --git a/poincare/test/power.cpp b/poincare/test/power.cpp index 6a8e9c479..f536686b5 100644 --- a/poincare/test/power.cpp +++ b/poincare/test/power.cpp @@ -102,4 +102,5 @@ QUIZ_CASE(poincare_power_simplify) { assert_parsed_expression_simplify_to("I^(2/3)", "1/2+R(3)/2*I"); assert_parsed_expression_simplify_to("X^(I*P/3)", "1/2+R(3)/2*I"); assert_parsed_expression_simplify_to("(-1)^(1/3)", "1/2+R(3)/2*I"); + assert_parsed_expression_simplify_to("R(-x)", "R(-x)"); } From 13dbc3edb31b7e5672c17823f124eb03970e2756 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 15 Feb 2019 14:59:52 +0100 Subject: [PATCH 296/373] [poincare] Power: (a^b)^c -> a^(b*c) with a < 0 and c integer is not always true when complex format is real: R(-1)^2 is undefined --- poincare/src/power.cpp | 15 +++++++++++++-- poincare/test/power.cpp | 2 ++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index cfe491353..1cfa9a51f 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -574,7 +574,15 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co return result; } } - // Step 10: (a^b)^c -> a^(b*c) if a > 0 or c is integer + /* Step 10: (a^b)^c -> a^(b*c) + * This rule is not generally true: ((-2)^2)^(1/2) != (-2)^(2*1/2) = -2 + * This rule is true if: + * - a > 0 + * - in Real: when b and c are integers + * - in other modes: when c is integer + * (Warning: in real mode only c integer is not enough: + * ex: ((-2)^(1/2))^2 = unreal != -2) + */ if (childAtIndex(0).type() == ExpressionNode::Type::Power) { Power p = childAtIndex(0).convert(); // Check if a > 0 or c is Integer @@ -582,7 +590,10 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co || (childAtIndex(1).type() == ExpressionNode::Type::Rational && childAtIndex(1).convert().integerDenominator().isOne())) { - return simplifyPowerPower(context, complexFormat, angleUnit, target); + // Check that the complex format is not Real or that b is an integer + if (complexFormat != Preferences::ComplexFormat::Real || (p.childAtIndex(1).type() == ExpressionNode::Type::Rational && p.childAtIndex(1).convert().integerDenominator().isOne())) { + return simplifyPowerPower(context, complexFormat, angleUnit, target); + } } } // Step 11: (a*b*c*...)^r ? diff --git a/poincare/test/power.cpp b/poincare/test/power.cpp index f536686b5..99f86e06c 100644 --- a/poincare/test/power.cpp +++ b/poincare/test/power.cpp @@ -103,4 +103,6 @@ QUIZ_CASE(poincare_power_simplify) { assert_parsed_expression_simplify_to("X^(I*P/3)", "1/2+R(3)/2*I"); assert_parsed_expression_simplify_to("(-1)^(1/3)", "1/2+R(3)/2*I"); assert_parsed_expression_simplify_to("R(-x)", "R(-x)"); + assert_parsed_expression_simplify_to("R(x)^2", "x", User, Radian, Cartesian); + assert_parsed_expression_simplify_to("R(x)^2", "R(x)^2", User, Radian, Real); } From 8029aab060b9ae87b0893227d569edc85c7ef90a Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Fri, 21 Dec 2018 11:32:43 +0100 Subject: [PATCH 297/373] [apps/calculation] Remove unecessary namespace --- apps/calculation/history_view_cell.cpp | 4 ++-- apps/calculation/history_view_cell.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/calculation/history_view_cell.cpp b/apps/calculation/history_view_cell.cpp index 9bc595365..318798a80 100644 --- a/apps/calculation/history_view_cell.cpp +++ b/apps/calculation/history_view_cell.cpp @@ -10,9 +10,9 @@ namespace Calculation { /* HistoryViewCellDataSource */ HistoryViewCellDataSource::HistoryViewCellDataSource() : - m_selectedSubviewType(HistoryViewCellDataSource::SubviewType::Output) {} + m_selectedSubviewType(SubviewType::Output) {} -void HistoryViewCellDataSource::setSelectedSubviewType(HistoryViewCellDataSource::SubviewType subviewType, HistoryViewCell * cell) { +void HistoryViewCellDataSource::setSelectedSubviewType(SubviewType subviewType, HistoryViewCell * cell) { m_selectedSubviewType = subviewType; if (cell) { cell->setHighlighted(cell->isHighlighted()); diff --git a/apps/calculation/history_view_cell.h b/apps/calculation/history_view_cell.h index f3a0eade1..c3c99fc97 100644 --- a/apps/calculation/history_view_cell.h +++ b/apps/calculation/history_view_cell.h @@ -17,7 +17,7 @@ public: Output }; HistoryViewCellDataSource(); - void setSelectedSubviewType(HistoryViewCellDataSource::SubviewType subviewType, HistoryViewCell * cell = nullptr); + void setSelectedSubviewType(SubviewType subviewType, HistoryViewCell * cell = nullptr); SubviewType selectedSubviewType() { return m_selectedSubviewType; } private: SubviewType m_selectedSubviewType; From 9a46f42a97dc54bca3c7c7df0f4bdf9f1c6db236 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Mon, 24 Dec 2018 16:56:26 +0100 Subject: [PATCH 298/373] [apps/shared] Fix indentation --- apps/shared/scrollable_exact_approximate_expressions_view.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/shared/scrollable_exact_approximate_expressions_view.h b/apps/shared/scrollable_exact_approximate_expressions_view.h index f14011fd5..5f963ea75 100644 --- a/apps/shared/scrollable_exact_approximate_expressions_view.h +++ b/apps/shared/scrollable_exact_approximate_expressions_view.h @@ -60,7 +60,7 @@ private: MessageTextView m_approximateSign; ExpressionView m_leftExpressionView; SubviewPosition m_selectedSubviewPosition; -}; + }; ContentCell m_contentCell; }; From 8772e1dc100c26418fec18e55f26e4b6763639ba Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Wed, 26 Dec 2018 10:59:37 +0100 Subject: [PATCH 299/373] [escher] Factorize ScrollView::layoutSubViews() --- escher/src/scroll_view.cpp | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index 11fc00f64..015b5f527 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -139,32 +139,19 @@ void ScrollView::layoutSubviews() { // Layout indicators /* If the two indicators are visible, we leave an empty rectangle in the right * bottom corner. Otherwise, the only indicator uses all the height/width. */ - if (hasHorizontalIndicator() && hasVerticalIndicator()) { - KDRect verticalIndicatorFrame = KDRect( + if (hasVerticalIndicator()) { + KDRect verticalIndicatorFrame = KDRect( m_frame.width() - m_indicatorThickness, 0, - m_indicatorThickness, m_frame.height() - m_indicatorThickness + m_indicatorThickness, m_frame.height() - hasHorizontalIndicator() * m_indicatorThickness ); m_verticalScrollIndicator.setFrame(verticalIndicatorFrame); + } + if (hasHorizontalIndicator()) { KDRect horizontalIndicatorFrame = KDRect( 0, m_frame.height() - m_indicatorThickness, - m_frame.width() - m_indicatorThickness, m_indicatorThickness + m_frame.width() - hasVerticalIndicator() * m_indicatorThickness, m_indicatorThickness ); - m_horizontalScrollIndicator.setFrame(horizontalIndicatorFrame); - } else { - if (hasVerticalIndicator()) { - KDRect verticalIndicatorFrame = KDRect( - m_frame.width() - m_indicatorThickness, 0, - m_indicatorThickness, m_frame.height() - ); - m_verticalScrollIndicator.setFrame(verticalIndicatorFrame); - } - if (hasHorizontalIndicator()) { - KDRect horizontalIndicatorFrame = KDRect( - 0, m_frame.height() - m_indicatorThickness, - m_frame.width(), m_indicatorThickness - ); - m_horizontalScrollIndicator.setFrame(horizontalIndicatorFrame); - } + m_horizontalScrollIndicator.setFrame(horizontalIndicatorFrame); } } From 7114fbc8dc4f2768feea88529d74be3500ac4f33 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Tue, 8 Jan 2019 15:19:48 +0100 Subject: [PATCH 300/373] [escher] Simplify ScrollViewIndicator --- escher/include/escher/scroll_view.h | 3 - escher/include/escher/scroll_view_indicator.h | 14 ++-- escher/src/scroll_view.cpp | 80 +++++++------------ escher/src/scroll_view_indicator.cpp | 51 +++++------- 4 files changed, 54 insertions(+), 94 deletions(-) diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index 097913aa1..7000ccc09 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -47,7 +47,6 @@ protected: KDCoordinate maxContentHeightDisplayableWithoutScrolling(); KDRect visibleContentRect(); void layoutSubviews() override; - void updateScrollIndicator(); KDSize contentSize(); #if ESCHER_VIEW_LOGGING virtual const char * className() const override; @@ -61,8 +60,6 @@ private: ScrollViewIndicator m_verticalScrollIndicator; ScrollViewIndicator m_horizontalScrollIndicator; - bool hasVerticalIndicator() const; - bool hasHorizontalIndicator() const; KDCoordinate m_topMargin; KDCoordinate m_rightMargin; KDCoordinate m_bottomMargin; diff --git a/escher/include/escher/scroll_view_indicator.h b/escher/include/escher/scroll_view_indicator.h index fee919f2b..e568da8a1 100644 --- a/escher/include/escher/scroll_view_indicator.h +++ b/escher/include/escher/scroll_view_indicator.h @@ -19,11 +19,8 @@ public: void setMargin(KDCoordinate m) { m_margin = m; } KDCoordinate margin() const { return m_margin; } - float start() const; - void setStart(float start); - float end() const; - void setEnd(float end); - KDRect frame(); + void update(KDCoordinate totalContentLength, KDCoordinate contentOffset, KDCoordinate visibleContentLength); + bool visible() const { return 0 < m_offset || m_visibleLength < 1; } protected: #if ESCHER_VIEW_LOGGING virtual const char * className() const override; @@ -32,8 +29,11 @@ protected: private: constexpr static KDCoordinate k_indicatorThickness = 4; Direction m_direction; - float m_start; - float m_end; + KDCoordinate totalLength() const { + return ((m_direction == Direction::Horizontal) ? m_frame.width() : m_frame.height()) - 2*m_margin; + } + float m_offset; + float m_visibleLength; KDColor m_indicatorColor; KDColor m_backgroundColor; KDCoordinate m_margin; diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index 015b5f527..8686d7a06 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -31,33 +31,22 @@ void ScrollView::setCommonMargins() { setLeftMargin(Metric::CommonLeftMargin); } -bool ScrollView::hasVerticalIndicator() const { - if (m_showsIndicators) { - return m_verticalScrollIndicator.end() < 1 || m_verticalScrollIndicator.start() > 0; - } - return false; -} - -bool ScrollView::hasHorizontalIndicator() const { - if (m_showsIndicators) { - return m_horizontalScrollIndicator.end() < 1 || m_horizontalScrollIndicator.start() > 0; - } - return false; -} - int ScrollView::numberOfSubviews() const { - return 1 + hasVerticalIndicator() + hasHorizontalIndicator(); + return (m_showsIndicators) ? 1 + m_verticalScrollIndicator.visible() + m_horizontalScrollIndicator.visible() : 1; } View * ScrollView::subviewAtIndex(int index) { - switch (index) { - case 0: - return m_contentView; - case 1: - return hasHorizontalIndicator() ? &m_horizontalScrollIndicator : &m_verticalScrollIndicator; - case 2: - return &m_verticalScrollIndicator; + if (index == 0) { + return m_contentView; + } + if (m_showsIndicators) { + switch (index) { + case 1: + return m_horizontalScrollIndicator.visible() ? &m_horizontalScrollIndicator : &m_verticalScrollIndicator; + case 2: + return &m_verticalScrollIndicator; } + } return nullptr; } @@ -133,52 +122,41 @@ void ScrollView::layoutSubviews() { KDRect contentFrame = KDRect(absoluteOffset, m_contentView->bounds().size()); m_contentView->setFrame(contentFrame); + if (!m_showsIndicators) { + return; + } + // We recompute the size of the scroll indicator - updateScrollIndicator(); + m_verticalScrollIndicator.update( + m_contentView->bounds().height()+m_topMargin+m_bottomMargin, + contentOffset().y(), + m_frame.height() + ); + m_horizontalScrollIndicator.update( + m_contentView->bounds().width()+m_leftMargin+m_rightMargin, + contentOffset().x(), + m_frame.width() + ); // Layout indicators /* If the two indicators are visible, we leave an empty rectangle in the right * bottom corner. Otherwise, the only indicator uses all the height/width. */ - if (hasVerticalIndicator()) { + if (m_verticalScrollIndicator.visible()) { KDRect verticalIndicatorFrame = KDRect( m_frame.width() - m_indicatorThickness, 0, - m_indicatorThickness, m_frame.height() - hasHorizontalIndicator() * m_indicatorThickness + m_indicatorThickness, m_frame.height() - m_horizontalScrollIndicator.visible() * m_indicatorThickness ); m_verticalScrollIndicator.setFrame(verticalIndicatorFrame); } - if (hasHorizontalIndicator()) { + if (m_horizontalScrollIndicator.visible()) { KDRect horizontalIndicatorFrame = KDRect( 0, m_frame.height() - m_indicatorThickness, - m_frame.width() - hasVerticalIndicator() * m_indicatorThickness, m_indicatorThickness + m_frame.width() - m_verticalScrollIndicator.visible() * m_indicatorThickness, m_indicatorThickness ); m_horizontalScrollIndicator.setFrame(horizontalIndicatorFrame); } } -void ScrollView::updateScrollIndicator() { - if (!m_showsIndicators) { - return; - } - float contentHeight = m_contentView->bounds().height()+m_topMargin+m_bottomMargin; - bool hadVerticalIndicator = hasVerticalIndicator(); - float verticalStart = contentOffset().y(); - float verticalEnd = contentOffset().y() + m_frame.height(); - m_verticalScrollIndicator.setStart(verticalStart/contentHeight); - m_verticalScrollIndicator.setEnd(verticalEnd/contentHeight); - if (hadVerticalIndicator && !hasVerticalIndicator()) { - markRectAsDirty(m_verticalScrollIndicator.frame()); - } - float contentWidth = m_contentView->bounds().width()+m_leftMargin+m_rightMargin; - bool hadHorizontalIndicator = hasHorizontalIndicator(); - float horizontalStart = contentOffset().x(); - float horizontalEnd = contentOffset().x() + m_frame.width(); - m_horizontalScrollIndicator.setStart(horizontalStart/contentWidth); - m_horizontalScrollIndicator.setEnd(horizontalEnd/contentWidth); - if (hadHorizontalIndicator && !hasHorizontalIndicator()) { - markRectAsDirty(m_horizontalScrollIndicator.frame()); - } -} - KDSize ScrollView::contentSize() { return m_contentView->minimalSizeForOptimalDisplay(); } diff --git a/escher/src/scroll_view_indicator.cpp b/escher/src/scroll_view_indicator.cpp index e5be1f5c8..3a7ece58f 100644 --- a/escher/src/scroll_view_indicator.cpp +++ b/escher/src/scroll_view_indicator.cpp @@ -7,8 +7,8 @@ extern "C" { ScrollViewIndicator::ScrollViewIndicator(ScrollViewIndicator::Direction direction) : View(), m_direction(direction), - m_start(0), - m_end(0), + m_offset(0), + m_visibleLength(0), m_indicatorColor(Palette::GreyDark), m_backgroundColor(Palette::GreyMiddle), m_margin(14) @@ -19,52 +19,37 @@ void ScrollViewIndicator::drawRect(KDContext * ctx, KDRect rect) const { KDRect frame = KDRectZero; if (m_direction == Direction::Horizontal) { frame = KDRect(m_margin, (m_frame.height() - k_indicatorThickness)/2, - m_frame.width() - 2*m_margin, k_indicatorThickness); + totalLength(), k_indicatorThickness); } else { assert(m_direction == Direction::Vertical); frame = KDRect((m_frame.width() - k_indicatorThickness)/2, m_margin, - k_indicatorThickness, m_frame.height() - 2*m_margin); + k_indicatorThickness, totalLength()); } ctx->fillRect(frame, m_backgroundColor); KDRect indicatorFrame = KDRectZero; if (m_direction == Direction::Horizontal) { - KDCoordinate indicatorWidth = m_frame.width() - 2*m_margin; - indicatorFrame = KDRect(m_margin+m_start*indicatorWidth, (m_frame.height() - k_indicatorThickness)/2, - (m_end-m_start)*indicatorWidth, k_indicatorThickness); + indicatorFrame = KDRect(m_margin+m_offset*totalLength(), (m_frame.height() - k_indicatorThickness)/2, + m_visibleLength*totalLength(), k_indicatorThickness); } else { assert(m_direction == Direction::Vertical); - KDCoordinate indicatorHeight = m_frame.height() - 2*m_margin; - indicatorFrame = KDRect((m_frame.width() - k_indicatorThickness)/2, m_margin+m_start*indicatorHeight, - k_indicatorThickness, (m_end-m_start)*indicatorHeight); + indicatorFrame = KDRect((m_frame.width() - k_indicatorThickness)/2, m_margin+m_offset*totalLength(), + k_indicatorThickness, m_visibleLength*totalLength()); } ctx->fillRect(indicatorFrame, m_indicatorColor); } -float ScrollViewIndicator::start() const { - return m_start; -} - -void ScrollViewIndicator::setStart(float start) { - if (m_start != start) { - m_start = start; +void ScrollViewIndicator::update(KDCoordinate totalContentLength, KDCoordinate contentOffset, KDCoordinate visibleContentLength) { + float offset = contentOffset; + float visibleLength = visibleContentLength; + offset = offset / totalContentLength; + visibleLength = visibleLength / totalContentLength; + if (m_offset != offset || m_visibleLength != visibleLength) { + m_offset = offset; + m_visibleLength = visibleLength; markRectAsDirty(bounds()); } } -float ScrollViewIndicator::end() const { - return m_end; -} - -void ScrollViewIndicator::setEnd(float end) { - if (m_end != end) { - m_end = end; - markRectAsDirty(bounds()); - } -} - -KDRect ScrollViewIndicator::frame() { - return m_frame; -} #if ESCHER_VIEW_LOGGING const char * ScrollViewIndicator::className() const { return "ScrollViewIndicator"; @@ -72,7 +57,7 @@ const char * ScrollViewIndicator::className() const { void ScrollViewIndicator::logAttributes(std::ostream &os) const { View::logAttributes(os); - os << " start=\"" << m_start << "\""; - os << " end=\"" << m_end << "\""; + os << " offset=\"" << m_offset << "\""; + os << " visibleLength=\"" << m_visibleLength << "\""; } #endif From 4936a3e7feb4483e2842f598768f73b3e9535800 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Tue, 8 Jan 2019 15:51:44 +0100 Subject: [PATCH 301/373] [escher] New ScrollViewHorizontalIndicator and ScrollViewVerticalIndicator --- escher/include/escher/scroll_view.h | 8 +-- escher/include/escher/scroll_view_indicator.h | 26 +++++---- escher/src/scroll_view.cpp | 9 ++- escher/src/scroll_view_indicator.cpp | 56 +++++++++++-------- 4 files changed, 58 insertions(+), 41 deletions(-) diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index 7000ccc09..43d6d3691 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -32,8 +32,8 @@ public: virtual void setBackgroundColor(KDColor c) { m_backgroundColor = c; } KDColor backgroundColor() const { return m_backgroundColor; } - ScrollViewIndicator * verticalScrollIndicator() { return &m_verticalScrollIndicator; } - ScrollViewIndicator * horizontalScrollIndicator() { return &m_horizontalScrollIndicator; } + ScrollViewVerticalIndicator * verticalScrollIndicator() { return &m_verticalScrollIndicator; } + ScrollViewHorizontalIndicator * horizontalScrollIndicator() { return &m_horizontalScrollIndicator; } void setIndicatorThickness(KDCoordinate t) { m_indicatorThickness = t; } KDCoordinate indicatorThickness() const { return m_indicatorThickness; } @@ -58,8 +58,8 @@ private: int numberOfSubviews() const override; View * subviewAtIndex(int index) override; - ScrollViewIndicator m_verticalScrollIndicator; - ScrollViewIndicator m_horizontalScrollIndicator; + ScrollViewVerticalIndicator m_verticalScrollIndicator; + ScrollViewHorizontalIndicator m_horizontalScrollIndicator; KDCoordinate m_topMargin; KDCoordinate m_rightMargin; KDCoordinate m_bottomMargin; diff --git a/escher/include/escher/scroll_view_indicator.h b/escher/include/escher/scroll_view_indicator.h index e568da8a1..7b8c9062c 100644 --- a/escher/include/escher/scroll_view_indicator.h +++ b/escher/include/escher/scroll_view_indicator.h @@ -5,12 +5,7 @@ class ScrollViewIndicator : public View { public: - enum class Direction { - Horizontal, - Vertical - }; - ScrollViewIndicator(Direction direction); - void drawRect(KDContext * ctx, KDRect rect) const override; + ScrollViewIndicator(); void setIndicatorColor(KDColor c) { m_indicatorColor = c; } KDColor indicatorColor() const { return m_indicatorColor; } @@ -26,12 +21,7 @@ protected: virtual const char * className() const override; virtual void logAttributes(std::ostream &os) const override; #endif -private: constexpr static KDCoordinate k_indicatorThickness = 4; - Direction m_direction; - KDCoordinate totalLength() const { - return ((m_direction == Direction::Horizontal) ? m_frame.width() : m_frame.height()) - 2*m_margin; - } float m_offset; float m_visibleLength; KDColor m_indicatorColor; @@ -39,4 +29,18 @@ private: KDCoordinate m_margin; }; +class ScrollViewHorizontalIndicator : public ScrollViewIndicator { +public: + void drawRect(KDContext * ctx, KDRect rect) const override; +private: + KDCoordinate totalLength() const { return m_frame.width() - 2*m_margin; } +}; + +class ScrollViewVerticalIndicator : public ScrollViewIndicator { +public: + void drawRect(KDContext * ctx, KDRect rect) const override; +private: + KDCoordinate totalLength() const { return m_frame.height() - 2*m_margin; } +}; + #endif diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index 8686d7a06..e1551f92a 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -10,8 +10,8 @@ ScrollView::ScrollView(View * contentView, ScrollViewDataSource * dataSource) : View(), m_contentView(contentView), m_dataSource(dataSource), - m_verticalScrollIndicator(ScrollViewIndicator::Direction::Vertical), - m_horizontalScrollIndicator(ScrollViewIndicator::Direction::Horizontal), + m_verticalScrollIndicator(), + m_horizontalScrollIndicator(), m_topMargin(0), m_rightMargin(0), m_bottomMargin(0), @@ -42,7 +42,10 @@ View * ScrollView::subviewAtIndex(int index) { if (m_showsIndicators) { switch (index) { case 1: - return m_horizontalScrollIndicator.visible() ? &m_horizontalScrollIndicator : &m_verticalScrollIndicator; + if (m_horizontalScrollIndicator.visible()) { + return &m_horizontalScrollIndicator; + } + return &m_verticalScrollIndicator; case 2: return &m_verticalScrollIndicator; } diff --git a/escher/src/scroll_view_indicator.cpp b/escher/src/scroll_view_indicator.cpp index 3a7ece58f..808f40719 100644 --- a/escher/src/scroll_view_indicator.cpp +++ b/escher/src/scroll_view_indicator.cpp @@ -4,9 +4,8 @@ extern "C" { #include } -ScrollViewIndicator::ScrollViewIndicator(ScrollViewIndicator::Direction direction) : +ScrollViewIndicator::ScrollViewIndicator() : View(), - m_direction(direction), m_offset(0), m_visibleLength(0), m_indicatorColor(Palette::GreyDark), @@ -15,27 +14,38 @@ ScrollViewIndicator::ScrollViewIndicator(ScrollViewIndicator::Direction directio { } -void ScrollViewIndicator::drawRect(KDContext * ctx, KDRect rect) const { - KDRect frame = KDRectZero; - if (m_direction == Direction::Horizontal) { - frame = KDRect(m_margin, (m_frame.height() - k_indicatorThickness)/2, - totalLength(), k_indicatorThickness); - } else { - assert(m_direction == Direction::Vertical); - frame = KDRect((m_frame.width() - k_indicatorThickness)/2, m_margin, - k_indicatorThickness, totalLength()); - } - ctx->fillRect(frame, m_backgroundColor); - KDRect indicatorFrame = KDRectZero; - if (m_direction == Direction::Horizontal) { - indicatorFrame = KDRect(m_margin+m_offset*totalLength(), (m_frame.height() - k_indicatorThickness)/2, - m_visibleLength*totalLength(), k_indicatorThickness); - } else { - assert(m_direction == Direction::Vertical); - indicatorFrame = KDRect((m_frame.width() - k_indicatorThickness)/2, m_margin+m_offset*totalLength(), - k_indicatorThickness, m_visibleLength*totalLength()); - } - ctx->fillRect(indicatorFrame, m_indicatorColor); +void ScrollViewHorizontalIndicator::drawRect(KDContext * ctx, KDRect rect) const { + ctx->fillRect( + KDRect( + m_margin, (m_frame.height() - k_indicatorThickness)/2, + totalLength(), k_indicatorThickness + ), + m_backgroundColor + ); + ctx->fillRect( + KDRect( + m_margin+m_offset*totalLength(), (m_frame.height() - k_indicatorThickness)/2, + m_visibleLength*totalLength(), k_indicatorThickness + ), + m_indicatorColor + ); +} + +void ScrollViewVerticalIndicator::drawRect(KDContext * ctx, KDRect rect) const { + ctx->fillRect( + KDRect( + (m_frame.width() - k_indicatorThickness)/2, m_margin, + k_indicatorThickness, totalLength() + ), + m_backgroundColor + ); + ctx->fillRect( + KDRect( + (m_frame.width() - k_indicatorThickness)/2, m_margin+m_offset*totalLength(), + k_indicatorThickness, m_visibleLength*totalLength() + ), + m_indicatorColor + ); } void ScrollViewIndicator::update(KDCoordinate totalContentLength, KDCoordinate contentOffset, KDCoordinate visibleContentLength) { From c02d44988b959a8ee745437d20ec9c14f074c6ef Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Tue, 22 Jan 2019 14:03:18 +0100 Subject: [PATCH 302/373] [escher/scroll_view] New ScrollView::Decorator class Containing the members specific to indicators --- apps/home/controller.cpp | 4 +- apps/shared/storage_values_controller.cpp | 2 +- apps/shared/values_controller.cpp | 2 +- escher/include/escher/scroll_view.h | 26 ++++-- escher/src/scroll_view.cpp | 109 +++++++++++++--------- 5 files changed, 86 insertions(+), 57 deletions(-) diff --git a/apps/home/controller.cpp b/apps/home/controller.cpp index aa99eb587..0873aadd8 100644 --- a/apps/home/controller.cpp +++ b/apps/home/controller.cpp @@ -12,8 +12,8 @@ Controller::ContentView::ContentView(Controller * controller, SelectableTableVie m_selectableTableView.setVerticalCellOverlap(0); m_selectableTableView.setMargins(0, k_sideMargin, k_bottomMargin, k_sideMargin); m_selectableTableView.setColorsBackground(false); - m_selectableTableView.setIndicatorThickness(k_indicatorThickness); - m_selectableTableView.verticalScrollIndicator()->setMargin(k_indicatorMargin); + m_selectableTableView.decorator()->setIndicatorThickness(k_indicatorThickness); + m_selectableTableView.decorator()->verticalBar()->setMargin(k_indicatorMargin); } SelectableTableView * Controller::ContentView::selectableTableView() { diff --git a/apps/shared/storage_values_controller.cpp b/apps/shared/storage_values_controller.cpp index 4a7558ee7..d72e856c1 100644 --- a/apps/shared/storage_values_controller.cpp +++ b/apps/shared/storage_values_controller.cpp @@ -32,7 +32,7 @@ StorageValuesController::StorageValuesController(Responder * parentResponder, In m_selectableTableView.setBottomMargin(k_bottomMargin); m_selectableTableView.setLeftMargin(k_leftMargin); m_selectableTableView.setBackgroundColor(Palette::WallScreenDark); - m_selectableTableView.setIndicatorThickness(13); + m_selectableTableView.decorator()->setIndicatorThickness(13); m_abscissaTitleCell.setMessageFont(k_font); for (int i = 0; i < k_maxNumberOfAbscissaCells; i++) { m_abscissaCells[i].setParentResponder(&m_selectableTableView); diff --git a/apps/shared/values_controller.cpp b/apps/shared/values_controller.cpp index 5a57c738a..3c7f49ab2 100644 --- a/apps/shared/values_controller.cpp +++ b/apps/shared/values_controller.cpp @@ -32,7 +32,7 @@ ValuesController::ValuesController(Responder * parentResponder, InputEventHandle m_selectableTableView.setBottomMargin(k_bottomMargin); m_selectableTableView.setLeftMargin(k_leftMargin); m_selectableTableView.setBackgroundColor(Palette::WallScreenDark); - m_selectableTableView.setIndicatorThickness(13); + m_selectableTableView.decorator()->setIndicatorThickness(13); m_abscissaTitleCell.setMessageFont(KDFont::SmallFont); for (int i = 0; i < k_maxNumberOfAbscissaCells; i++) { m_abscissaCells[i].setParentResponder(&m_selectableTableView); diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index 43d6d3691..86a505e8a 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -25,6 +25,22 @@ public: void setMargins(KDCoordinate m) { setMargins(m, m, m, m); } void setCommonMargins(); + class Decorator { + public: + Decorator(); + int numberOfIndicators(); + View * indicatorAtIndex(int index); + void layoutIndicators(KDSize content, KDPoint offset, KDSize frame); + ScrollViewVerticalIndicator * verticalBar() { return &m_verticalScrollIndicator; } + ScrollViewHorizontalIndicator * horizontalBar() { return &m_horizontalScrollIndicator; } + void setIndicatorThickness(KDCoordinate t) { m_indicatorThickness = t; } + private: + ScrollViewVerticalIndicator m_verticalScrollIndicator; + ScrollViewHorizontalIndicator m_horizontalScrollIndicator; + KDCoordinate m_indicatorThickness; + }; + + Decorator * decorator() { return &m_decorator; } void setShowsIndicators(bool s) { m_showsIndicators = s; } bool showsIndicators() const { return m_showsIndicators; } void setColorsBackground(bool c) { m_colorsBackground = c; } @@ -32,11 +48,6 @@ public: virtual void setBackgroundColor(KDColor c) { m_backgroundColor = c; } KDColor backgroundColor() const { return m_backgroundColor; } - ScrollViewVerticalIndicator * verticalScrollIndicator() { return &m_verticalScrollIndicator; } - ScrollViewHorizontalIndicator * horizontalScrollIndicator() { return &m_horizontalScrollIndicator; } - void setIndicatorThickness(KDCoordinate t) { m_indicatorThickness = t; } - KDCoordinate indicatorThickness() const { return m_indicatorThickness; } - void setContentOffset(KDPoint offset, bool forceRelayout = false); KDPoint contentOffset() const { return m_dataSource->offset(); } @@ -58,13 +69,12 @@ private: int numberOfSubviews() const override; View * subviewAtIndex(int index) override; - ScrollViewVerticalIndicator m_verticalScrollIndicator; - ScrollViewHorizontalIndicator m_horizontalScrollIndicator; KDCoordinate m_topMargin; KDCoordinate m_rightMargin; KDCoordinate m_bottomMargin; KDCoordinate m_leftMargin; - KDCoordinate m_indicatorThickness; + + Decorator m_decorator; bool m_showsIndicators; bool m_colorsBackground; KDColor m_backgroundColor; diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index e1551f92a..0421c2135 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -10,13 +10,11 @@ ScrollView::ScrollView(View * contentView, ScrollViewDataSource * dataSource) : View(), m_contentView(contentView), m_dataSource(dataSource), - m_verticalScrollIndicator(), - m_horizontalScrollIndicator(), m_topMargin(0), m_rightMargin(0), m_bottomMargin(0), m_leftMargin(0), - m_indicatorThickness(20), + m_decorator(), m_showsIndicators(true), m_colorsBackground(true), m_backgroundColor(Palette::WallScreen) @@ -32,7 +30,11 @@ void ScrollView::setCommonMargins() { } int ScrollView::numberOfSubviews() const { - return (m_showsIndicators) ? 1 + m_verticalScrollIndicator.visible() + m_horizontalScrollIndicator.visible() : 1; + int result = 1; + if (m_showsIndicators) { + result += const_cast(this)->m_decorator.numberOfIndicators(); + } + return result; } View * ScrollView::subviewAtIndex(int index) { @@ -40,15 +42,7 @@ View * ScrollView::subviewAtIndex(int index) { return m_contentView; } if (m_showsIndicators) { - switch (index) { - case 1: - if (m_horizontalScrollIndicator.visible()) { - return &m_horizontalScrollIndicator; - } - return &m_verticalScrollIndicator; - case 2: - return &m_verticalScrollIndicator; - } + return m_decorator.indicatorAtIndex(index); } return nullptr; } @@ -124,39 +118,12 @@ void ScrollView::layoutSubviews() { KDPoint absoluteOffset = contentOffset().opposite().translatedBy(KDPoint(m_leftMargin, m_topMargin)); KDRect contentFrame = KDRect(absoluteOffset, m_contentView->bounds().size()); m_contentView->setFrame(contentFrame); - - if (!m_showsIndicators) { - return; - } - - // We recompute the size of the scroll indicator - m_verticalScrollIndicator.update( - m_contentView->bounds().height()+m_topMargin+m_bottomMargin, - contentOffset().y(), - m_frame.height() - ); - m_horizontalScrollIndicator.update( - m_contentView->bounds().width()+m_leftMargin+m_rightMargin, - contentOffset().x(), - m_frame.width() - ); - - // Layout indicators - /* If the two indicators are visible, we leave an empty rectangle in the right - * bottom corner. Otherwise, the only indicator uses all the height/width. */ - if (m_verticalScrollIndicator.visible()) { - KDRect verticalIndicatorFrame = KDRect( - m_frame.width() - m_indicatorThickness, 0, - m_indicatorThickness, m_frame.height() - m_horizontalScrollIndicator.visible() * m_indicatorThickness + if (m_showsIndicators) { + KDSize content( + m_contentView->bounds().width() + m_leftMargin + m_rightMargin, + m_contentView->bounds().height() + m_topMargin + m_bottomMargin ); - m_verticalScrollIndicator.setFrame(verticalIndicatorFrame); - } - if (m_horizontalScrollIndicator.visible()) { - KDRect horizontalIndicatorFrame = KDRect( - 0, m_frame.height() - m_indicatorThickness, - m_frame.width() - m_verticalScrollIndicator.visible() * m_indicatorThickness, m_indicatorThickness - ); - m_horizontalScrollIndicator.setFrame(horizontalIndicatorFrame); + m_decorator.layoutIndicators(content, contentOffset(), m_frame.size()); } } @@ -178,6 +145,58 @@ KDCoordinate ScrollView::maxContentHeightDisplayableWithoutScrolling() { return m_frame.height() - m_topMargin - m_bottomMargin; } +ScrollView::Decorator::Decorator() : + m_verticalScrollIndicator(), + m_horizontalScrollIndicator(), + m_indicatorThickness(20) +{ +} + +int ScrollView::Decorator::numberOfIndicators() { + return m_verticalScrollIndicator.visible() + m_horizontalScrollIndicator.visible(); +} + +View * ScrollView::Decorator::indicatorAtIndex(int index) { + switch (index) { + case 1: + if (m_horizontalScrollIndicator.visible()) { + return &m_horizontalScrollIndicator; + } else { + return &m_verticalScrollIndicator; + } + case 2: + return &m_verticalScrollIndicator; + } + return nullptr; +} + +void ScrollView::Decorator::layoutIndicators(KDSize content, KDPoint offset, KDSize frame) { + m_horizontalScrollIndicator.update( + content.width(), + offset.x(), + frame.width() + ); + m_verticalScrollIndicator.update( + content.height(), + offset.y(), + frame.height() + ); + /* If the two indicators are visible, we leave an empty rectangle in the right + * bottom corner. Otherwise, the only indicator uses all the height/width. */ + if (m_verticalScrollIndicator.visible()) { + m_verticalScrollIndicator.setFrame(KDRect( + frame.width() - m_indicatorThickness, 0, + m_indicatorThickness, frame.height() - m_horizontalScrollIndicator.visible() * m_indicatorThickness + )); + } + if (m_horizontalScrollIndicator.visible()) { + m_horizontalScrollIndicator.setFrame(KDRect( + 0, frame.height() - m_indicatorThickness, + frame.width() - m_verticalScrollIndicator.visible() * m_indicatorThickness, m_indicatorThickness + )); + } +} + #if ESCHER_VIEW_LOGGING const char * ScrollView::className() const { return "ScrollView"; From 42d6ec66ab307e37bf29611c4e8e20228ef28d33 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Wed, 23 Jan 2019 17:19:47 +0100 Subject: [PATCH 303/373] [escher/scroll_view] Prepare ScrollViewIndicator for future ScrollViewArrow --- escher/include/escher/scroll_view.h | 8 +- escher/include/escher/scroll_view_indicator.h | 30 +++---- escher/src/scroll_view.cpp | 30 +++---- escher/src/scroll_view_indicator.cpp | 79 ++++++++++--------- 4 files changed, 76 insertions(+), 71 deletions(-) diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index 86a505e8a..dcd2096e8 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -31,12 +31,12 @@ public: int numberOfIndicators(); View * indicatorAtIndex(int index); void layoutIndicators(KDSize content, KDPoint offset, KDSize frame); - ScrollViewVerticalIndicator * verticalBar() { return &m_verticalScrollIndicator; } - ScrollViewHorizontalIndicator * horizontalBar() { return &m_horizontalScrollIndicator; } + ScrollViewVerticalBar * verticalBar() { return &m_verticalBar; } + ScrollViewHorizontalBar * horizontalBar() { return &m_horizontalBar; } void setIndicatorThickness(KDCoordinate t) { m_indicatorThickness = t; } private: - ScrollViewVerticalIndicator m_verticalScrollIndicator; - ScrollViewHorizontalIndicator m_horizontalScrollIndicator; + ScrollViewVerticalBar m_verticalBar; + ScrollViewHorizontalBar m_horizontalBar; KDCoordinate m_indicatorThickness; }; diff --git a/escher/include/escher/scroll_view_indicator.h b/escher/include/escher/scroll_view_indicator.h index 7b8c9062c..e75ec52f2 100644 --- a/escher/include/escher/scroll_view_indicator.h +++ b/escher/include/escher/scroll_view_indicator.h @@ -6,37 +6,37 @@ class ScrollViewIndicator : public View { public: ScrollViewIndicator(); - - void setIndicatorColor(KDColor c) { m_indicatorColor = c; } - KDColor indicatorColor() const { return m_indicatorColor; } - void setBackgroundColor(KDColor c) { m_backgroundColor = c; } - KDColor backgroundColor() const { return m_backgroundColor; } void setMargin(KDCoordinate m) { m_margin = m; } KDCoordinate margin() const { return m_margin; } - - void update(KDCoordinate totalContentLength, KDCoordinate contentOffset, KDCoordinate visibleContentLength); - bool visible() const { return 0 < m_offset || m_visibleLength < 1; } protected: #if ESCHER_VIEW_LOGGING virtual const char * className() const override; virtual void logAttributes(std::ostream &os) const override; #endif - constexpr static KDCoordinate k_indicatorThickness = 4; - float m_offset; - float m_visibleLength; - KDColor m_indicatorColor; - KDColor m_backgroundColor; + KDColor m_color; KDCoordinate m_margin; }; -class ScrollViewHorizontalIndicator : public ScrollViewIndicator { +class ScrollViewBar : public ScrollViewIndicator { +public: + ScrollViewBar(); + void update(KDCoordinate totalContentLength, KDCoordinate contentOffset, KDCoordinate visibleContentLength); + bool visible() const { return 0 < m_offset || m_visibleLength < 1; } +protected: + constexpr static KDCoordinate k_indicatorThickness = 4; + float m_offset; + float m_visibleLength; + KDColor m_trackColor; +}; + +class ScrollViewHorizontalBar : public ScrollViewBar { public: void drawRect(KDContext * ctx, KDRect rect) const override; private: KDCoordinate totalLength() const { return m_frame.width() - 2*m_margin; } }; -class ScrollViewVerticalIndicator : public ScrollViewIndicator { +class ScrollViewVerticalBar : public ScrollViewBar { public: void drawRect(KDContext * ctx, KDRect rect) const override; private: diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index 0421c2135..5a70f135d 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -146,53 +146,53 @@ KDCoordinate ScrollView::maxContentHeightDisplayableWithoutScrolling() { } ScrollView::Decorator::Decorator() : - m_verticalScrollIndicator(), - m_horizontalScrollIndicator(), + m_verticalBar(), + m_horizontalBar(), m_indicatorThickness(20) { } int ScrollView::Decorator::numberOfIndicators() { - return m_verticalScrollIndicator.visible() + m_horizontalScrollIndicator.visible(); + return m_verticalBar.visible() + m_horizontalBar.visible(); } View * ScrollView::Decorator::indicatorAtIndex(int index) { switch (index) { case 1: - if (m_horizontalScrollIndicator.visible()) { - return &m_horizontalScrollIndicator; + if (m_horizontalBar.visible()) { + return &m_horizontalBar; } else { - return &m_verticalScrollIndicator; + return &m_verticalBar; } case 2: - return &m_verticalScrollIndicator; + return &m_verticalBar; } return nullptr; } void ScrollView::Decorator::layoutIndicators(KDSize content, KDPoint offset, KDSize frame) { - m_horizontalScrollIndicator.update( + m_horizontalBar.update( content.width(), offset.x(), frame.width() ); - m_verticalScrollIndicator.update( + m_verticalBar.update( content.height(), offset.y(), frame.height() ); /* If the two indicators are visible, we leave an empty rectangle in the right * bottom corner. Otherwise, the only indicator uses all the height/width. */ - if (m_verticalScrollIndicator.visible()) { - m_verticalScrollIndicator.setFrame(KDRect( + if (m_verticalBar.visible()) { + m_verticalBar.setFrame(KDRect( frame.width() - m_indicatorThickness, 0, - m_indicatorThickness, frame.height() - m_horizontalScrollIndicator.visible() * m_indicatorThickness + m_indicatorThickness, frame.height() - m_horizontalBar.visible() * m_indicatorThickness )); } - if (m_horizontalScrollIndicator.visible()) { - m_horizontalScrollIndicator.setFrame(KDRect( + if (m_horizontalBar.visible()) { + m_horizontalBar.setFrame(KDRect( 0, frame.height() - m_indicatorThickness, - frame.width() - m_verticalScrollIndicator.visible() * m_indicatorThickness, m_indicatorThickness + frame.width() - m_verticalBar.visible() * m_indicatorThickness, m_indicatorThickness )); } } diff --git a/escher/src/scroll_view_indicator.cpp b/escher/src/scroll_view_indicator.cpp index 808f40719..c8c46acb7 100644 --- a/escher/src/scroll_view_indicator.cpp +++ b/escher/src/scroll_view_indicator.cpp @@ -6,49 +6,20 @@ extern "C" { ScrollViewIndicator::ScrollViewIndicator() : View(), - m_offset(0), - m_visibleLength(0), - m_indicatorColor(Palette::GreyDark), - m_backgroundColor(Palette::GreyMiddle), + m_color(Palette::GreyDark), m_margin(14) { } -void ScrollViewHorizontalIndicator::drawRect(KDContext * ctx, KDRect rect) const { - ctx->fillRect( - KDRect( - m_margin, (m_frame.height() - k_indicatorThickness)/2, - totalLength(), k_indicatorThickness - ), - m_backgroundColor - ); - ctx->fillRect( - KDRect( - m_margin+m_offset*totalLength(), (m_frame.height() - k_indicatorThickness)/2, - m_visibleLength*totalLength(), k_indicatorThickness - ), - m_indicatorColor - ); +ScrollViewBar::ScrollViewBar() : + ScrollViewIndicator(), + m_offset(0), + m_visibleLength(0), + m_trackColor(Palette::GreyMiddle) +{ } -void ScrollViewVerticalIndicator::drawRect(KDContext * ctx, KDRect rect) const { - ctx->fillRect( - KDRect( - (m_frame.width() - k_indicatorThickness)/2, m_margin, - k_indicatorThickness, totalLength() - ), - m_backgroundColor - ); - ctx->fillRect( - KDRect( - (m_frame.width() - k_indicatorThickness)/2, m_margin+m_offset*totalLength(), - k_indicatorThickness, m_visibleLength*totalLength() - ), - m_indicatorColor - ); -} - -void ScrollViewIndicator::update(KDCoordinate totalContentLength, KDCoordinate contentOffset, KDCoordinate visibleContentLength) { +void ScrollViewBar::update(KDCoordinate totalContentLength, KDCoordinate contentOffset, KDCoordinate visibleContentLength) { float offset = contentOffset; float visibleLength = visibleContentLength; offset = offset / totalContentLength; @@ -60,6 +31,40 @@ void ScrollViewIndicator::update(KDCoordinate totalContentLength, KDCoordinate c } } +void ScrollViewHorizontalBar::drawRect(KDContext * ctx, KDRect rect) const { + ctx->fillRect( + KDRect( + m_margin, (m_frame.height() - k_indicatorThickness)/2, + totalLength(), k_indicatorThickness + ), + m_trackColor + ); + ctx->fillRect( + KDRect( + m_margin+m_offset*totalLength(), (m_frame.height() - k_indicatorThickness)/2, + m_visibleLength*totalLength(), k_indicatorThickness + ), + m_color + ); +} + +void ScrollViewVerticalBar::drawRect(KDContext * ctx, KDRect rect) const { + ctx->fillRect( + KDRect( + (m_frame.width() - k_indicatorThickness)/2, m_margin, + k_indicatorThickness, totalLength() + ), + m_trackColor + ); + ctx->fillRect( + KDRect( + (m_frame.width() - k_indicatorThickness)/2, m_margin+m_offset*totalLength(), + k_indicatorThickness, m_visibleLength*totalLength() + ), + m_color + ); +} + #if ESCHER_VIEW_LOGGING const char * ScrollViewIndicator::className() const { return "ScrollViewIndicator"; From 5b78d65b6d8710bf4637d7e4ea3f0f5bc1b25ac9 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Wed, 23 Jan 2019 18:06:01 +0100 Subject: [PATCH 304/373] [escher/scroll_view] Simplify subviews management --- escher/include/escher/scroll_view.h | 7 +++++-- escher/src/scroll_view.cpp | 18 ------------------ escher/src/scroll_view_indicator.cpp | 6 ++++++ 3 files changed, 11 insertions(+), 20 deletions(-) diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index dcd2096e8..2a5b2c1aa 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -28,8 +28,11 @@ public: class Decorator { public: Decorator(); - int numberOfIndicators(); - View * indicatorAtIndex(int index); + int numberOfIndicators() { return 2; } + View * indicatorAtIndex(int index) { + assert(0 < index && index <= numberOfIndicators()); + return &m_verticalBar + (index-1); + } void layoutIndicators(KDSize content, KDPoint offset, KDSize frame); ScrollViewVerticalBar * verticalBar() { return &m_verticalBar; } ScrollViewHorizontalBar * horizontalBar() { return &m_horizontalBar; } diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index 5a70f135d..2e6d40319 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -152,24 +152,6 @@ ScrollView::Decorator::Decorator() : { } -int ScrollView::Decorator::numberOfIndicators() { - return m_verticalBar.visible() + m_horizontalBar.visible(); -} - -View * ScrollView::Decorator::indicatorAtIndex(int index) { - switch (index) { - case 1: - if (m_horizontalBar.visible()) { - return &m_horizontalBar; - } else { - return &m_verticalBar; - } - case 2: - return &m_verticalBar; - } - return nullptr; -} - void ScrollView::Decorator::layoutIndicators(KDSize content, KDPoint offset, KDSize frame) { m_horizontalBar.update( content.width(), diff --git a/escher/src/scroll_view_indicator.cpp b/escher/src/scroll_view_indicator.cpp index c8c46acb7..4374e5e6f 100644 --- a/escher/src/scroll_view_indicator.cpp +++ b/escher/src/scroll_view_indicator.cpp @@ -32,6 +32,9 @@ void ScrollViewBar::update(KDCoordinate totalContentLength, KDCoordinate content } void ScrollViewHorizontalBar::drawRect(KDContext * ctx, KDRect rect) const { + if (!visible()) { + return; + } ctx->fillRect( KDRect( m_margin, (m_frame.height() - k_indicatorThickness)/2, @@ -49,6 +52,9 @@ void ScrollViewHorizontalBar::drawRect(KDContext * ctx, KDRect rect) const { } void ScrollViewVerticalBar::drawRect(KDContext * ctx, KDRect rect) const { + if (!visible()) { + return; + } ctx->fillRect( KDRect( (m_frame.width() - k_indicatorThickness)/2, m_margin, From 81f80ef6022a9a0b64a6a94dcc942a3b68c61194 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Thu, 24 Jan 2019 11:39:16 +0100 Subject: [PATCH 305/373] [escher/scroll_view] Simplify layoutIndicators Mark indicators' frame as dirty when necessary, indirectly by setFrame to empty. --- escher/include/escher/scroll_view_indicator.h | 4 ++-- escher/src/scroll_view.cpp | 24 ++++++++----------- escher/src/scroll_view_indicator.cpp | 3 ++- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/escher/include/escher/scroll_view_indicator.h b/escher/include/escher/scroll_view_indicator.h index e75ec52f2..31641cab1 100644 --- a/escher/include/escher/scroll_view_indicator.h +++ b/escher/include/escher/scroll_view_indicator.h @@ -20,10 +20,10 @@ protected: class ScrollViewBar : public ScrollViewIndicator { public: ScrollViewBar(); - void update(KDCoordinate totalContentLength, KDCoordinate contentOffset, KDCoordinate visibleContentLength); - bool visible() const { return 0 < m_offset || m_visibleLength < 1; } + bool update(KDCoordinate totalContentLength, KDCoordinate contentOffset, KDCoordinate visibleContentLength); protected: constexpr static KDCoordinate k_indicatorThickness = 4; + bool visible() const { return 0 < m_offset || m_visibleLength < 1; } float m_offset; float m_visibleLength; KDColor m_trackColor; diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index 2e6d40319..c4cbd15cc 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -153,30 +153,26 @@ ScrollView::Decorator::Decorator() : } void ScrollView::Decorator::layoutIndicators(KDSize content, KDPoint offset, KDSize frame) { - m_horizontalBar.update( + KDCoordinate hBarFrameBreadth = m_indicatorThickness * m_horizontalBar.update( content.width(), offset.x(), frame.width() ); - m_verticalBar.update( + KDCoordinate vBarFrameBreadth = m_indicatorThickness * m_verticalBar.update( content.height(), offset.y(), frame.height() ); /* If the two indicators are visible, we leave an empty rectangle in the right * bottom corner. Otherwise, the only indicator uses all the height/width. */ - if (m_verticalBar.visible()) { - m_verticalBar.setFrame(KDRect( - frame.width() - m_indicatorThickness, 0, - m_indicatorThickness, frame.height() - m_horizontalBar.visible() * m_indicatorThickness - )); - } - if (m_horizontalBar.visible()) { - m_horizontalBar.setFrame(KDRect( - 0, frame.height() - m_indicatorThickness, - frame.width() - m_verticalBar.visible() * m_indicatorThickness, m_indicatorThickness - )); - } + m_verticalBar.setFrame(KDRect( + frame.width() - vBarFrameBreadth, 0, + vBarFrameBreadth, frame.height() - hBarFrameBreadth + )); + m_horizontalBar.setFrame(KDRect( + 0, frame.height() - hBarFrameBreadth, + frame.width() - vBarFrameBreadth, hBarFrameBreadth + )); } #if ESCHER_VIEW_LOGGING diff --git a/escher/src/scroll_view_indicator.cpp b/escher/src/scroll_view_indicator.cpp index 4374e5e6f..56b7e2f1c 100644 --- a/escher/src/scroll_view_indicator.cpp +++ b/escher/src/scroll_view_indicator.cpp @@ -19,7 +19,7 @@ ScrollViewBar::ScrollViewBar() : { } -void ScrollViewBar::update(KDCoordinate totalContentLength, KDCoordinate contentOffset, KDCoordinate visibleContentLength) { +bool ScrollViewBar::update(KDCoordinate totalContentLength, KDCoordinate contentOffset, KDCoordinate visibleContentLength) { float offset = contentOffset; float visibleLength = visibleContentLength; offset = offset / totalContentLength; @@ -29,6 +29,7 @@ void ScrollViewBar::update(KDCoordinate totalContentLength, KDCoordinate content m_visibleLength = visibleLength; markRectAsDirty(bounds()); } + return visible(); } void ScrollViewHorizontalBar::drawRect(KDContext * ctx, KDRect rect) const { From 1e958717fb5bfcde1001c685a37549c8a802c40d Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Thu, 24 Jan 2019 11:47:53 +0100 Subject: [PATCH 306/373] [escher/scroll_view] Rename m_indicatorThickness to m_barsFrameBreadth --- apps/home/controller.cpp | 2 +- apps/home/controller.h | 2 +- apps/shared/storage_values_controller.cpp | 2 +- apps/shared/values_controller.cpp | 2 +- escher/include/escher/scroll_view.h | 4 ++-- escher/src/scroll_view.cpp | 6 +++--- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/apps/home/controller.cpp b/apps/home/controller.cpp index 0873aadd8..a68183025 100644 --- a/apps/home/controller.cpp +++ b/apps/home/controller.cpp @@ -12,7 +12,7 @@ Controller::ContentView::ContentView(Controller * controller, SelectableTableVie m_selectableTableView.setVerticalCellOverlap(0); m_selectableTableView.setMargins(0, k_sideMargin, k_bottomMargin, k_sideMargin); m_selectableTableView.setColorsBackground(false); - m_selectableTableView.decorator()->setIndicatorThickness(k_indicatorThickness); + m_selectableTableView.decorator()->setBarsFrameBreadth(k_scrollBarsFrameBreadth); m_selectableTableView.decorator()->verticalBar()->setMargin(k_indicatorMargin); } diff --git a/apps/home/controller.h b/apps/home/controller.h index 183dbda07..679651b1a 100644 --- a/apps/home/controller.h +++ b/apps/home/controller.h @@ -43,7 +43,7 @@ private: AppsContainer * m_container; static constexpr KDCoordinate k_sideMargin = 4; static constexpr KDCoordinate k_bottomMargin = 14; - static constexpr KDCoordinate k_indicatorThickness = 15; + static constexpr KDCoordinate k_scrollBarsFrameBreadth = 15; static constexpr KDCoordinate k_indicatorMargin = 61; static constexpr int k_numberOfColumns = 3; static constexpr int k_maxNumberOfCells = 16; diff --git a/apps/shared/storage_values_controller.cpp b/apps/shared/storage_values_controller.cpp index d72e856c1..e9b12b3dc 100644 --- a/apps/shared/storage_values_controller.cpp +++ b/apps/shared/storage_values_controller.cpp @@ -32,7 +32,7 @@ StorageValuesController::StorageValuesController(Responder * parentResponder, In m_selectableTableView.setBottomMargin(k_bottomMargin); m_selectableTableView.setLeftMargin(k_leftMargin); m_selectableTableView.setBackgroundColor(Palette::WallScreenDark); - m_selectableTableView.decorator()->setIndicatorThickness(13); + m_selectableTableView.decorator()->setBarsFrameBreadth(13); m_abscissaTitleCell.setMessageFont(k_font); for (int i = 0; i < k_maxNumberOfAbscissaCells; i++) { m_abscissaCells[i].setParentResponder(&m_selectableTableView); diff --git a/apps/shared/values_controller.cpp b/apps/shared/values_controller.cpp index 3c7f49ab2..a6d893ae5 100644 --- a/apps/shared/values_controller.cpp +++ b/apps/shared/values_controller.cpp @@ -32,7 +32,7 @@ ValuesController::ValuesController(Responder * parentResponder, InputEventHandle m_selectableTableView.setBottomMargin(k_bottomMargin); m_selectableTableView.setLeftMargin(k_leftMargin); m_selectableTableView.setBackgroundColor(Palette::WallScreenDark); - m_selectableTableView.decorator()->setIndicatorThickness(13); + m_selectableTableView.decorator()->setBarsFrameBreadth(13); m_abscissaTitleCell.setMessageFont(KDFont::SmallFont); for (int i = 0; i < k_maxNumberOfAbscissaCells; i++) { m_abscissaCells[i].setParentResponder(&m_selectableTableView); diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index 2a5b2c1aa..d47408f71 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -36,11 +36,11 @@ public: void layoutIndicators(KDSize content, KDPoint offset, KDSize frame); ScrollViewVerticalBar * verticalBar() { return &m_verticalBar; } ScrollViewHorizontalBar * horizontalBar() { return &m_horizontalBar; } - void setIndicatorThickness(KDCoordinate t) { m_indicatorThickness = t; } + void setBarsFrameBreadth(KDCoordinate t) { m_barsFrameBreadth = t; } private: ScrollViewVerticalBar m_verticalBar; ScrollViewHorizontalBar m_horizontalBar; - KDCoordinate m_indicatorThickness; + KDCoordinate m_barsFrameBreadth; }; Decorator * decorator() { return &m_decorator; } diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index c4cbd15cc..caa271a3d 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -148,17 +148,17 @@ KDCoordinate ScrollView::maxContentHeightDisplayableWithoutScrolling() { ScrollView::Decorator::Decorator() : m_verticalBar(), m_horizontalBar(), - m_indicatorThickness(20) + m_barsFrameBreadth(20) { } void ScrollView::Decorator::layoutIndicators(KDSize content, KDPoint offset, KDSize frame) { - KDCoordinate hBarFrameBreadth = m_indicatorThickness * m_horizontalBar.update( + KDCoordinate hBarFrameBreadth = m_barsFrameBreadth * m_horizontalBar.update( content.width(), offset.x(), frame.width() ); - KDCoordinate vBarFrameBreadth = m_indicatorThickness * m_verticalBar.update( + KDCoordinate vBarFrameBreadth = m_barsFrameBreadth * m_verticalBar.update( content.height(), offset.y(), frame.height() From 1beb8ca98fbb447c97e9015a75e096200d9cec78 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Thu, 24 Jan 2019 15:52:07 +0100 Subject: [PATCH 307/373] [escher/scroll_view] Add arrow indicators --- escher/include/escher/scroll_view.h | 16 ++++++++++ escher/include/escher/scroll_view_indicator.h | 17 ++++++++++ escher/src/scroll_view.cpp | 32 +++++++++++++++++++ escher/src/scroll_view_indicator.cpp | 24 ++++++++++++++ 4 files changed, 89 insertions(+) diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index d47408f71..611a87311 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -43,6 +43,22 @@ public: KDCoordinate m_barsFrameBreadth; }; + class DecoratorV2 { + public: + DecoratorV2(); + int numberOfIndicators() { return 4; } + View * indicatorAtIndex(int index) { + assert(0 < index && index <= numberOfIndicators()); + return &m_topArrow + (index-1); + } + void layoutIndicators(KDSize content, KDPoint offset, KDSize frame); + private: + ScrollViewArrow m_topArrow; + ScrollViewArrow m_rightArrow; + ScrollViewArrow m_bottomArrow; + ScrollViewArrow m_leftArrow; + }; + Decorator * decorator() { return &m_decorator; } void setShowsIndicators(bool s) { m_showsIndicators = s; } bool showsIndicators() const { return m_showsIndicators; } diff --git a/escher/include/escher/scroll_view_indicator.h b/escher/include/escher/scroll_view_indicator.h index 31641cab1..6744d6974 100644 --- a/escher/include/escher/scroll_view_indicator.h +++ b/escher/include/escher/scroll_view_indicator.h @@ -43,4 +43,21 @@ private: KDCoordinate totalLength() const { return m_frame.height() - 2*m_margin; } }; +class ScrollViewArrow : public ScrollViewIndicator { +public: + enum Side : char { //FIXME + Top = 't', + Right = '>', + Bottom = 'b', + Left = '<' + }; + ScrollViewArrow(Side side); + bool update(bool visible); + void drawRect(KDContext * ctx, KDRect rect) const override; +private: + bool m_visible; + const char m_arrow; + KDColor m_backgroundColor; +}; + #endif diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index caa271a3d..806138462 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -175,6 +175,38 @@ void ScrollView::Decorator::layoutIndicators(KDSize content, KDPoint offset, KDS )); } +ScrollView::DecoratorV2::DecoratorV2() : + m_topArrow(ScrollViewArrow::Side::Top), + m_rightArrow(ScrollViewArrow::Side::Right), + m_bottomArrow(ScrollViewArrow::Side::Bottom), + m_leftArrow(ScrollViewArrow::Side::Left) +{ +} + +void ScrollView::DecoratorV2::layoutIndicators(KDSize content, KDPoint offset, KDSize frame) { + KDSize arrowSize = KDFont::LargeFont->glyphSize(); + KDCoordinate topArrowFrameBreadth = arrowSize.height() * m_topArrow.update(0 < offset.y()); + KDCoordinate rightArrowFrameBreadth = arrowSize.width() * m_rightArrow.update(offset.x() + frame.width() < content.width()); + KDCoordinate bottomArrowFrameBreadth = arrowSize.height() * m_bottomArrow.update(offset.y() + frame.height() < content.height()); + KDCoordinate leftArrowFrameBreadth = arrowSize.width() * m_leftArrow.update(0 < offset.x()); + m_topArrow.setFrame(KDRect( + 0, 0, + frame.width(), topArrowFrameBreadth + )); + m_rightArrow.setFrame(KDRect( + frame.width() - rightArrowFrameBreadth, 0, + rightArrowFrameBreadth, frame.height() + )); + m_bottomArrow.setFrame(KDRect( + 0, frame.height() - bottomArrowFrameBreadth, + frame.width(), bottomArrowFrameBreadth + )); + m_leftArrow.setFrame(KDRect( + 0, 0, + leftArrowFrameBreadth, frame.height() + )); +} + #if ESCHER_VIEW_LOGGING const char * ScrollView::className() const { return "ScrollView"; diff --git a/escher/src/scroll_view_indicator.cpp b/escher/src/scroll_view_indicator.cpp index 56b7e2f1c..6786566ca 100644 --- a/escher/src/scroll_view_indicator.cpp +++ b/escher/src/scroll_view_indicator.cpp @@ -72,6 +72,30 @@ void ScrollViewVerticalBar::drawRect(KDContext * ctx, KDRect rect) const { ); } +ScrollViewArrow::ScrollViewArrow(Side side) : + m_visible(false), + m_arrow(side) +{ +} + +bool ScrollViewArrow::update(bool visible) { + if (m_visible != visible) { + markRectAsDirty(bounds()); + } + m_visible = visible; + return visible; +} + +void ScrollViewArrow::drawRect(KDContext * ctx, KDRect rect) const { + ctx->fillRect(bounds(), m_backgroundColor); + KDSize arrowSize = KDFont::LargeFont->glyphSize(); + const KDPoint arrowAlign = KDPoint( + (m_arrow == Top || m_arrow == Bottom) * (m_frame.width() - arrowSize.width()) / 2, + (m_arrow == Left || m_arrow == Right) * (m_frame.height() - arrowSize.height()) / 2 + ); + ctx->drawString(&m_arrow, arrowAlign, KDFont::LargeFont, m_color, m_backgroundColor, m_visible); +} + #if ESCHER_VIEW_LOGGING const char * ScrollViewIndicator::className() const { return "ScrollViewIndicator"; From eb17334050acd1c53d2338970518cb7fe94f9fbd Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Thu, 24 Jan 2019 16:40:51 +0100 Subject: [PATCH 308/373] [escher/scroll_view] New Arrow/BarDecorator inherit from Decorator --- apps/home/controller.cpp | 4 ++-- apps/shared/storage_values_controller.cpp | 2 +- apps/shared/values_controller.cpp | 2 +- escher/include/escher/scroll_view.h | 27 ++++++++++++++--------- escher/src/scroll_view.cpp | 8 +++---- 5 files changed, 25 insertions(+), 18 deletions(-) diff --git a/apps/home/controller.cpp b/apps/home/controller.cpp index a68183025..a4f61b7c1 100644 --- a/apps/home/controller.cpp +++ b/apps/home/controller.cpp @@ -12,8 +12,8 @@ Controller::ContentView::ContentView(Controller * controller, SelectableTableVie m_selectableTableView.setVerticalCellOverlap(0); m_selectableTableView.setMargins(0, k_sideMargin, k_bottomMargin, k_sideMargin); m_selectableTableView.setColorsBackground(false); - m_selectableTableView.decorator()->setBarsFrameBreadth(k_scrollBarsFrameBreadth); - m_selectableTableView.decorator()->verticalBar()->setMargin(k_indicatorMargin); + static_cast(m_selectableTableView.decorator())->setBarsFrameBreadth(k_scrollBarsFrameBreadth); + static_cast(m_selectableTableView.decorator())->verticalBar()->setMargin(k_indicatorMargin); } SelectableTableView * Controller::ContentView::selectableTableView() { diff --git a/apps/shared/storage_values_controller.cpp b/apps/shared/storage_values_controller.cpp index e9b12b3dc..cadc74dd4 100644 --- a/apps/shared/storage_values_controller.cpp +++ b/apps/shared/storage_values_controller.cpp @@ -32,7 +32,7 @@ StorageValuesController::StorageValuesController(Responder * parentResponder, In m_selectableTableView.setBottomMargin(k_bottomMargin); m_selectableTableView.setLeftMargin(k_leftMargin); m_selectableTableView.setBackgroundColor(Palette::WallScreenDark); - m_selectableTableView.decorator()->setBarsFrameBreadth(13); + static_cast(m_selectableTableView.decorator())->setBarsFrameBreadth(13); m_abscissaTitleCell.setMessageFont(k_font); for (int i = 0; i < k_maxNumberOfAbscissaCells; i++) { m_abscissaCells[i].setParentResponder(&m_selectableTableView); diff --git a/apps/shared/values_controller.cpp b/apps/shared/values_controller.cpp index a6d893ae5..d19e77dd6 100644 --- a/apps/shared/values_controller.cpp +++ b/apps/shared/values_controller.cpp @@ -32,7 +32,7 @@ ValuesController::ValuesController(Responder * parentResponder, InputEventHandle m_selectableTableView.setBottomMargin(k_bottomMargin); m_selectableTableView.setLeftMargin(k_leftMargin); m_selectableTableView.setBackgroundColor(Palette::WallScreenDark); - m_selectableTableView.decorator()->setBarsFrameBreadth(13); + static_cast(m_selectableTableView.decorator())->setBarsFrameBreadth(13); m_abscissaTitleCell.setMessageFont(KDFont::SmallFont); for (int i = 0; i < k_maxNumberOfAbscissaCells; i++) { m_abscissaCells[i].setParentResponder(&m_selectableTableView); diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index 611a87311..15e0547cf 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -27,13 +27,20 @@ public: class Decorator { public: - Decorator(); - int numberOfIndicators() { return 2; } - View * indicatorAtIndex(int index) { + virtual int numberOfIndicators() { return 0; } + virtual View * indicatorAtIndex(int index) { assert(false); return nullptr; } + virtual void layoutIndicators(KDSize content, KDPoint offset, KDSize frame) {} + }; + + class BarDecorator : public Decorator { + public: + BarDecorator(); + int numberOfIndicators() override { return 2; } + View * indicatorAtIndex(int index) override { assert(0 < index && index <= numberOfIndicators()); return &m_verticalBar + (index-1); } - void layoutIndicators(KDSize content, KDPoint offset, KDSize frame); + void layoutIndicators(KDSize content, KDPoint offset, KDSize frame) override; ScrollViewVerticalBar * verticalBar() { return &m_verticalBar; } ScrollViewHorizontalBar * horizontalBar() { return &m_horizontalBar; } void setBarsFrameBreadth(KDCoordinate t) { m_barsFrameBreadth = t; } @@ -43,15 +50,15 @@ public: KDCoordinate m_barsFrameBreadth; }; - class DecoratorV2 { + class ArrowDecorator : public Decorator { public: - DecoratorV2(); - int numberOfIndicators() { return 4; } - View * indicatorAtIndex(int index) { + ArrowDecorator(); + int numberOfIndicators() override { return 4; } + View * indicatorAtIndex(int index) override { assert(0 < index && index <= numberOfIndicators()); return &m_topArrow + (index-1); } - void layoutIndicators(KDSize content, KDPoint offset, KDSize frame); + void layoutIndicators(KDSize content, KDPoint offset, KDSize frame) override; private: ScrollViewArrow m_topArrow; ScrollViewArrow m_rightArrow; @@ -93,7 +100,7 @@ private: KDCoordinate m_bottomMargin; KDCoordinate m_leftMargin; - Decorator m_decorator; + BarDecorator m_decorator; bool m_showsIndicators; bool m_colorsBackground; KDColor m_backgroundColor; diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index 806138462..94d8d9e25 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -145,14 +145,14 @@ KDCoordinate ScrollView::maxContentHeightDisplayableWithoutScrolling() { return m_frame.height() - m_topMargin - m_bottomMargin; } -ScrollView::Decorator::Decorator() : +ScrollView::BarDecorator::BarDecorator() : m_verticalBar(), m_horizontalBar(), m_barsFrameBreadth(20) { } -void ScrollView::Decorator::layoutIndicators(KDSize content, KDPoint offset, KDSize frame) { +void ScrollView::BarDecorator::layoutIndicators(KDSize content, KDPoint offset, KDSize frame) { KDCoordinate hBarFrameBreadth = m_barsFrameBreadth * m_horizontalBar.update( content.width(), offset.x(), @@ -175,7 +175,7 @@ void ScrollView::Decorator::layoutIndicators(KDSize content, KDPoint offset, KDS )); } -ScrollView::DecoratorV2::DecoratorV2() : +ScrollView::ArrowDecorator::ArrowDecorator() : m_topArrow(ScrollViewArrow::Side::Top), m_rightArrow(ScrollViewArrow::Side::Right), m_bottomArrow(ScrollViewArrow::Side::Bottom), @@ -183,7 +183,7 @@ ScrollView::DecoratorV2::DecoratorV2() : { } -void ScrollView::DecoratorV2::layoutIndicators(KDSize content, KDPoint offset, KDSize frame) { +void ScrollView::ArrowDecorator::layoutIndicators(KDSize content, KDPoint offset, KDSize frame) { KDSize arrowSize = KDFont::LargeFont->glyphSize(); KDCoordinate topArrowFrameBreadth = arrowSize.height() * m_topArrow.update(0 < offset.y()); KDCoordinate rightArrowFrameBreadth = arrowSize.width() * m_rightArrow.update(offset.x() + frame.width() < content.width()); From 6f9493db5de9fdc5f392cca50aa93ea5c6a4cfc9 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Thu, 24 Jan 2019 16:44:33 +0100 Subject: [PATCH 309/373] [escher/scroll_view] Use virtuality of Decorator methods --- escher/src/scroll_view.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index 94d8d9e25..8070cff9b 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -32,7 +32,7 @@ void ScrollView::setCommonMargins() { int ScrollView::numberOfSubviews() const { int result = 1; if (m_showsIndicators) { - result += const_cast(this)->m_decorator.numberOfIndicators(); + result += const_cast(this)->decorator()->numberOfIndicators(); } return result; } @@ -42,7 +42,7 @@ View * ScrollView::subviewAtIndex(int index) { return m_contentView; } if (m_showsIndicators) { - return m_decorator.indicatorAtIndex(index); + return decorator()->indicatorAtIndex(index); } return nullptr; } @@ -123,7 +123,7 @@ void ScrollView::layoutSubviews() { m_contentView->bounds().width() + m_leftMargin + m_rightMargin, m_contentView->bounds().height() + m_topMargin + m_bottomMargin ); - m_decorator.layoutIndicators(content, contentOffset(), m_frame.size()); + decorator()->layoutIndicators(content, contentOffset(), m_frame.size()); } } From 09e08b43a01844ca5211855f2a007026b1fe9fed Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Thu, 24 Jan 2019 18:22:08 +0100 Subject: [PATCH 310/373] [escher/scroll_view] Define enum class Decorator::Type --- escher/include/escher/scroll_view.h | 13 +++++++++++-- escher/src/scroll_view.cpp | 15 +++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index 15e0547cf..42ed46697 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -27,6 +27,11 @@ public: class Decorator { public: + enum class Type { + None, + Bars, + Arrows + }; virtual int numberOfIndicators() { return 0; } virtual View * indicatorAtIndex(int index) { assert(false); return nullptr; } virtual void layoutIndicators(KDSize content, KDPoint offset, KDSize frame) {} @@ -66,7 +71,8 @@ public: ScrollViewArrow m_leftArrow; }; - Decorator * decorator() { return &m_decorator; } + Decorator * decorator(); + void setDecoratorType(Decorator::Type t) { m_decoratorType = t; } void setShowsIndicators(bool s) { m_showsIndicators = s; } bool showsIndicators() const { return m_showsIndicators; } void setColorsBackground(bool c) { m_colorsBackground = c; } @@ -100,7 +106,10 @@ private: KDCoordinate m_bottomMargin; KDCoordinate m_leftMargin; - BarDecorator m_decorator; + Decorator::Type m_decoratorType; + Decorator m_decorator; + BarDecorator m_barDecorator; + ArrowDecorator m_arrowDecorator; bool m_showsIndicators; bool m_colorsBackground; KDColor m_backgroundColor; diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index 8070cff9b..70185478d 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -14,7 +14,10 @@ ScrollView::ScrollView(View * contentView, ScrollViewDataSource * dataSource) : m_rightMargin(0), m_bottomMargin(0), m_leftMargin(0), + m_decoratorType(Decorator::Type::Bars), m_decorator(), + m_barDecorator(), + m_arrowDecorator(), m_showsIndicators(true), m_colorsBackground(true), m_backgroundColor(Palette::WallScreen) @@ -29,6 +32,18 @@ void ScrollView::setCommonMargins() { setLeftMargin(Metric::CommonLeftMargin); } +ScrollView::Decorator * ScrollView::decorator() { + switch (m_decoratorType) { + case Decorator::Type::Bars: + return &m_barDecorator; + case Decorator::Type::Arrows: + return &m_arrowDecorator; + default: + assert(m_decoratorType == Decorator::Type::None); + return &m_decorator; + } +} + int ScrollView::numberOfSubviews() const { int result = 1; if (m_showsIndicators) { From faae55eb5189fe0e6be4a3b395386449cad85536 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Fri, 25 Jan 2019 10:37:02 +0100 Subject: [PATCH 311/373] [escher/scroll_view] Replace setShowsIndicators by setDecoratorType --- apps/calculation/selectable_table_view.cpp | 2 +- apps/code/menu_controller.cpp | 2 +- apps/probability/calculation_controller.cpp | 2 +- .../calculation_type_controller.cpp | 2 +- .../list/type_parameter_controller.cpp | 2 +- apps/solver/equation_list_view.cpp | 4 +-- .../equation_models_parameter_controller.cpp | 2 +- escher/include/escher/scroll_view.h | 7 ++--- escher/src/nested_menu_controller.cpp | 2 +- escher/src/scroll_view.cpp | 31 +++---------------- escher/src/scrollable_view.cpp | 2 +- 11 files changed, 17 insertions(+), 41 deletions(-) diff --git a/apps/calculation/selectable_table_view.cpp b/apps/calculation/selectable_table_view.cpp index 958ac8a15..c00bed4b1 100644 --- a/apps/calculation/selectable_table_view.cpp +++ b/apps/calculation/selectable_table_view.cpp @@ -8,7 +8,7 @@ CalculationSelectableTableView::CalculationSelectableTableView(Responder * paren { setVerticalCellOverlap(0); setMargins(0); - setShowsIndicators(false); + setDecoratorType(ScrollView::Decorator::Type::None); } void CalculationSelectableTableView::scrollToCell(int i, int j) { diff --git a/apps/code/menu_controller.cpp b/apps/code/menu_controller.cpp index e7e04a8d4..940e145fe 100644 --- a/apps/code/menu_controller.cpp +++ b/apps/code/menu_controller.cpp @@ -26,7 +26,7 @@ MenuController::MenuController(Responder * parentResponder, App * pythonDelegate m_shouldDisplayAddScriptRow(true) { m_selectableTableView.setMargins(0); - m_selectableTableView.setShowsIndicators(false); + m_selectableTableView.setDecoratorType(ScrollView::Decorator::Type::None); m_addNewScriptCell.setMessage(I18n::Message::AddScript); for (int i = 0; i < k_maxNumberOfDisplayableScriptCells; i++) { m_scriptCells[i].setParentResponder(&m_selectableTableView); diff --git a/apps/probability/calculation_controller.cpp b/apps/probability/calculation_controller.cpp index ea4311966..12d3f3de4 100644 --- a/apps/probability/calculation_controller.cpp +++ b/apps/probability/calculation_controller.cpp @@ -66,7 +66,7 @@ CalculationController::CalculationController(Responder * parentResponder, InputE assert(calculation != nullptr); m_selectableTableView.setMargins(k_tableMargin); m_selectableTableView.setVerticalCellOverlap(0); - m_selectableTableView.setShowsIndicators(false); + m_selectableTableView.setDecoratorType(ScrollView::Decorator::Type::None); m_selectableTableView.setBackgroundColor(KDColorWhite); diff --git a/apps/probability/calculation_type_controller.cpp b/apps/probability/calculation_type_controller.cpp index a0b6980b0..0f16323f4 100644 --- a/apps/probability/calculation_type_controller.cpp +++ b/apps/probability/calculation_type_controller.cpp @@ -22,7 +22,7 @@ CalculationTypeController::CalculationTypeController(Responder * parentResponder assert(m_calculation != nullptr); m_selectableTableView.setMargins(0); m_selectableTableView.setVerticalCellOverlap(0); - m_selectableTableView.setShowsIndicators(false); + m_selectableTableView.setDecoratorType(ScrollView::Decorator::Type::None); m_selectableTableView.setColorsBackground(false); } diff --git a/apps/sequence/list/type_parameter_controller.cpp b/apps/sequence/list/type_parameter_controller.cpp index c168c7435..5ddcfd003 100644 --- a/apps/sequence/list/type_parameter_controller.cpp +++ b/apps/sequence/list/type_parameter_controller.cpp @@ -23,7 +23,7 @@ TypeParameterController::TypeParameterController(Responder * parentResponder, Se m_listController(list) { m_selectableTableView.setMargins(topMargin, rightMargin, bottomMargin, leftMargin); - m_selectableTableView.setShowsIndicators(false); + m_selectableTableView.setDecoratorType(ScrollView::Decorator::Type::None); } const char * TypeParameterController::title() { diff --git a/apps/solver/equation_list_view.cpp b/apps/solver/equation_list_view.cpp index ae19c0dde..78d2e9e0a 100644 --- a/apps/solver/equation_list_view.cpp +++ b/apps/solver/equation_list_view.cpp @@ -14,10 +14,10 @@ EquationListView::EquationListView(Responder * parentResponder, TableViewDataSou { m_listView.setMargins(0); m_listView.setVerticalCellOverlap(0); - m_listView.setShowsIndicators(false); + m_listView.setDecoratorType(ScrollView::Decorator::Type::None); selectionDataSource->setScrollViewDelegate(this); m_scrollBraceView.setMargins(k_margin, k_margin, k_margin, k_margin); - m_scrollBraceView.setShowsIndicators(false); + m_scrollBraceView.setDecoratorType(ScrollView::Decorator::Type::None); m_scrollBraceView.setBackgroundColor(KDColorWhite); } diff --git a/apps/solver/equation_models_parameter_controller.cpp b/apps/solver/equation_models_parameter_controller.cpp index 0a73cfb1d..33ecf50d1 100644 --- a/apps/solver/equation_models_parameter_controller.cpp +++ b/apps/solver/equation_models_parameter_controller.cpp @@ -20,7 +20,7 @@ EquationModelsParameterController::EquationModelsParameterController(Responder * m_listController(listController) { m_selectableTableView.setMargins(0); - m_selectableTableView.setShowsIndicators(false); + m_selectableTableView.setDecoratorType(ScrollView::Decorator::Type::None); for (int i = 0; i < k_numberOfExpressionCells; i++) { Poincare::Expression e = Expression::Parse(k_models[i+1]); m_layouts[i] = e.createLayout(Poincare::Preferences::PrintFloatMode::Decimal, Constant::ShortNumberOfSignificantDigits); diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index 42ed46697..a460ebe38 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -73,8 +73,6 @@ public: Decorator * decorator(); void setDecoratorType(Decorator::Type t) { m_decoratorType = t; } - void setShowsIndicators(bool s) { m_showsIndicators = s; } - bool showsIndicators() const { return m_showsIndicators; } void setColorsBackground(bool c) { m_colorsBackground = c; } bool colorsBackground() const { return m_colorsBackground; } virtual void setBackgroundColor(KDColor c) { m_backgroundColor = c; } @@ -98,8 +96,8 @@ protected: View * m_contentView; private: ScrollViewDataSource * m_dataSource; - int numberOfSubviews() const override; - View * subviewAtIndex(int index) override; + int numberOfSubviews() const override { return 1 + const_cast(this)->decorator()->numberOfIndicators(); } + View * subviewAtIndex(int index) override { return (index == 0) ? m_contentView : decorator()->indicatorAtIndex(index); } KDCoordinate m_topMargin; KDCoordinate m_rightMargin; @@ -110,7 +108,6 @@ private: Decorator m_decorator; BarDecorator m_barDecorator; ArrowDecorator m_arrowDecorator; - bool m_showsIndicators; bool m_colorsBackground; KDColor m_backgroundColor; }; diff --git a/escher/src/nested_menu_controller.cpp b/escher/src/nested_menu_controller.cpp index 1844e3673..e19708512 100644 --- a/escher/src/nested_menu_controller.cpp +++ b/escher/src/nested_menu_controller.cpp @@ -94,7 +94,7 @@ NestedMenuController::NestedMenuController(Responder * parentResponder, I18n::Me m_sender(nullptr) { m_selectableTableView.setMargins(0); - m_selectableTableView.setShowsIndicators(false); + m_selectableTableView.setDecoratorType(ScrollView::Decorator::Type::None); } bool NestedMenuController::handleEvent(Ion::Events::Event event) { diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index 70185478d..7d7c13824 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -18,7 +18,6 @@ ScrollView::ScrollView(View * contentView, ScrollViewDataSource * dataSource) : m_decorator(), m_barDecorator(), m_arrowDecorator(), - m_showsIndicators(true), m_colorsBackground(true), m_backgroundColor(Palette::WallScreen) { @@ -44,24 +43,6 @@ ScrollView::Decorator * ScrollView::decorator() { } } -int ScrollView::numberOfSubviews() const { - int result = 1; - if (m_showsIndicators) { - result += const_cast(this)->decorator()->numberOfIndicators(); - } - return result; -} - -View * ScrollView::subviewAtIndex(int index) { - if (index == 0) { - return m_contentView; - } - if (m_showsIndicators) { - return decorator()->indicatorAtIndex(index); - } - return nullptr; -} - void ScrollView::drawRect(KDContext * ctx, KDRect rect) const { if (!m_colorsBackground) { return; @@ -133,13 +114,11 @@ void ScrollView::layoutSubviews() { KDPoint absoluteOffset = contentOffset().opposite().translatedBy(KDPoint(m_leftMargin, m_topMargin)); KDRect contentFrame = KDRect(absoluteOffset, m_contentView->bounds().size()); m_contentView->setFrame(contentFrame); - if (m_showsIndicators) { - KDSize content( - m_contentView->bounds().width() + m_leftMargin + m_rightMargin, - m_contentView->bounds().height() + m_topMargin + m_bottomMargin - ); - decorator()->layoutIndicators(content, contentOffset(), m_frame.size()); - } + KDSize content( + m_contentView->bounds().width() + m_leftMargin + m_rightMargin, + m_contentView->bounds().height() + m_topMargin + m_bottomMargin + ); + decorator()->layoutIndicators(content, contentOffset(), m_frame.size()); } KDSize ScrollView::contentSize() { diff --git a/escher/src/scrollable_view.cpp b/escher/src/scrollable_view.cpp index bc9048715..a8a30b9d2 100644 --- a/escher/src/scrollable_view.cpp +++ b/escher/src/scrollable_view.cpp @@ -7,7 +7,7 @@ ScrollableView::ScrollableView(Responder * parentResponder, View * view, ScrollV ScrollView(view, dataSource), m_manualScrollingOffset(KDPointZero) { - setShowsIndicators(false); + setDecoratorType(ScrollView::Decorator::Type::None); setColorsBackground(false); } From 9b0e2ac05958e8d511399b5912f19f5c2223d5f3 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Mon, 28 Jan 2019 11:54:39 +0100 Subject: [PATCH 312/373] [escher/scroll_view] Simplify scrollToContentPoint --- escher/src/scroll_view.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index 7d7c13824..a3fe12419 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -83,15 +83,10 @@ void ScrollView::scrollToContentPoint(KDPoint p, bool allowOverscroll) { } /* Handle cases when the size of the view has decreased. */ - KDCoordinate contentOffsetX = contentOffset().x(); - KDCoordinate contentOffsetY = contentOffset().y(); - if (maxContentHeightDisplayableWithoutScrolling() > contentSize().height()-contentOffsetY) { - contentOffsetY = contentSize().height() > maxContentHeightDisplayableWithoutScrolling() ? contentSize().height()-maxContentHeightDisplayableWithoutScrolling() : 0; - } - if (maxContentWidthDisplayableWithoutScrolling() > contentSize().width()-contentOffsetX) { - contentOffsetX = contentSize().width() > maxContentWidthDisplayableWithoutScrolling() ? contentSize().width()-maxContentWidthDisplayableWithoutScrolling() : 0; - } - setContentOffset(KDPoint(contentOffsetX, contentOffsetY)); + setContentOffset(KDPoint( + min(contentOffset().x(), max(contentSize().width() - maxContentWidthDisplayableWithoutScrolling(), 0)), + min(contentOffset().y(), max(contentSize().height() - maxContentHeightDisplayableWithoutScrolling(), 0)) + )); } void ScrollView::scrollToContentRect(KDRect rect, bool allowOverscroll) { From acecb92f756661c69198800044820be8b1c18e8e Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Thu, 31 Jan 2019 15:03:31 +0100 Subject: [PATCH 313/373] [escher/*_view_controller] New ViewController::initView() method Does some part of viewWillAppear(). --- .../include/escher/alternate_empty_view_controller.h | 1 + escher/include/escher/bank_view_controller.h | 1 + escher/include/escher/button_row_controller.h | 1 + escher/include/escher/modal_view_controller.h | 1 + escher/include/escher/stack_view_controller.h | 1 + escher/include/escher/tab_view_controller.h | 1 + escher/include/escher/view_controller.h | 9 +++++++-- escher/src/alternate_empty_view_controller.cpp | 4 ++++ escher/src/app.cpp | 3 ++- escher/src/bank_view_controller.cpp | 8 +++++++- escher/src/button_row_controller.cpp | 4 ++++ escher/src/modal_view_controller.cpp | 7 ++++++- escher/src/stack_view_controller.cpp | 5 +++++ escher/src/tab_view_controller.cpp | 12 +++++++----- 14 files changed, 48 insertions(+), 10 deletions(-) diff --git a/escher/include/escher/alternate_empty_view_controller.h b/escher/include/escher/alternate_empty_view_controller.h index e0834ad75..1e16d58fc 100644 --- a/escher/include/escher/alternate_empty_view_controller.h +++ b/escher/include/escher/alternate_empty_view_controller.h @@ -12,6 +12,7 @@ public: const char * title() override; bool handleEvent(Ion::Events::Event event) override; void didBecomeFirstResponder() override; + void initView() override; void viewWillAppear() override; void viewDidDisappear() override; private: diff --git a/escher/include/escher/bank_view_controller.h b/escher/include/escher/bank_view_controller.h index 5da61235b..90f7270da 100644 --- a/escher/include/escher/bank_view_controller.h +++ b/escher/include/escher/bank_view_controller.h @@ -15,6 +15,7 @@ public: View * view() override { return &m_view; } void didEnterResponderChain(Responder * previousResponder) override; + void initView() override; void viewWillAppear() override; void viewDidDisappear() override; private: diff --git a/escher/include/escher/button_row_controller.h b/escher/include/escher/button_row_controller.h index 4f4faa66f..879c1b5d7 100644 --- a/escher/include/escher/button_row_controller.h +++ b/escher/include/escher/button_row_controller.h @@ -33,6 +33,7 @@ public: int selectedButton(); bool setSelectedButton(int selectedButton); void setMessageOfButtonAtIndex(I18n::Message message, int index); + void initView() override; void viewWillAppear() override; void viewDidDisappear() override; ViewController::DisplayParameter displayParameter() override { return DisplayParameter::DoNotShowOwnTitle; } diff --git a/escher/include/escher/modal_view_controller.h b/escher/include/escher/modal_view_controller.h index 198e473b3..1bce427ad 100644 --- a/escher/include/escher/modal_view_controller.h +++ b/escher/include/escher/modal_view_controller.h @@ -16,6 +16,7 @@ public: void reloadModalViewController(); void dismissModalViewController(); bool isDisplayingModal(); + void initView() override; void viewWillAppear() override; void viewDidDisappear() override; protected: diff --git a/escher/include/escher/stack_view_controller.h b/escher/include/escher/stack_view_controller.h index f711f2748..7675072c4 100644 --- a/escher/include/escher/stack_view_controller.h +++ b/escher/include/escher/stack_view_controller.h @@ -21,6 +21,7 @@ public: const char * title() override; bool handleEvent(Ion::Events::Event event) override; void didBecomeFirstResponder() override; + void initView() override; void viewWillAppear() override; void viewDidDisappear() override; private: diff --git a/escher/include/escher/tab_view_controller.h b/escher/include/escher/tab_view_controller.h index 9e6328b03..f7bed6244 100644 --- a/escher/include/escher/tab_view_controller.h +++ b/escher/include/escher/tab_view_controller.h @@ -19,6 +19,7 @@ public: void didBecomeFirstResponder() override; void didEnterResponderChain(Responder * previousResponder) override; void willResignFirstResponder() override; + void initView() override; void viewWillAppear() override; void viewDidDisappear() override; private: diff --git a/escher/include/escher/view_controller.h b/escher/include/escher/view_controller.h index 316d7cae2..6084edc39 100644 --- a/escher/include/escher/view_controller.h +++ b/escher/include/escher/view_controller.h @@ -21,8 +21,12 @@ extern "C" { * - viewWillDisappear * - willExitResponderChain * - willResignFirstResponder - * Both methods are always called after setting a view and layouting it - * subviews. */ + * + * Both methods are always called after setting a view and laying its subwiews + * out. + * + * The method initView is called before setting a View (or often sets itself) + * and laying it out. */ #include #include @@ -43,6 +47,7 @@ public: ViewController(Responder * parentResponder); virtual const char * title(); virtual View * view() = 0; + virtual void initView() {} virtual void viewWillAppear(); virtual void viewDidDisappear(); virtual DisplayParameter displayParameter() { return DisplayParameter::Default; } diff --git a/escher/src/alternate_empty_view_controller.cpp b/escher/src/alternate_empty_view_controller.cpp index 5c23c1af9..43159799e 100644 --- a/escher/src/alternate_empty_view_controller.cpp +++ b/escher/src/alternate_empty_view_controller.cpp @@ -71,6 +71,10 @@ void AlternateEmptyViewController::didBecomeFirstResponder() { } } +void AlternateEmptyViewController::initView() { + m_contentView.mainViewController()->initView(); +} + void AlternateEmptyViewController::viewWillAppear() { m_contentView.layoutSubviews(); if (!m_contentView.alternateEmptyViewDelegate()->isEmpty()) { diff --git a/escher/src/app.cpp b/escher/src/app.cpp index 4a0b73b36..db8d49626 100644 --- a/escher/src/app.cpp +++ b/escher/src/app.cpp @@ -108,8 +108,9 @@ const Container * App::container() const { void App::didBecomeActive(Window * window) { View * view = m_modalViewController.view(); assert(m_modalViewController.app() == this); - m_modalViewController.viewWillAppear(); + m_modalViewController.initView(); window->setContentView(view); + m_modalViewController.viewWillAppear(); setFirstResponder(&m_modalViewController); } diff --git a/escher/src/bank_view_controller.cpp b/escher/src/bank_view_controller.cpp index 6e6146ad0..315088247 100644 --- a/escher/src/bank_view_controller.cpp +++ b/escher/src/bank_view_controller.cpp @@ -24,8 +24,14 @@ void BankViewController::didEnterResponderChain(Responder * previousResponder) { app()->setFirstResponder(activeViewController()); } -void BankViewController::viewWillAppear() { +void BankViewController::initView() { + for (int i = 0; i < numberOfChildren(); i++) { + childAtIndex(i)->initView(); + } m_view.setSubview(activeViewController()->view()); +} + +void BankViewController::viewWillAppear() { activeViewController()->viewWillAppear(); } diff --git a/escher/src/button_row_controller.cpp b/escher/src/button_row_controller.cpp index e225a5fae..941415889 100644 --- a/escher/src/button_row_controller.cpp +++ b/escher/src/button_row_controller.cpp @@ -211,6 +211,10 @@ bool ButtonRowController::handleEvent(Ion::Events::Event event) { return false; } +void ButtonRowController::initView() { + m_contentView.mainViewController()->initView(); +} + void ButtonRowController::viewWillAppear() { /* We need to layout subviews at first appearance because the number of * buttons might have changed between 2 appearences. */ diff --git a/escher/src/modal_view_controller.cpp b/escher/src/modal_view_controller.cpp index cd3ab4bd3..316a85c26 100644 --- a/escher/src/modal_view_controller.cpp +++ b/escher/src/modal_view_controller.cpp @@ -118,6 +118,7 @@ void ModalViewController::displayModalViewController(ViewController * vc, float m_currentModalViewController = vc; vc->setParentResponder(this); m_previousResponder = app()->firstResponder(); + m_currentModalViewController->initView(); m_contentView.presentModalView(vc->view(), verticalAlignment, horizontalAlignment, topMargin, leftMargin, bottomMargin, rightMargin); m_currentModalViewController->viewWillAppear(); app()->setFirstResponder(vc); @@ -152,8 +153,12 @@ bool ModalViewController::handleEvent(Ion::Events::Event event) { return false; } -void ModalViewController::viewWillAppear() { +void ModalViewController::initView() { m_contentView.setMainView(m_regularViewController->view()); + m_regularViewController->initView(); +} + +void ModalViewController::viewWillAppear() { m_contentView.layoutSubviews(); if (m_contentView.isDisplayingModal()) { m_currentModalViewController->viewWillAppear(); diff --git a/escher/src/stack_view_controller.cpp b/escher/src/stack_view_controller.cpp index fd5e2e74e..795a5ee3a 100644 --- a/escher/src/stack_view_controller.cpp +++ b/escher/src/stack_view_controller.cpp @@ -96,6 +96,7 @@ void StackViewController::push(ViewController * vc, KDColor textColor, KDColor b Frame frame = Frame(vc, textColor, backgroundColor, separatorColor); /* Add the frame to the model */ pushModel(frame); + frame.viewController()->initView(); if (!m_isVisible) { return; } @@ -156,6 +157,10 @@ View * StackViewController::view() { return &m_view; } +void StackViewController::initView() { + m_childrenFrame[0].viewController()->initView(); +} + void StackViewController::viewWillAppear() { /* Load the stack view */ for (int i = 0; i < m_numberOfChildren; i++) { diff --git a/escher/src/tab_view_controller.cpp b/escher/src/tab_view_controller.cpp index 91672bfe3..098663bc7 100644 --- a/escher/src/tab_view_controller.cpp +++ b/escher/src/tab_view_controller.cpp @@ -156,12 +156,14 @@ const char * TabViewController::tabName(uint8_t index) { return m_children[index]->title(); } -void TabViewController::viewWillAppear() { - if (m_view.m_tabView.numberOfTabs() != m_numberOfChildren) { - for (int i=0; iinitView(); } +} + +void TabViewController::viewWillAppear() { if (m_dataSource->activeTab() < 0) { m_dataSource->setActiveTab(0); } From c439d6f376512c60ebee5b53ccfc84d8a691b098 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Thu, 31 Jan 2019 15:15:02 +0100 Subject: [PATCH 314/373] [escher/scroll_view] Mark maxContent...DisplayableWithoutScrolling() as const --- escher/include/escher/scroll_view.h | 8 ++++++-- escher/src/scroll_view.cpp | 8 -------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index a460ebe38..5789d56f5 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -84,8 +84,12 @@ public: void scrollToContentPoint(KDPoint p, bool allowOverscroll = false); void scrollToContentRect(KDRect rect, bool allowOverscroll = false); // Minimal scrolling to make this rect visible protected: - KDCoordinate maxContentWidthDisplayableWithoutScrolling(); - KDCoordinate maxContentHeightDisplayableWithoutScrolling(); + KDCoordinate maxContentWidthDisplayableWithoutScrolling() const { + return m_frame.width() - m_leftMargin - m_rightMargin; + } + KDCoordinate maxContentHeightDisplayableWithoutScrolling() const { + return m_frame.height() - m_topMargin - m_bottomMargin; + } KDRect visibleContentRect(); void layoutSubviews() override; KDSize contentSize(); diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index a3fe12419..bd65b9f1c 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -126,14 +126,6 @@ void ScrollView::setContentOffset(KDPoint offset, bool forceRelayout) { } } -KDCoordinate ScrollView::maxContentWidthDisplayableWithoutScrolling() { - return m_frame.width() - m_leftMargin - m_rightMargin; -} - -KDCoordinate ScrollView::maxContentHeightDisplayableWithoutScrolling() { - return m_frame.height() - m_topMargin - m_bottomMargin; -} - ScrollView::BarDecorator::BarDecorator() : m_verticalBar(), m_horizontalBar(), From cda88b3c3b8ea1d05bd3e8436e9083b339ea474c Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Thu, 31 Jan 2019 15:20:05 +0100 Subject: [PATCH 315/373] [escher/scroll_view] Fix virtuality issues of layoutSubviews Method contentSize() made virtual and overridden by ScrollableView so that ScrollableView and TableView do not need to setSize themselves and that setSize/setFrame is not called twice over m_contentView. --- escher/include/escher/scroll_view.h | 2 +- escher/include/escher/scrollable_view.h | 2 +- escher/include/escher/table_view.h | 3 +-- escher/src/scroll_view.cpp | 8 +------- escher/src/scrollable_view.cpp | 11 +++++------ escher/src/table_view.cpp | 25 +++++++++++++------------ 6 files changed, 22 insertions(+), 29 deletions(-) diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index 5789d56f5..3a7ff7d92 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -92,7 +92,7 @@ protected: } KDRect visibleContentRect(); void layoutSubviews() override; - KDSize contentSize(); + virtual KDSize contentSize() const { return m_contentView->minimalSizeForOptimalDisplay(); } #if ESCHER_VIEW_LOGGING virtual const char * className() const override; virtual void logAttributes(std::ostream &os) const override; diff --git a/escher/include/escher/scrollable_view.h b/escher/include/escher/scrollable_view.h index 4ceeca709..ba4aaea4e 100644 --- a/escher/include/escher/scrollable_view.h +++ b/escher/include/escher/scrollable_view.h @@ -11,7 +11,7 @@ public: bool handleEvent(Ion::Events::Event event) override; void reloadScroll(bool forceRelayout = false); protected: - void layoutSubviews() override; + KDSize contentSize() const override; KDPoint m_manualScrollingOffset; }; diff --git a/escher/include/escher/table_view.h b/escher/include/escher/table_view.h index b67868cae..eb7010306 100644 --- a/escher/include/escher/table_view.h +++ b/escher/include/escher/table_view.h @@ -38,12 +38,12 @@ protected: void scrollToCell(int i, int j) const; void reloadCellAtLocation(int i, int j); HighlightCell * cellAtLocation(int i, int j); - void resizeToFitContent(); TableViewDataSource * dataSource(); int rowsScrollingOffset() const; int columnsScrollingOffset() const; int numberOfDisplayableRows() const; int numberOfDisplayableColumns() const; + void layoutSubviews() override; protected: #if ESCHER_VIEW_LOGGING const char * className() const override; @@ -54,7 +54,6 @@ protected: int numberOfSubviews() const override; View * subviewAtIndex(int index) override; - void layoutSubviews() override; /* realCellWidth enables to handle list view for which * TableViewDataSource->cellWidht = 0 */ diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index bd65b9f1c..52d2506b5 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -104,10 +104,8 @@ KDRect ScrollView::visibleContentRect() { } void ScrollView::layoutSubviews() { - // Layout contentView - // We're only re-positionning the contentView, not modifying its size. KDPoint absoluteOffset = contentOffset().opposite().translatedBy(KDPoint(m_leftMargin, m_topMargin)); - KDRect contentFrame = KDRect(absoluteOffset, m_contentView->bounds().size()); + KDRect contentFrame = KDRect(absoluteOffset, contentSize()); m_contentView->setFrame(contentFrame); KDSize content( m_contentView->bounds().width() + m_leftMargin + m_rightMargin, @@ -116,10 +114,6 @@ void ScrollView::layoutSubviews() { decorator()->layoutIndicators(content, contentOffset(), m_frame.size()); } -KDSize ScrollView::contentSize() { - return m_contentView->minimalSizeForOptimalDisplay(); -} - void ScrollView::setContentOffset(KDPoint offset, bool forceRelayout) { if (m_dataSource->setOffset(offset) || forceRelayout) { layoutSubviews(); diff --git a/escher/src/scrollable_view.cpp b/escher/src/scrollable_view.cpp index a8a30b9d2..ea122e2b0 100644 --- a/escher/src/scrollable_view.cpp +++ b/escher/src/scrollable_view.cpp @@ -50,10 +50,9 @@ void ScrollableView::reloadScroll(bool forceReLayout) { setContentOffset(m_manualScrollingOffset, forceReLayout); } -void ScrollableView::layoutSubviews() { - KDSize viewSize = contentSize(); - KDCoordinate viewWidth = max(viewSize.width(), bounds().width() - leftMargin() - rightMargin()); - KDCoordinate viewHeight = max(viewSize.height(), bounds().height() - topMargin() - bottomMargin()); - m_contentView->setSize(KDSize(viewWidth, viewHeight)); - ScrollView::layoutSubviews(); +KDSize ScrollableView::contentSize() const { + KDSize viewSize = ScrollView::contentSize(); + KDCoordinate viewWidth = max(viewSize.width(), maxContentWidthDisplayableWithoutScrolling()); + KDCoordinate viewHeight = max(viewSize.height(), maxContentHeightDisplayableWithoutScrolling()); + return KDSize(viewWidth, viewHeight); } diff --git a/escher/src/table_view.cpp b/escher/src/table_view.cpp index 6aa1784cd..9a9d2ef28 100644 --- a/escher/src/table_view.cpp +++ b/escher/src/table_view.cpp @@ -38,12 +38,20 @@ const char * TableView::className() const { #endif void TableView::layoutSubviews() { - // We only have to layout our contentView. - // We will size it here, and ScrollView::layoutSubviews will position it. - - m_contentView.resizeToFitContent(); - ScrollView::layoutSubviews(); + m_contentView.layoutSubviews(); + /* FIXME: + * On the one hand, ScrollView::layoutSubviews() + * calls setFrame(...) over m_contentView, + * which typically calls layoutSubviews() over m_contentView. + * However, if the frame happens to be unchanged, + * setFrame(...) does not call layoutSubviews. + * On the other hand, calling only m_contentView.layoutSubviews() + * does not relayout ScrollView when the offset + * or the content's size changes. + * For those reasons, we call both of them explicitly. + * Finally, this solution is not optimal at all since + * layoutSubviews is called twice over m_contentView. */ } void TableView::reloadCellAtLocation(int i, int j) { @@ -75,13 +83,6 @@ KDCoordinate TableView::ContentView::columnWidth(int i) const { return columnWidth; } -void TableView::ContentView::resizeToFitContent() { - if (!(m_tableView->bounds() == KDRectZero)) { - layoutSubviews(); - setSize(KDSize(width(), height())); - } -} - KDCoordinate TableView::ContentView::height() const { return m_dataSource->cumulatedHeightFromIndex(m_dataSource->numberOfRows())+m_verticalCellOverlap; } From 538d5cce6401480fcac26e5b4943eba85de38950 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Fri, 1 Feb 2019 17:16:57 +0100 Subject: [PATCH 316/373] [ion/blackbox/compare] Fix comment --- ion/src/blackbox/compare.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ion/src/blackbox/compare.cpp b/ion/src/blackbox/compare.cpp index 791ccfd2a..b3c18aec5 100644 --- a/ion/src/blackbox/compare.cpp +++ b/ion/src/blackbox/compare.cpp @@ -13,7 +13,7 @@ * * To compare the versions on a given scenario: * make -j8 PLATFORM=blackbox compare - * ./compare path/to/scenario + * ./compare < path/to/scenario * To fuzz over scenarios that are in a folder named "tests": * make -j8 PLATFORM=blackbox TOOLCHAIN=afl compare_fuzz */ From fd654d1c79f48b7ef4e6e9a549108b975fa2ec0b Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Fri, 8 Feb 2019 14:01:19 +0100 Subject: [PATCH 317/373] [escher/scroll_view] Remove setColorsBackground Introduced in commit 37da7b95a to avoid screen tearing. Not necessary anymore since commit 0e9092d2e. --- apps/home/controller.cpp | 2 +- apps/probability/calculation_type_controller.cpp | 1 - escher/include/escher/scroll_view.h | 3 --- escher/src/expression_field.cpp | 2 -- escher/src/scroll_view.cpp | 4 ---- escher/src/scrollable_view.cpp | 1 - 6 files changed, 1 insertion(+), 12 deletions(-) diff --git a/apps/home/controller.cpp b/apps/home/controller.cpp index a4f61b7c1..f1b7bcefc 100644 --- a/apps/home/controller.cpp +++ b/apps/home/controller.cpp @@ -11,7 +11,7 @@ Controller::ContentView::ContentView(Controller * controller, SelectableTableVie { m_selectableTableView.setVerticalCellOverlap(0); m_selectableTableView.setMargins(0, k_sideMargin, k_bottomMargin, k_sideMargin); - m_selectableTableView.setColorsBackground(false); + m_selectableTableView.setBackgroundColor(KDColorWhite); static_cast(m_selectableTableView.decorator())->setBarsFrameBreadth(k_scrollBarsFrameBreadth); static_cast(m_selectableTableView.decorator())->verticalBar()->setMargin(k_indicatorMargin); } diff --git a/apps/probability/calculation_type_controller.cpp b/apps/probability/calculation_type_controller.cpp index 0f16323f4..aef5c6527 100644 --- a/apps/probability/calculation_type_controller.cpp +++ b/apps/probability/calculation_type_controller.cpp @@ -23,7 +23,6 @@ CalculationTypeController::CalculationTypeController(Responder * parentResponder m_selectableTableView.setMargins(0); m_selectableTableView.setVerticalCellOverlap(0); m_selectableTableView.setDecoratorType(ScrollView::Decorator::Type::None); - m_selectableTableView.setColorsBackground(false); } View * CalculationTypeController::view() { diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index 3a7ff7d92..c58fe512e 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -73,8 +73,6 @@ public: Decorator * decorator(); void setDecoratorType(Decorator::Type t) { m_decoratorType = t; } - void setColorsBackground(bool c) { m_colorsBackground = c; } - bool colorsBackground() const { return m_colorsBackground; } virtual void setBackgroundColor(KDColor c) { m_backgroundColor = c; } KDColor backgroundColor() const { return m_backgroundColor; } @@ -112,7 +110,6 @@ private: Decorator m_decorator; BarDecorator m_barDecorator; ArrowDecorator m_arrowDecorator; - bool m_colorsBackground; KDColor m_backgroundColor; }; diff --git a/escher/src/expression_field.cpp b/escher/src/expression_field.cpp index 8d7e26287..2fa9ee575 100644 --- a/escher/src/expression_field.cpp +++ b/escher/src/expression_field.cpp @@ -13,11 +13,9 @@ ExpressionField::ExpressionField(Responder * parentResponder, char * textBuffer, // Initialize text field m_textField.setMargins(0, k_horizontalMargin, 0, k_horizontalMargin); m_textField.setBackgroundColor(KDColorWhite); - m_textField.setColorsBackground(true); // Initialize layout field m_layoutField.setMargins(k_verticalMargin, k_horizontalMargin, k_verticalMargin, k_horizontalMargin); m_layoutField.setBackgroundColor(KDColorWhite); - m_layoutField.setColorsBackground(true); } void ExpressionField::setEditing(bool isEditing, bool reinitDraftBuffer) { diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index 52d2506b5..31afada97 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -18,7 +18,6 @@ ScrollView::ScrollView(View * contentView, ScrollViewDataSource * dataSource) : m_decorator(), m_barDecorator(), m_arrowDecorator(), - m_colorsBackground(true), m_backgroundColor(Palette::WallScreen) { assert(m_dataSource != nullptr); @@ -44,9 +43,6 @@ ScrollView::Decorator * ScrollView::decorator() { } void ScrollView::drawRect(KDContext * ctx, KDRect rect) const { - if (!m_colorsBackground) { - return; - } KDCoordinate height = bounds().height(); KDCoordinate width = bounds().width(); KDCoordinate offsetX = contentOffset().x(); diff --git a/escher/src/scrollable_view.cpp b/escher/src/scrollable_view.cpp index ea122e2b0..1faeab4c4 100644 --- a/escher/src/scrollable_view.cpp +++ b/escher/src/scrollable_view.cpp @@ -8,7 +8,6 @@ ScrollableView::ScrollableView(Responder * parentResponder, View * view, ScrollV m_manualScrollingOffset(KDPointZero) { setDecoratorType(ScrollView::Decorator::Type::None); - setColorsBackground(false); } bool ScrollableView::handleEvent(Ion::Events::Event event) { From fb32d9385efc72bd1f439badd54d633836d188e0 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Tue, 5 Feb 2019 10:07:11 +0100 Subject: [PATCH 318/373] [escher/scroll_view] Encapsulate m_contentView inside m_innerView --- escher/include/escher/scroll_view.h | 17 +++++++++++++++-- escher/src/scroll_view.cpp | 28 +++++++++++++++------------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index c58fe512e..a3e5faf3e 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -8,7 +8,6 @@ class ScrollView : public View { public: ScrollView(View * contentView, ScrollViewDataSource * dataSource); - void drawRect(KDContext * ctx, KDRect rect) const override; void setTopMargin(KDCoordinate m) { m_topMargin = m; } KDCoordinate topMargin() const { return m_topMargin; } @@ -99,13 +98,27 @@ protected: private: ScrollViewDataSource * m_dataSource; int numberOfSubviews() const override { return 1 + const_cast(this)->decorator()->numberOfIndicators(); } - View * subviewAtIndex(int index) override { return (index == 0) ? m_contentView : decorator()->indicatorAtIndex(index); } + View * subviewAtIndex(int index) override { return (index == 0) ? &m_innerView : decorator()->indicatorAtIndex(index); } + + class InnerView : public View { + public: + InnerView(ScrollView * scrollView) : View(), m_scrollView(scrollView) {} + void drawRect(KDContext * ctx, KDRect rect) const override; + private: + int numberOfSubviews() const override { return 1; } + View * subviewAtIndex(int index) override { + assert(index == 0); + return m_scrollView->m_contentView; + } + const ScrollView * m_scrollView; + }; KDCoordinate m_topMargin; KDCoordinate m_rightMargin; KDCoordinate m_bottomMargin; KDCoordinate m_leftMargin; + InnerView m_innerView; Decorator::Type m_decoratorType; Decorator m_decorator; BarDecorator m_barDecorator; diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index 31afada97..7a519ff70 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -14,6 +14,7 @@ ScrollView::ScrollView(View * contentView, ScrollViewDataSource * dataSource) : m_rightMargin(0), m_bottomMargin(0), m_leftMargin(0), + m_innerView(this), m_decoratorType(Decorator::Type::Bars), m_decorator(), m_barDecorator(), @@ -42,19 +43,6 @@ ScrollView::Decorator * ScrollView::decorator() { } } -void ScrollView::drawRect(KDContext * ctx, KDRect rect) const { - KDCoordinate height = bounds().height(); - KDCoordinate width = bounds().width(); - KDCoordinate offsetX = contentOffset().x(); - KDCoordinate offsetY = contentOffset().y(); - KDCoordinate contentHeight = m_contentView->bounds().height(); - KDCoordinate contentWidth = m_contentView->bounds().width(); - ctx->fillRect(KDRect(0, 0, width, m_topMargin-offsetY), m_backgroundColor); - ctx->fillRect(KDRect(0, contentHeight+m_topMargin-offsetY, width, height - contentHeight - m_topMargin + offsetY), m_backgroundColor); - ctx->fillRect(KDRect(0, 0, m_leftMargin-offsetX, height), m_backgroundColor); - ctx->fillRect(KDRect(contentWidth + m_leftMargin - offsetX, 0, width - contentWidth - m_leftMargin + offsetX, height), m_backgroundColor); -} - void ScrollView::scrollToContentPoint(KDPoint p, bool allowOverscroll) { if (!allowOverscroll && !m_contentView->bounds().contains(p)) { return; @@ -100,6 +88,7 @@ KDRect ScrollView::visibleContentRect() { } void ScrollView::layoutSubviews() { + m_innerView.setFrame(bounds()); KDPoint absoluteOffset = contentOffset().opposite().translatedBy(KDPoint(m_leftMargin, m_topMargin)); KDRect contentFrame = KDRect(absoluteOffset, contentSize()); m_contentView->setFrame(contentFrame); @@ -116,6 +105,19 @@ void ScrollView::setContentOffset(KDPoint offset, bool forceRelayout) { } } +void ScrollView::InnerView::drawRect(KDContext * ctx, KDRect rect) const { + KDCoordinate height = bounds().height(); + KDCoordinate width = bounds().width(); + KDCoordinate offsetX = m_scrollView->contentOffset().x(); + KDCoordinate offsetY = m_scrollView->contentOffset().y(); + KDCoordinate contentHeight = m_scrollView->m_contentView->bounds().height(); + KDCoordinate contentWidth = m_scrollView->m_contentView->bounds().width(); + ctx->fillRect(KDRect(0, 0, width, m_scrollView->m_topMargin-offsetY), m_scrollView->m_backgroundColor); + ctx->fillRect(KDRect(0, contentHeight+m_scrollView->m_topMargin-offsetY, width, height - contentHeight - m_scrollView->m_topMargin + offsetY), m_scrollView->m_backgroundColor); + ctx->fillRect(KDRect(0, 0, m_scrollView->m_leftMargin-offsetX, height), m_scrollView->m_backgroundColor); + ctx->fillRect(KDRect(contentWidth + m_scrollView->m_leftMargin - offsetX, 0, width - contentWidth - m_scrollView->m_leftMargin + offsetX, height), m_scrollView->m_backgroundColor); +} + ScrollView::BarDecorator::BarDecorator() : m_verticalBar(), m_horizontalBar(), From 0e0b49acce11639b7576b270dfc6c209b000ce48 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Thu, 7 Feb 2019 16:08:15 +0100 Subject: [PATCH 319/373] [apps/calculation] Remove HistoryViewCell horizontal margins --- apps/calculation/history_view_cell.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/apps/calculation/history_view_cell.cpp b/apps/calculation/history_view_cell.cpp index 318798a80..05cc33bfc 100644 --- a/apps/calculation/history_view_cell.cpp +++ b/apps/calculation/history_view_cell.cpp @@ -93,20 +93,21 @@ View * HistoryViewCell::subviewAtIndex(int index) { } void HistoryViewCell::layoutSubviews() { - KDCoordinate width = bounds().width(); - KDCoordinate height = bounds().height(); + KDCoordinate maxFrameWidth = bounds().width(); KDSize inputSize = m_inputView.minimalSizeForOptimalDisplay(); - if (inputSize.width() + Metric::HistoryHorizontalMargin > width) { - m_inputView.setFrame(KDRect(Metric::HistoryHorizontalMargin, k_digitVerticalMargin, width - Metric::HistoryHorizontalMargin, inputSize.height())); - } else { - m_inputView.setFrame(KDRect(Metric::HistoryHorizontalMargin, k_digitVerticalMargin, inputSize.width(), inputSize.height())); - } + m_inputView.setFrame(KDRect( + 0, + k_digitVerticalMargin, + min(maxFrameWidth, inputSize.width()), + inputSize.height() + )); KDSize outputSize = m_scrollableOutputView.minimalSizeForOptimalDisplay(); - if (outputSize.width() + Metric::HistoryHorizontalMargin > width) { - m_scrollableOutputView.setFrame(KDRect(Metric::HistoryHorizontalMargin, inputSize.height() + 2*k_digitVerticalMargin, width - Metric::HistoryHorizontalMargin, height - inputSize.height() - 3*k_digitVerticalMargin)); - } else { - m_scrollableOutputView.setFrame(KDRect(width - outputSize.width() - Metric::HistoryHorizontalMargin, inputSize.height() + 2*k_digitVerticalMargin, outputSize.width(), height - inputSize.height() - 3*k_digitVerticalMargin)); - } + m_scrollableOutputView.setFrame(KDRect( + max(0, maxFrameWidth - outputSize.width()), + inputSize.height() + 2*k_digitVerticalMargin, + min(maxFrameWidth, outputSize.width()), + bounds().height() - inputSize.height() - 3*k_digitVerticalMargin + )); } void HistoryViewCell::setCalculation(Calculation * calculation) { From 08e8bf0eeb659b3bbca36c49d3081cdbc96ae618 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Tue, 5 Feb 2019 16:13:00 +0100 Subject: [PATCH 320/373] [escher] Implement ScrollView::minimalSizeForOptimalDisplay including margins Remove from derived classes: - apps/calculation/scrollable_expression_view - apps/code/consol_line_cell - apps/shared/scrollable_exact_approximate_expressions_view - escher/layout_field - escher/table_view - escher/text_field --- .../calculation/scrollable_expression_view.cpp | 4 ---- apps/calculation/scrollable_expression_view.h | 1 - apps/code/console_line_cell.cpp | 4 ---- apps/code/console_line_cell.h | 1 - apps/probability/parameters_controller.cpp | 4 ++-- ...able_exact_approximate_expressions_view.cpp | 4 ---- ...llable_exact_approximate_expressions_view.h | 1 - escher/include/escher/layout_field.h | 6 ------ escher/include/escher/scroll_view.h | 1 + escher/include/escher/table_view.h | 1 - escher/include/escher/text_field.h | 1 - escher/src/scroll_view.cpp | 18 +++++++++++------- escher/src/scrollable_view.cpp | 4 ++-- escher/src/table_view.cpp | 4 ---- escher/src/text_field.cpp | 4 ---- 15 files changed, 16 insertions(+), 42 deletions(-) diff --git a/apps/calculation/scrollable_expression_view.cpp b/apps/calculation/scrollable_expression_view.cpp index 35cfe08de..aa35d956f 100644 --- a/apps/calculation/scrollable_expression_view.cpp +++ b/apps/calculation/scrollable_expression_view.cpp @@ -20,8 +20,4 @@ void ScrollableExpressionView::setBackgroundColor(KDColor backgroundColor) { ScrollableView::setBackgroundColor(backgroundColor); } -KDSize ScrollableExpressionView::minimalSizeForOptimalDisplay() const { - return m_expressionView.minimalSizeForOptimalDisplay(); -} - } diff --git a/apps/calculation/scrollable_expression_view.h b/apps/calculation/scrollable_expression_view.h index d4ac8e330..78fc5ff56 100644 --- a/apps/calculation/scrollable_expression_view.h +++ b/apps/calculation/scrollable_expression_view.h @@ -10,7 +10,6 @@ public: ScrollableExpressionView(Responder * parentResponder); void setLayout(Poincare::Layout layout); void setBackgroundColor(KDColor backgroundColor) override; - KDSize minimalSizeForOptimalDisplay() const override; private: ExpressionView m_expressionView; }; diff --git a/apps/code/console_line_cell.cpp b/apps/code/console_line_cell.cpp index 7593591b1..5a696d57a 100644 --- a/apps/code/console_line_cell.cpp +++ b/apps/code/console_line_cell.cpp @@ -31,10 +31,6 @@ ConsoleLineCell::ScrollableConsoleLineView::ScrollableConsoleLineView(Responder { } -KDSize ConsoleLineCell::ScrollableConsoleLineView::minimalSizeForOptimalDisplay() const { - return m_consoleLineView.minimalSizeForOptimalDisplay(); -} - ConsoleLineCell::ConsoleLineCell(Responder * parentResponder) : HighlightCell(), Responder(parentResponder), diff --git a/apps/code/console_line_cell.h b/apps/code/console_line_cell.h index e192e82cc..8cb3ef58a 100644 --- a/apps/code/console_line_cell.h +++ b/apps/code/console_line_cell.h @@ -48,7 +48,6 @@ private: }; ScrollableConsoleLineView(Responder * parentResponder); - KDSize minimalSizeForOptimalDisplay() const override; ConsoleLineView * consoleLineView() { return &m_consoleLineView; } private: ConsoleLineView m_consoleLineView; diff --git a/apps/probability/parameters_controller.cpp b/apps/probability/parameters_controller.cpp index 1a2f82ffd..def7ab459 100644 --- a/apps/probability/parameters_controller.cpp +++ b/apps/probability/parameters_controller.cpp @@ -16,7 +16,7 @@ ParametersController::ContentView::ContentView(Responder * parentResponder, Sele } void ParametersController::ContentView::drawRect(KDContext * ctx, KDRect rect) const { - int tableHeight = m_selectableTableView->minimalSizeForOptimalDisplay().height()+ Metric::CommonTopMargin + Metric::CommonBottomMargin; + int tableHeight = m_selectableTableView->minimalSizeForOptimalDisplay().height(); ctx->fillRect(KDRect(0, tableHeight, bounds().width(), bounds().height() - tableHeight), Palette::WallScreen); } @@ -53,7 +53,7 @@ View * ParametersController::ContentView::subviewAtIndex(int index) { void ParametersController::ContentView::layoutSubviews() { KDCoordinate titleHeight = KDFont::SmallFont->glyphSize().height()+k_titleMargin; m_titleView.setFrame(KDRect(0, 0, bounds().width(), titleHeight)); - KDCoordinate tableHeight = m_selectableTableView->minimalSizeForOptimalDisplay().height() + Metric::CommonTopMargin + Metric::CommonBottomMargin; + KDCoordinate tableHeight = m_selectableTableView->minimalSizeForOptimalDisplay().height(); m_selectableTableView->setFrame(KDRect(0, titleHeight, bounds().width(), tableHeight)); KDCoordinate textHeight = KDFont::SmallFont->glyphSize().height(); KDCoordinate defOrigin = (titleHeight+tableHeight)/2+(bounds().height()-textHeight)/2; diff --git a/apps/shared/scrollable_exact_approximate_expressions_view.cpp b/apps/shared/scrollable_exact_approximate_expressions_view.cpp index 1a26b9709..8f29f1a6f 100644 --- a/apps/shared/scrollable_exact_approximate_expressions_view.cpp +++ b/apps/shared/scrollable_exact_approximate_expressions_view.cpp @@ -138,8 +138,4 @@ bool ScrollableExactApproximateExpressionsView::handleEvent(Ion::Events::Event e return ScrollableView::handleEvent(event); } -KDSize ScrollableExactApproximateExpressionsView::minimalSizeForOptimalDisplay() const { - return m_contentCell.minimalSizeForOptimalDisplay(); -} - } diff --git a/apps/shared/scrollable_exact_approximate_expressions_view.h b/apps/shared/scrollable_exact_approximate_expressions_view.h index 5f963ea75..3b4972edb 100644 --- a/apps/shared/scrollable_exact_approximate_expressions_view.h +++ b/apps/shared/scrollable_exact_approximate_expressions_view.h @@ -25,7 +25,6 @@ public: } void didBecomeFirstResponder() override; bool handleEvent(Ion::Events::Event event) override; - KDSize minimalSizeForOptimalDisplay() const override; Poincare::Layout layout() const { return m_contentCell.layout(); } diff --git a/escher/include/escher/layout_field.h b/escher/include/escher/layout_field.h index 343de5446..bb8a38927 100644 --- a/escher/include/escher/layout_field.h +++ b/escher/include/escher/layout_field.h @@ -43,12 +43,6 @@ public: return m_delegate->layoutFieldShouldFinishEditing(this, event); } - /* View */ - KDSize minimalSizeForOptimalDisplay() const override { - KDSize contentViewSize = m_contentView.minimalSizeForOptimalDisplay(); - return KDSize(contentViewSize.width(), contentViewSize.height()); - } - protected: void reload(KDSize previousSize); virtual bool privateHandleEvent(Ion::Events::Event event); diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index a3e5faf3e..57e7b385e 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -8,6 +8,7 @@ class ScrollView : public View { public: ScrollView(View * contentView, ScrollViewDataSource * dataSource); + KDSize minimalSizeForOptimalDisplay() const override; void setTopMargin(KDCoordinate m) { m_topMargin = m; } KDCoordinate topMargin() const { return m_topMargin; } diff --git a/escher/include/escher/table_view.h b/escher/include/escher/table_view.h index eb7010306..7fde8754c 100644 --- a/escher/include/escher/table_view.h +++ b/escher/include/escher/table_view.h @@ -20,7 +20,6 @@ public: virtual void scrollToCell(int i, int j); HighlightCell * cellAtLocation(int i, int j); void reloadCellAtLocation(int i, int j); - KDSize minimalSizeForOptimalDisplay() const override; protected: #if ESCHER_VIEW_LOGGING const char * className() const override; diff --git a/escher/include/escher/text_field.h b/escher/include/escher/text_field.h index f04e5772a..49b488747 100644 --- a/escher/include/escher/text_field.h +++ b/escher/include/escher/text_field.h @@ -20,7 +20,6 @@ public: void setText(const char * text); void setAlignment(float horizontalAlignment, float verticalAlignment); virtual void setEditing(bool isEditing, bool reinitDraftBuffer = true) override; - KDSize minimalSizeForOptimalDisplay() const override; char XNTChar(char defaultXNTChar) override; bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false) override; bool handleEvent(Ion::Events::Event event) override; diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index 7a519ff70..2539ea0fa 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -24,6 +24,14 @@ ScrollView::ScrollView(View * contentView, ScrollViewDataSource * dataSource) : assert(m_dataSource != nullptr); } +KDSize ScrollView::minimalSizeForOptimalDisplay() const { + KDSize contentSize = m_contentView->minimalSizeForOptimalDisplay(); + return KDSize( + contentSize.width() + m_leftMargin + m_rightMargin, + contentSize.height() + m_topMargin + m_bottomMargin + ); +} + void ScrollView::setCommonMargins() { setTopMargin(Metric::CommonTopMargin); setRightMargin(Metric::CommonRightMargin); @@ -68,8 +76,8 @@ void ScrollView::scrollToContentPoint(KDPoint p, bool allowOverscroll) { /* Handle cases when the size of the view has decreased. */ setContentOffset(KDPoint( - min(contentOffset().x(), max(contentSize().width() - maxContentWidthDisplayableWithoutScrolling(), 0)), - min(contentOffset().y(), max(contentSize().height() - maxContentHeightDisplayableWithoutScrolling(), 0)) + min(contentOffset().x(), max(minimalSizeForOptimalDisplay().width() - bounds().width(), 0)), + min(contentOffset().y(), max(minimalSizeForOptimalDisplay().height() - bounds().height(), 0)) )); } @@ -92,11 +100,7 @@ void ScrollView::layoutSubviews() { KDPoint absoluteOffset = contentOffset().opposite().translatedBy(KDPoint(m_leftMargin, m_topMargin)); KDRect contentFrame = KDRect(absoluteOffset, contentSize()); m_contentView->setFrame(contentFrame); - KDSize content( - m_contentView->bounds().width() + m_leftMargin + m_rightMargin, - m_contentView->bounds().height() + m_topMargin + m_bottomMargin - ); - decorator()->layoutIndicators(content, contentOffset(), m_frame.size()); + decorator()->layoutIndicators(minimalSizeForOptimalDisplay(), contentOffset(), m_frame.size()); } void ScrollView::setContentOffset(KDPoint offset, bool forceRelayout) { diff --git a/escher/src/scrollable_view.cpp b/escher/src/scrollable_view.cpp index 1faeab4c4..f2781fa32 100644 --- a/escher/src/scrollable_view.cpp +++ b/escher/src/scrollable_view.cpp @@ -19,7 +19,7 @@ bool ScrollableView::handleEvent(Ion::Events::Event event) { } } if (event == Ion::Events::Right) { - KDCoordinate movementToEdge = m_contentView->minimalSizeForOptimalDisplay().width() - bounds().width() - m_manualScrollingOffset.x(); + KDCoordinate movementToEdge = minimalSizeForOptimalDisplay().width() - bounds().width() - m_manualScrollingOffset.x(); if (movementToEdge > 0) { translation = KDPoint(min(Metric::ScrollStep, movementToEdge), 0); } @@ -31,7 +31,7 @@ bool ScrollableView::handleEvent(Ion::Events::Event event) { } } if (event == Ion::Events::Down) { - KDCoordinate movementToEdge = m_contentView->minimalSizeForOptimalDisplay().height() - bounds().height() - m_manualScrollingOffset.y(); + KDCoordinate movementToEdge = minimalSizeForOptimalDisplay().height() - bounds().height() - m_manualScrollingOffset.y(); if (movementToEdge > 0) { translation = KDPoint(0, min(Metric::ScrollStep, movementToEdge)); } diff --git a/escher/src/table_view.cpp b/escher/src/table_view.cpp index 9a9d2ef28..adb859b8d 100644 --- a/escher/src/table_view.cpp +++ b/escher/src/table_view.cpp @@ -13,10 +13,6 @@ TableView::TableView(TableViewDataSource * dataSource, ScrollViewDataSource * sc { } -KDSize TableView::minimalSizeForOptimalDisplay() const { - return m_contentView.minimalSizeForOptimalDisplay(); -} - TableViewDataSource * TableView::dataSource() { return m_contentView.dataSource(); } diff --git a/escher/src/text_field.cpp b/escher/src/text_field.cpp index bd0cb88b9..7f21bcfc6 100644 --- a/escher/src/text_field.cpp +++ b/escher/src/text_field.cpp @@ -312,10 +312,6 @@ bool TextField::privateHandleEvent(Ion::Events::Event event) { return false; } -KDSize TextField::minimalSizeForOptimalDisplay() const { - return m_contentView.minimalSizeForOptimalDisplay(); -} - char TextField::XNTChar(char defaultXNTChar) { static constexpr struct { const char *name; char xnt; } sFunctions[] = { { "diff", 'x' }, { "int", 'x' }, From 7a977f5689b95d6384acaae615a49fe7775bab68 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Thu, 7 Feb 2019 16:13:03 +0100 Subject: [PATCH 321/373] [apps/calculation] Remove redundancy In HistoryController::willDisplayCellForIndex, both setCalculation and reloadCell end up calling ScrollableExpressionView::layoutSubviews. Indeed, setCalculation calls setLayout over m_inputView, which in turn calls layoutSubviews. It is logical to remove the first occurence. --- apps/calculation/scrollable_expression_view.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/calculation/scrollable_expression_view.cpp b/apps/calculation/scrollable_expression_view.cpp index aa35d956f..692662014 100644 --- a/apps/calculation/scrollable_expression_view.cpp +++ b/apps/calculation/scrollable_expression_view.cpp @@ -12,7 +12,6 @@ ScrollableExpressionView::ScrollableExpressionView(Responder * parentResponder) void ScrollableExpressionView::setLayout(Layout layout) { m_expressionView.setLayout(layout); - layoutSubviews(); } void ScrollableExpressionView::setBackgroundColor(KDColor backgroundColor) { From da0d42ca3b27d4e0b15144f575023d8faa6c6576 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Thu, 7 Feb 2019 18:19:44 +0100 Subject: [PATCH 322/373] [apps/calculation/history_view_cell] Fix background colors Set m_inputView's m_expressionView's background color --- apps/calculation/history_view_cell.cpp | 5 +++-- apps/calculation/scrollable_expression_view.cpp | 4 ++++ apps/calculation/scrollable_expression_view.h | 1 + escher/include/escher/scroll_view.h | 7 ++++++- escher/include/escher/scroll_view_indicator.h | 1 + escher/src/scroll_view.cpp | 6 ++++++ 6 files changed, 21 insertions(+), 3 deletions(-) diff --git a/apps/calculation/history_view_cell.cpp b/apps/calculation/history_view_cell.cpp index 05cc33bfc..d51413654 100644 --- a/apps/calculation/history_view_cell.cpp +++ b/apps/calculation/history_view_cell.cpp @@ -39,17 +39,18 @@ Shared::ScrollableExactApproximateExpressionsView * HistoryViewCell::outputView( void HistoryViewCell::setEven(bool even) { EvenOddCell::setEven(even); m_inputView.setBackgroundColor(backgroundColor()); + m_scrollableOutputView.setBackgroundColor(backgroundColor()); m_scrollableOutputView.evenOddCell()->setEven(even); } void HistoryViewCell::setHighlighted(bool highlight) { assert(m_dataSource); m_highlighted = highlight; - m_inputView.setBackgroundColor(backgroundColor()); + m_inputView.setExpressionBackgroundColor(backgroundColor()); m_scrollableOutputView.evenOddCell()->setHighlighted(false); if (isHighlighted()) { if (m_dataSource->selectedSubviewType() == HistoryViewCellDataSource::SubviewType::Input) { - m_inputView.setBackgroundColor(Palette::Select); + m_inputView.setExpressionBackgroundColor(Palette::Select); } else { m_scrollableOutputView.evenOddCell()->setHighlighted(true); } diff --git a/apps/calculation/scrollable_expression_view.cpp b/apps/calculation/scrollable_expression_view.cpp index 692662014..a07068934 100644 --- a/apps/calculation/scrollable_expression_view.cpp +++ b/apps/calculation/scrollable_expression_view.cpp @@ -19,4 +19,8 @@ void ScrollableExpressionView::setBackgroundColor(KDColor backgroundColor) { ScrollableView::setBackgroundColor(backgroundColor); } +void ScrollableExpressionView::setExpressionBackgroundColor(KDColor backgroundColor) { + m_expressionView.setBackgroundColor(backgroundColor); +} + } diff --git a/apps/calculation/scrollable_expression_view.h b/apps/calculation/scrollable_expression_view.h index 78fc5ff56..15ce343bf 100644 --- a/apps/calculation/scrollable_expression_view.h +++ b/apps/calculation/scrollable_expression_view.h @@ -10,6 +10,7 @@ public: ScrollableExpressionView(Responder * parentResponder); void setLayout(Poincare::Layout layout); void setBackgroundColor(KDColor backgroundColor) override; + void setExpressionBackgroundColor(KDColor backgroundColor); private: ExpressionView m_expressionView; }; diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index 57e7b385e..6fa18ac84 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -35,6 +35,7 @@ public: virtual int numberOfIndicators() { return 0; } virtual View * indicatorAtIndex(int index) { assert(false); return nullptr; } virtual void layoutIndicators(KDSize content, KDPoint offset, KDSize frame) {} + virtual void setBackgroundColor(KDColor c) {} }; class BarDecorator : public Decorator { @@ -64,6 +65,7 @@ public: return &m_topArrow + (index-1); } void layoutIndicators(KDSize content, KDPoint offset, KDSize frame) override; + void setBackgroundColor(KDColor c) override; private: ScrollViewArrow m_topArrow; ScrollViewArrow m_rightArrow; @@ -73,7 +75,10 @@ public: Decorator * decorator(); void setDecoratorType(Decorator::Type t) { m_decoratorType = t; } - virtual void setBackgroundColor(KDColor c) { m_backgroundColor = c; } + virtual void setBackgroundColor(KDColor c) { + m_backgroundColor = c; + decorator()->setBackgroundColor(m_backgroundColor); + } KDColor backgroundColor() const { return m_backgroundColor; } void setContentOffset(KDPoint offset, bool forceRelayout = false); diff --git a/escher/include/escher/scroll_view_indicator.h b/escher/include/escher/scroll_view_indicator.h index 6744d6974..b91a64bb4 100644 --- a/escher/include/escher/scroll_view_indicator.h +++ b/escher/include/escher/scroll_view_indicator.h @@ -53,6 +53,7 @@ public: }; ScrollViewArrow(Side side); bool update(bool visible); + void setBackgroundColor(KDColor c) { m_backgroundColor = c; } void drawRect(KDContext * ctx, KDRect rect) const override; private: bool m_visible; diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index 2539ea0fa..f22f77f07 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -184,6 +184,12 @@ void ScrollView::ArrowDecorator::layoutIndicators(KDSize content, KDPoint offset )); } +void ScrollView::ArrowDecorator::setBackgroundColor(KDColor c) { + for (int i = 0; i < numberOfIndicators(); i++) { + (&m_topArrow + i)->setBackgroundColor(c); + } +} + #if ESCHER_VIEW_LOGGING const char * ScrollView::className() const { return "ScrollView"; From 98e00404b824587c21eaf741fceabb89928ce4a7 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Mon, 11 Feb 2019 15:08:02 +0100 Subject: [PATCH 323/373] [apps/calculation] Enable arrow scrolling indicators and add horizontal margin --- apps/calculation/scrollable_expression_view.cpp | 2 ++ apps/shared/scrollable_exact_approximate_expressions_view.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/apps/calculation/scrollable_expression_view.cpp b/apps/calculation/scrollable_expression_view.cpp index a07068934..68e150883 100644 --- a/apps/calculation/scrollable_expression_view.cpp +++ b/apps/calculation/scrollable_expression_view.cpp @@ -8,6 +8,8 @@ ScrollableExpressionView::ScrollableExpressionView(Responder * parentResponder) ScrollableView(parentResponder, &m_expressionView, this), m_expressionView() { + setDecoratorType(ScrollView::Decorator::Type::Arrows); + setMargins(0, Metric::HistoryHorizontalMargin, 0, Metric::HistoryHorizontalMargin); } void ScrollableExpressionView::setLayout(Layout layout) { diff --git a/apps/shared/scrollable_exact_approximate_expressions_view.cpp b/apps/shared/scrollable_exact_approximate_expressions_view.cpp index 8f29f1a6f..75e349b2d 100644 --- a/apps/shared/scrollable_exact_approximate_expressions_view.cpp +++ b/apps/shared/scrollable_exact_approximate_expressions_view.cpp @@ -102,6 +102,8 @@ ScrollableExactApproximateExpressionsView::ScrollableExactApproximateExpressions ScrollableView(parentResponder, &m_contentCell, this), m_contentCell() { + setDecoratorType(ScrollView::Decorator::Type::Arrows); + setMargins(0, Metric::HistoryHorizontalMargin, 0, Metric::HistoryHorizontalMargin); } void ScrollableExactApproximateExpressionsView::setLayouts(Poincare::Layout rightLayout, Poincare::Layout leftLayout) { From 76537cd43241337cd715f9699eafeb9a36d3c5d6 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Mon, 11 Feb 2019 15:56:45 +0100 Subject: [PATCH 324/373] [escher/scroll_view] layoutSubviews without screen tearing due to indicators --- escher/include/escher/scroll_view.h | 6 +++--- escher/src/scroll_view.cpp | 21 ++++++++++++++------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index 6fa18ac84..fde6512ce 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -34,7 +34,7 @@ public: }; virtual int numberOfIndicators() { return 0; } virtual View * indicatorAtIndex(int index) { assert(false); return nullptr; } - virtual void layoutIndicators(KDSize content, KDPoint offset, KDSize frame) {} + virtual KDRect layoutIndicators(KDSize content, KDPoint offset, KDRect frame) { return frame; } virtual void setBackgroundColor(KDColor c) {} }; @@ -46,7 +46,7 @@ public: assert(0 < index && index <= numberOfIndicators()); return &m_verticalBar + (index-1); } - void layoutIndicators(KDSize content, KDPoint offset, KDSize frame) override; + KDRect layoutIndicators(KDSize content, KDPoint offset, KDRect frame) override; ScrollViewVerticalBar * verticalBar() { return &m_verticalBar; } ScrollViewHorizontalBar * horizontalBar() { return &m_horizontalBar; } void setBarsFrameBreadth(KDCoordinate t) { m_barsFrameBreadth = t; } @@ -64,7 +64,7 @@ public: assert(0 < index && index <= numberOfIndicators()); return &m_topArrow + (index-1); } - void layoutIndicators(KDSize content, KDPoint offset, KDSize frame) override; + KDRect layoutIndicators(KDSize content, KDPoint offset, KDRect frame) override; void setBackgroundColor(KDColor c) override; private: ScrollViewArrow m_topArrow; diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index f22f77f07..4209ce91e 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -96,11 +96,11 @@ KDRect ScrollView::visibleContentRect() { } void ScrollView::layoutSubviews() { - m_innerView.setFrame(bounds()); - KDPoint absoluteOffset = contentOffset().opposite().translatedBy(KDPoint(m_leftMargin, m_topMargin)); + KDRect innerFrame = decorator()->layoutIndicators(minimalSizeForOptimalDisplay(), contentOffset(), bounds()); + m_innerView.setFrame(innerFrame); + KDPoint absoluteOffset = contentOffset().opposite().translatedBy(KDPoint(m_leftMargin - innerFrame.x(), m_topMargin - innerFrame.y())); KDRect contentFrame = KDRect(absoluteOffset, contentSize()); m_contentView->setFrame(contentFrame); - decorator()->layoutIndicators(minimalSizeForOptimalDisplay(), contentOffset(), m_frame.size()); } void ScrollView::setContentOffset(KDPoint offset, bool forceRelayout) { @@ -112,8 +112,8 @@ void ScrollView::setContentOffset(KDPoint offset, bool forceRelayout) { void ScrollView::InnerView::drawRect(KDContext * ctx, KDRect rect) const { KDCoordinate height = bounds().height(); KDCoordinate width = bounds().width(); - KDCoordinate offsetX = m_scrollView->contentOffset().x(); - KDCoordinate offsetY = m_scrollView->contentOffset().y(); + KDCoordinate offsetX = m_scrollView->contentOffset().x() + m_frame.x(); + KDCoordinate offsetY = m_scrollView->contentOffset().y() + m_frame.y(); KDCoordinate contentHeight = m_scrollView->m_contentView->bounds().height(); KDCoordinate contentWidth = m_scrollView->m_contentView->bounds().width(); ctx->fillRect(KDRect(0, 0, width, m_scrollView->m_topMargin-offsetY), m_scrollView->m_backgroundColor); @@ -129,7 +129,7 @@ ScrollView::BarDecorator::BarDecorator() : { } -void ScrollView::BarDecorator::layoutIndicators(KDSize content, KDPoint offset, KDSize frame) { +KDRect ScrollView::BarDecorator::layoutIndicators(KDSize content, KDPoint offset, KDRect frame) { KDCoordinate hBarFrameBreadth = m_barsFrameBreadth * m_horizontalBar.update( content.width(), offset.x(), @@ -150,6 +150,7 @@ void ScrollView::BarDecorator::layoutIndicators(KDSize content, KDPoint offset, 0, frame.height() - hBarFrameBreadth, frame.width() - vBarFrameBreadth, hBarFrameBreadth )); + return frame; } ScrollView::ArrowDecorator::ArrowDecorator() : @@ -160,7 +161,7 @@ ScrollView::ArrowDecorator::ArrowDecorator() : { } -void ScrollView::ArrowDecorator::layoutIndicators(KDSize content, KDPoint offset, KDSize frame) { +KDRect ScrollView::ArrowDecorator::layoutIndicators(KDSize content, KDPoint offset, KDRect frame) { KDSize arrowSize = KDFont::LargeFont->glyphSize(); KDCoordinate topArrowFrameBreadth = arrowSize.height() * m_topArrow.update(0 < offset.y()); KDCoordinate rightArrowFrameBreadth = arrowSize.width() * m_rightArrow.update(offset.x() + frame.width() < content.width()); @@ -182,6 +183,12 @@ void ScrollView::ArrowDecorator::layoutIndicators(KDSize content, KDPoint offset 0, 0, leftArrowFrameBreadth, frame.height() )); + return KDRect( + frame.x() + leftArrowFrameBreadth, + frame.y() + topArrowFrameBreadth, + frame.width() - leftArrowFrameBreadth - rightArrowFrameBreadth, + frame.height() - topArrowFrameBreadth - bottomArrowFrameBreadth + ); } void ScrollView::ArrowDecorator::setBackgroundColor(KDColor c) { From 1662b06f3698fcd9fb69814c82b217e5ae806664 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Tue, 12 Feb 2019 16:18:10 +0100 Subject: [PATCH 325/373] [escher/scroll_view] Put the decorators inside a union --- escher/include/escher/scroll_view.h | 24 ++++++++++++--- escher/src/scroll_view.cpp | 48 +++++++++++++++++++---------- 2 files changed, 51 insertions(+), 21 deletions(-) diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index fde6512ce..ea8490838 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -8,6 +8,7 @@ class ScrollView : public View { public: ScrollView(View * contentView, ScrollViewDataSource * dataSource); + ScrollView(ScrollView&& other); KDSize minimalSizeForOptimalDisplay() const override; void setTopMargin(KDCoordinate m) { m_topMargin = m; } @@ -73,8 +74,11 @@ public: ScrollViewArrow m_leftArrow; }; - Decorator * decorator(); - void setDecoratorType(Decorator::Type t) { m_decoratorType = t; } + Decorator * decorator() { return m_decorators.activeDecorator(); } + void setDecoratorType(Decorator::Type t) { + m_decoratorType = t; + m_decorators.setActiveDecorator(t); + } virtual void setBackgroundColor(KDColor c) { m_backgroundColor = c; decorator()->setBackgroundColor(m_backgroundColor); @@ -126,9 +130,19 @@ private: InnerView m_innerView; Decorator::Type m_decoratorType; - Decorator m_decorator; - BarDecorator m_barDecorator; - ArrowDecorator m_arrowDecorator; + union Decorators { + public: + /* Enforce trivial constructor and destructor that just leaves the memory unmodified. */ + Decorators() {} + ~Decorators() {} + Decorator * activeDecorator() { return &m_none; } + void setActiveDecorator(Decorator::Type t); + private: + Decorator m_none; + BarDecorator m_bars; + ArrowDecorator m_arrows; + }; + Decorators m_decorators; KDColor m_backgroundColor; }; diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index 4209ce91e..d60756393 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -2,6 +2,8 @@ #include #include +#include + extern "C" { #include } @@ -15,13 +17,24 @@ ScrollView::ScrollView(View * contentView, ScrollViewDataSource * dataSource) : m_bottomMargin(0), m_leftMargin(0), m_innerView(this), - m_decoratorType(Decorator::Type::Bars), - m_decorator(), - m_barDecorator(), - m_arrowDecorator(), + m_decorators(), m_backgroundColor(Palette::WallScreen) { assert(m_dataSource != nullptr); + setDecoratorType(Decorator::Type::Bars); +} + +ScrollView::ScrollView(ScrollView&& other) : + m_contentView(other.m_contentView), + m_dataSource(other.m_dataSource), + m_topMargin(other.m_topMargin), + m_rightMargin(other.m_rightMargin), + m_bottomMargin(other.m_bottomMargin), + m_leftMargin(other.m_leftMargin), + m_innerView(this), + m_backgroundColor(other.m_backgroundColor) +{ + setDecoratorType(other.m_decoratorType); } KDSize ScrollView::minimalSizeForOptimalDisplay() const { @@ -39,18 +52,6 @@ void ScrollView::setCommonMargins() { setLeftMargin(Metric::CommonLeftMargin); } -ScrollView::Decorator * ScrollView::decorator() { - switch (m_decoratorType) { - case Decorator::Type::Bars: - return &m_barDecorator; - case Decorator::Type::Arrows: - return &m_arrowDecorator; - default: - assert(m_decoratorType == Decorator::Type::None); - return &m_decorator; - } -} - void ScrollView::scrollToContentPoint(KDPoint p, bool allowOverscroll) { if (!allowOverscroll && !m_contentView->bounds().contains(p)) { return; @@ -197,6 +198,21 @@ void ScrollView::ArrowDecorator::setBackgroundColor(KDColor c) { } } +void ScrollView::Decorators::setActiveDecorator(Decorator::Type t) { + /* We do NOT need to destroy the previous decorator because they don't have a destructor */ + switch (t) { + case Decorator::Type::Bars: + new (&m_bars) BarDecorator(); + break; + case Decorator::Type::Arrows: + new (&m_arrows) ArrowDecorator(); + break; + default: + assert(t == Decorator::Type::None); + new (&m_none) Decorator(); + } +} + #if ESCHER_VIEW_LOGGING const char * ScrollView::className() const { return "ScrollView"; From f18a55defe9a21135a52274cc8c03523c25c704e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 14 Feb 2019 11:43:54 +0100 Subject: [PATCH 326/373] [escher] ScrollView: make numberOfIndicators method const --- escher/include/escher/scroll_view.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index ea8490838..5f627f7c8 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -33,7 +33,7 @@ public: Bars, Arrows }; - virtual int numberOfIndicators() { return 0; } + virtual int numberOfIndicators() const { return 0; } virtual View * indicatorAtIndex(int index) { assert(false); return nullptr; } virtual KDRect layoutIndicators(KDSize content, KDPoint offset, KDRect frame) { return frame; } virtual void setBackgroundColor(KDColor c) {} @@ -42,7 +42,7 @@ public: class BarDecorator : public Decorator { public: BarDecorator(); - int numberOfIndicators() override { return 2; } + int numberOfIndicators() const override { return 2; } View * indicatorAtIndex(int index) override { assert(0 < index && index <= numberOfIndicators()); return &m_verticalBar + (index-1); @@ -60,7 +60,7 @@ public: class ArrowDecorator : public Decorator { public: ArrowDecorator(); - int numberOfIndicators() override { return 4; } + int numberOfIndicators() const override { return 4; } View * indicatorAtIndex(int index) override { assert(0 < index && index <= numberOfIndicators()); return &m_topArrow + (index-1); From 3487547f167b0567b57d5ccd8a4774eb6d5a309f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 14 Feb 2019 15:40:03 +0100 Subject: [PATCH 327/373] [escher] ScrollView: fix Decorators contructor/destructors --- escher/include/escher/scroll_view.h | 8 +++++--- escher/src/scroll_view.cpp | 14 +++++++++++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index 5f627f7c8..cc680eec6 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -33,6 +33,9 @@ public: Bars, Arrows }; + /* We want (Decorator *)->~Decorator() to call ~BarDecorator() or ~ArrowDecorator() + * when required. */ + virtual ~Decorator() = default; virtual int numberOfIndicators() const { return 0; } virtual View * indicatorAtIndex(int index) { assert(false); return nullptr; } virtual KDRect layoutIndicators(KDSize content, KDPoint offset, KDRect frame) { return frame; } @@ -132,9 +135,8 @@ private: Decorator::Type m_decoratorType; union Decorators { public: - /* Enforce trivial constructor and destructor that just leaves the memory unmodified. */ - Decorators() {} - ~Decorators() {} + Decorators(); + ~Decorators(); Decorator * activeDecorator() { return &m_none; } void setActiveDecorator(Decorator::Type t); private: diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index d60756393..76dcf9bbd 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -198,8 +198,20 @@ void ScrollView::ArrowDecorator::setBackgroundColor(KDColor c) { } } +ScrollView::Decorators::Decorators() { + /* We need to initiate the Union at construction to avoid destructing an + * uninitialized object when changing the decorator type. */ + new (this) Decorator(); +} + +ScrollView::Decorators::~Decorators() { + activeDecorator()->~Decorator(); +} + void ScrollView::Decorators::setActiveDecorator(Decorator::Type t) { - /* We do NOT need to destroy the previous decorator because they don't have a destructor */ + /* Decorator destructor is virtual so calling ~Decorator() on a Decorator + * pointer will call the appropriate destructor. */ + activeDecorator()->~Decorator(); switch (t) { case Decorator::Type::Bars: new (&m_bars) BarDecorator(); From 15de9f93ef09f9e540121d68ee51bcab6ebe19c0 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Thu, 14 Feb 2019 16:57:44 +0100 Subject: [PATCH 328/373] [escher/scroll_view] Implement Decorator::indicatorAtIndex explicitly Instead of using pointer arithmetic --- escher/include/escher/scroll_view.h | 10 ++-------- escher/src/scroll_view.cpp | 28 ++++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index cc680eec6..8fd79e7d6 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -46,10 +46,7 @@ public: public: BarDecorator(); int numberOfIndicators() const override { return 2; } - View * indicatorAtIndex(int index) override { - assert(0 < index && index <= numberOfIndicators()); - return &m_verticalBar + (index-1); - } + View * indicatorAtIndex(int index) override; KDRect layoutIndicators(KDSize content, KDPoint offset, KDRect frame) override; ScrollViewVerticalBar * verticalBar() { return &m_verticalBar; } ScrollViewHorizontalBar * horizontalBar() { return &m_horizontalBar; } @@ -64,10 +61,7 @@ public: public: ArrowDecorator(); int numberOfIndicators() const override { return 4; } - View * indicatorAtIndex(int index) override { - assert(0 < index && index <= numberOfIndicators()); - return &m_topArrow + (index-1); - } + View * indicatorAtIndex(int index) override; KDRect layoutIndicators(KDSize content, KDPoint offset, KDRect frame) override; void setBackgroundColor(KDColor c) override; private: diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index 76dcf9bbd..832ac6f4c 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -130,6 +130,16 @@ ScrollView::BarDecorator::BarDecorator() : { } +View * ScrollView::BarDecorator::indicatorAtIndex(int index) { + switch(index) { + case 1: + return &m_verticalBar; + default: + assert(index == 2); + return &m_horizontalBar; + } +} + KDRect ScrollView::BarDecorator::layoutIndicators(KDSize content, KDPoint offset, KDRect frame) { KDCoordinate hBarFrameBreadth = m_barsFrameBreadth * m_horizontalBar.update( content.width(), @@ -162,6 +172,20 @@ ScrollView::ArrowDecorator::ArrowDecorator() : { } +View * ScrollView::ArrowDecorator::indicatorAtIndex(int index) { + switch(index) { + case 1: + return &m_topArrow; + case 2: + return &m_rightArrow; + case 3: + return &m_bottomArrow; + default: + assert(index == 4); + return &m_leftArrow; + } +} + KDRect ScrollView::ArrowDecorator::layoutIndicators(KDSize content, KDPoint offset, KDRect frame) { KDSize arrowSize = KDFont::LargeFont->glyphSize(); KDCoordinate topArrowFrameBreadth = arrowSize.height() * m_topArrow.update(0 < offset.y()); @@ -193,8 +217,8 @@ KDRect ScrollView::ArrowDecorator::layoutIndicators(KDSize content, KDPoint offs } void ScrollView::ArrowDecorator::setBackgroundColor(KDColor c) { - for (int i = 0; i < numberOfIndicators(); i++) { - (&m_topArrow + i)->setBackgroundColor(c); + for (int index = 1; index <= numberOfIndicators(); index++) { + static_cast(indicatorAtIndex(index))->setBackgroundColor(c); } } From 571967088e4091aaa2380a662f9d42f4122c3578 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Thu, 14 Feb 2019 17:21:28 +0100 Subject: [PATCH 329/373] [escher/scroll_view] Uniformize scroll bars frame across Epsilon --- apps/home/controller.cpp | 1 - apps/home/controller.h | 1 - apps/shared/storage_values_controller.cpp | 1 - apps/shared/values_controller.cpp | 1 - escher/include/escher/scroll_view.h | 3 +-- escher/src/scroll_view.cpp | 7 +++---- 6 files changed, 4 insertions(+), 10 deletions(-) diff --git a/apps/home/controller.cpp b/apps/home/controller.cpp index f1b7bcefc..10f0075a5 100644 --- a/apps/home/controller.cpp +++ b/apps/home/controller.cpp @@ -12,7 +12,6 @@ Controller::ContentView::ContentView(Controller * controller, SelectableTableVie m_selectableTableView.setVerticalCellOverlap(0); m_selectableTableView.setMargins(0, k_sideMargin, k_bottomMargin, k_sideMargin); m_selectableTableView.setBackgroundColor(KDColorWhite); - static_cast(m_selectableTableView.decorator())->setBarsFrameBreadth(k_scrollBarsFrameBreadth); static_cast(m_selectableTableView.decorator())->verticalBar()->setMargin(k_indicatorMargin); } diff --git a/apps/home/controller.h b/apps/home/controller.h index 679651b1a..ae3be69e5 100644 --- a/apps/home/controller.h +++ b/apps/home/controller.h @@ -43,7 +43,6 @@ private: AppsContainer * m_container; static constexpr KDCoordinate k_sideMargin = 4; static constexpr KDCoordinate k_bottomMargin = 14; - static constexpr KDCoordinate k_scrollBarsFrameBreadth = 15; static constexpr KDCoordinate k_indicatorMargin = 61; static constexpr int k_numberOfColumns = 3; static constexpr int k_maxNumberOfCells = 16; diff --git a/apps/shared/storage_values_controller.cpp b/apps/shared/storage_values_controller.cpp index cadc74dd4..d8946031d 100644 --- a/apps/shared/storage_values_controller.cpp +++ b/apps/shared/storage_values_controller.cpp @@ -32,7 +32,6 @@ StorageValuesController::StorageValuesController(Responder * parentResponder, In m_selectableTableView.setBottomMargin(k_bottomMargin); m_selectableTableView.setLeftMargin(k_leftMargin); m_selectableTableView.setBackgroundColor(Palette::WallScreenDark); - static_cast(m_selectableTableView.decorator())->setBarsFrameBreadth(13); m_abscissaTitleCell.setMessageFont(k_font); for (int i = 0; i < k_maxNumberOfAbscissaCells; i++) { m_abscissaCells[i].setParentResponder(&m_selectableTableView); diff --git a/apps/shared/values_controller.cpp b/apps/shared/values_controller.cpp index d19e77dd6..5d8091cb9 100644 --- a/apps/shared/values_controller.cpp +++ b/apps/shared/values_controller.cpp @@ -32,7 +32,6 @@ ValuesController::ValuesController(Responder * parentResponder, InputEventHandle m_selectableTableView.setBottomMargin(k_bottomMargin); m_selectableTableView.setLeftMargin(k_leftMargin); m_selectableTableView.setBackgroundColor(Palette::WallScreenDark); - static_cast(m_selectableTableView.decorator())->setBarsFrameBreadth(13); m_abscissaTitleCell.setMessageFont(KDFont::SmallFont); for (int i = 0; i < k_maxNumberOfAbscissaCells; i++) { m_abscissaCells[i].setParentResponder(&m_selectableTableView); diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index 8fd79e7d6..78cc1c70d 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -50,11 +50,10 @@ public: KDRect layoutIndicators(KDSize content, KDPoint offset, KDRect frame) override; ScrollViewVerticalBar * verticalBar() { return &m_verticalBar; } ScrollViewHorizontalBar * horizontalBar() { return &m_horizontalBar; } - void setBarsFrameBreadth(KDCoordinate t) { m_barsFrameBreadth = t; } private: ScrollViewVerticalBar m_verticalBar; ScrollViewHorizontalBar m_horizontalBar; - KDCoordinate m_barsFrameBreadth; + static constexpr KDCoordinate k_barsFrameBreadth = 13; }; class ArrowDecorator : public Decorator { diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index 832ac6f4c..681273fdc 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -125,8 +125,7 @@ void ScrollView::InnerView::drawRect(KDContext * ctx, KDRect rect) const { ScrollView::BarDecorator::BarDecorator() : m_verticalBar(), - m_horizontalBar(), - m_barsFrameBreadth(20) + m_horizontalBar() { } @@ -141,12 +140,12 @@ View * ScrollView::BarDecorator::indicatorAtIndex(int index) { } KDRect ScrollView::BarDecorator::layoutIndicators(KDSize content, KDPoint offset, KDRect frame) { - KDCoordinate hBarFrameBreadth = m_barsFrameBreadth * m_horizontalBar.update( + KDCoordinate hBarFrameBreadth = k_barsFrameBreadth * m_horizontalBar.update( content.width(), offset.x(), frame.width() ); - KDCoordinate vBarFrameBreadth = m_barsFrameBreadth * m_verticalBar.update( + KDCoordinate vBarFrameBreadth = k_barsFrameBreadth * m_verticalBar.update( content.height(), offset.y(), frame.height() From 0943406263b05bae36c79254e67719993de01b82 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Fri, 15 Feb 2019 11:49:20 +0100 Subject: [PATCH 330/373] Fix HistoryViewCell and ScrollableExactApproximateExxpressionsCell margins issue Remove all margins from those cells. Rather add margins to their respective subviews: - ScrollableExpressionView - ScrollableExactApproximateExpressionsView. As a notable consequence, the distance in HistoryViewCell between its subviews becomes 10 instead of 5. In passing, replace - Metric::HistoryHorizontalMargin = 10 - ScrollableExactApproximateExpressionsView::k_digitHorizontalMargin = 10 - HistoryViewCell::k_digitVerticalMargin = 5 - ScrollableExactApproximateExpressionsCell::k_margin = 5 by - Metric::CommonSmallMargin = 5 - Metric::CommonLargeMargin = 10. --- apps/calculation/history_controller.cpp | 2 +- apps/calculation/history_view_cell.cpp | 6 +++--- apps/calculation/history_view_cell.h | 1 - apps/calculation/scrollable_expression_view.cpp | 7 ++++++- apps/code/script_name_cell.h | 2 +- ...crollable_exact_approximate_expressions_cell.cpp | 2 +- .../scrollable_exact_approximate_expressions_cell.h | 1 - ...crollable_exact_approximate_expressions_view.cpp | 13 +++++++++---- .../scrollable_exact_approximate_expressions_view.h | 1 - apps/solver/solutions_controller.cpp | 2 +- escher/include/escher/metric.h | 3 ++- 11 files changed, 24 insertions(+), 16 deletions(-) diff --git a/apps/calculation/history_controller.cpp b/apps/calculation/history_controller.cpp index 741304ac0..ba3ec25cd 100644 --- a/apps/calculation/history_controller.cpp +++ b/apps/calculation/history_controller.cpp @@ -150,7 +150,7 @@ KDCoordinate HistoryController::rowHeight(int j) { } Calculation * calculation = m_calculationStore->calculationAtIndex(j); App * calculationApp = (App *)app(); - return calculation->height(calculationApp->localContext()) + 3*HistoryViewCell::k_digitVerticalMargin; + return calculation->height(calculationApp->localContext()) + 4 * Metric::CommonSmallMargin; } int HistoryController::typeAtLocation(int i, int j) { diff --git a/apps/calculation/history_view_cell.cpp b/apps/calculation/history_view_cell.cpp index d51413654..ff9cb69a4 100644 --- a/apps/calculation/history_view_cell.cpp +++ b/apps/calculation/history_view_cell.cpp @@ -98,16 +98,16 @@ void HistoryViewCell::layoutSubviews() { KDSize inputSize = m_inputView.minimalSizeForOptimalDisplay(); m_inputView.setFrame(KDRect( 0, - k_digitVerticalMargin, + 0, min(maxFrameWidth, inputSize.width()), inputSize.height() )); KDSize outputSize = m_scrollableOutputView.minimalSizeForOptimalDisplay(); m_scrollableOutputView.setFrame(KDRect( max(0, maxFrameWidth - outputSize.width()), - inputSize.height() + 2*k_digitVerticalMargin, + inputSize.height(), min(maxFrameWidth, outputSize.width()), - bounds().height() - inputSize.height() - 3*k_digitVerticalMargin + bounds().height() - inputSize.height() )); } diff --git a/apps/calculation/history_view_cell.h b/apps/calculation/history_view_cell.h index c3c99fc97..55053d6dc 100644 --- a/apps/calculation/history_view_cell.h +++ b/apps/calculation/history_view_cell.h @@ -42,7 +42,6 @@ public: void layoutSubviews() override; void didBecomeFirstResponder() override; bool handleEvent(Ion::Events::Event event) override; - constexpr static KDCoordinate k_digitVerticalMargin = 5; Shared::ScrollableExactApproximateExpressionsView * outputView(); private: constexpr static KDCoordinate k_resultWidth = 80; diff --git a/apps/calculation/scrollable_expression_view.cpp b/apps/calculation/scrollable_expression_view.cpp index 68e150883..4860699ad 100644 --- a/apps/calculation/scrollable_expression_view.cpp +++ b/apps/calculation/scrollable_expression_view.cpp @@ -9,7 +9,12 @@ ScrollableExpressionView::ScrollableExpressionView(Responder * parentResponder) m_expressionView() { setDecoratorType(ScrollView::Decorator::Type::Arrows); - setMargins(0, Metric::HistoryHorizontalMargin, 0, Metric::HistoryHorizontalMargin); + setMargins( + Metric::CommonSmallMargin, + Metric::CommonLargeMargin, + Metric::CommonSmallMargin, + Metric::CommonLargeMargin + ); } void ScrollableExpressionView::setLayout(Layout layout) { diff --git a/apps/code/script_name_cell.h b/apps/code/script_name_cell.h index 08719b3f7..914432114 100644 --- a/apps/code/script_name_cell.h +++ b/apps/code/script_name_cell.h @@ -38,7 +38,7 @@ public: private: constexpr static size_t k_extensionLength = 1+ScriptStore::k_scriptExtensionLength; // '.' + "py" - constexpr static KDCoordinate k_leftMargin = Metric::HistoryHorizontalMargin; + constexpr static KDCoordinate k_leftMargin = Metric::CommonLargeMargin; // View int numberOfSubviews() const override { return 1; } diff --git a/apps/shared/scrollable_exact_approximate_expressions_cell.cpp b/apps/shared/scrollable_exact_approximate_expressions_cell.cpp index b590b3381..5dd92de68 100644 --- a/apps/shared/scrollable_exact_approximate_expressions_cell.cpp +++ b/apps/shared/scrollable_exact_approximate_expressions_cell.cpp @@ -41,7 +41,7 @@ View * ScrollableExactApproximateExpressionsCell::subviewAtIndex(int index) { } void ScrollableExactApproximateExpressionsCell::layoutSubviews() { - m_view.setFrame(KDRect(k_margin,k_margin, bounds().width()-2*k_margin, bounds().height()-2*k_margin)); + m_view.setFrame(bounds()); } } diff --git a/apps/shared/scrollable_exact_approximate_expressions_cell.h b/apps/shared/scrollable_exact_approximate_expressions_cell.h index f74f77091..3d8a8209f 100644 --- a/apps/shared/scrollable_exact_approximate_expressions_cell.h +++ b/apps/shared/scrollable_exact_approximate_expressions_cell.h @@ -24,7 +24,6 @@ public: } Poincare::Layout layout() const override { return m_view.layout(); } void didBecomeFirstResponder() override; - constexpr static KDCoordinate k_margin = 5; private: int numberOfSubviews() const override; View * subviewAtIndex(int index) override; diff --git a/apps/shared/scrollable_exact_approximate_expressions_view.cpp b/apps/shared/scrollable_exact_approximate_expressions_view.cpp index 75e349b2d..3b286e6b1 100644 --- a/apps/shared/scrollable_exact_approximate_expressions_view.cpp +++ b/apps/shared/scrollable_exact_approximate_expressions_view.cpp @@ -53,7 +53,7 @@ KDSize ScrollableExactApproximateExpressionsView::ContentCell::minimalSizeForOpt KDCoordinate rightBaseline = m_rightExpressionView.layout().baseline(); KDCoordinate height = max(leftBaseline, rightBaseline) + max(leftExpressionSize.height()-leftBaseline, rightExpressionSize.height()-rightBaseline); KDSize approximateSignSize = m_approximateSign.minimalSizeForOptimalDisplay(); - return KDSize(leftExpressionSize.width()+approximateSignSize.width()+rightExpressionSize.width()+2*k_digitHorizontalMargin, height); + return KDSize(leftExpressionSize.width()+approximateSignSize.width()+rightExpressionSize.width()+2*Metric::CommonLargeMargin, height); } void ScrollableExactApproximateExpressionsView::ContentCell::setSelectedSubviewPosition(ScrollableExactApproximateExpressionsView::SubviewPosition subviewPosition) { @@ -94,8 +94,8 @@ void ScrollableExactApproximateExpressionsView::ContentCell::layoutSubviews() { KDSize leftExpressionSize = m_leftExpressionView.minimalSizeForOptimalDisplay(); KDSize approximateSignSize = m_approximateSign.minimalSizeForOptimalDisplay(); m_leftExpressionView.setFrame(KDRect(0, baseline-leftBaseline, leftExpressionSize)); - m_rightExpressionView.setFrame(KDRect(2*k_digitHorizontalMargin+leftExpressionSize.width()+approximateSignSize.width(), baseline-rightBaseline, rightExpressionSize)); - m_approximateSign.setFrame(KDRect(k_digitHorizontalMargin+leftExpressionSize.width(), baseline-approximateSignSize.height()/2, approximateSignSize)); + m_rightExpressionView.setFrame(KDRect(2*Metric::CommonLargeMargin+leftExpressionSize.width()+approximateSignSize.width(), baseline-rightBaseline, rightExpressionSize)); + m_approximateSign.setFrame(KDRect(Metric::CommonLargeMargin+leftExpressionSize.width(), baseline-approximateSignSize.height()/2, approximateSignSize)); } ScrollableExactApproximateExpressionsView::ScrollableExactApproximateExpressionsView(Responder * parentResponder) : @@ -103,7 +103,12 @@ ScrollableExactApproximateExpressionsView::ScrollableExactApproximateExpressions m_contentCell() { setDecoratorType(ScrollView::Decorator::Type::Arrows); - setMargins(0, Metric::HistoryHorizontalMargin, 0, Metric::HistoryHorizontalMargin); + setMargins( + Metric::CommonSmallMargin, + Metric::CommonLargeMargin, + Metric::CommonSmallMargin, + Metric::CommonLargeMargin + ); } void ScrollableExactApproximateExpressionsView::setLayouts(Poincare::Layout rightLayout, Poincare::Layout leftLayout) { diff --git a/apps/shared/scrollable_exact_approximate_expressions_view.h b/apps/shared/scrollable_exact_approximate_expressions_view.h index 3b4972edb..38a35357e 100644 --- a/apps/shared/scrollable_exact_approximate_expressions_view.h +++ b/apps/shared/scrollable_exact_approximate_expressions_view.h @@ -54,7 +54,6 @@ private: Poincare::Layout layout() const override; private: View * subviewAtIndex(int index) override; - constexpr static KDCoordinate k_digitHorizontalMargin = 10; ExpressionView m_rightExpressionView; MessageTextView m_approximateSign; ExpressionView m_leftExpressionView; diff --git a/apps/solver/solutions_controller.cpp b/apps/solver/solutions_controller.cpp index 90e780373..3cf912611 100644 --- a/apps/solver/solutions_controller.cpp +++ b/apps/solver/solutions_controller.cpp @@ -220,7 +220,7 @@ KDCoordinate SolutionsController::rowHeight(int j) { KDCoordinate exactLayoutHeight = exactLayout.layoutSize().height(); KDCoordinate approximateLayoutHeight = approximateLayout.layoutSize().height(); KDCoordinate layoutHeight = max(exactLayout.baseline(), approximateLayout.baseline()) + max(exactLayoutHeight-exactLayout.baseline(), approximateLayoutHeight-approximateLayout.baseline()); - return layoutHeight+ScrollableExactApproximateExpressionsCell::k_margin*2; + return layoutHeight + 2 * Metric::CommonSmallMargin; } KDCoordinate SolutionsController::cumulatedWidthFromIndex(int i) { diff --git a/escher/include/escher/metric.h b/escher/include/escher/metric.h index 5294e9e46..265b69d8a 100644 --- a/escher/include/escher/metric.h +++ b/escher/include/escher/metric.h @@ -9,7 +9,8 @@ public: constexpr static KDCoordinate CommonRightMargin = 20; constexpr static KDCoordinate CommonTopMargin = 15; constexpr static KDCoordinate CommonBottomMargin = 15; - constexpr static KDCoordinate HistoryHorizontalMargin = 10; + constexpr static KDCoordinate CommonLargeMargin = 10; + constexpr static KDCoordinate CommonSmallMargin = 5; constexpr static KDCoordinate TitleBarExternHorizontalMargin = 5; constexpr static KDCoordinate TitleBarHeight = 18; constexpr static KDCoordinate ParameterCellHeight = 35; From 3d254b9ef16af88f61a6a4180ede0c8daa977958 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Fri, 15 Feb 2019 13:33:16 +0100 Subject: [PATCH 331/373] [apps/shared/scrollable_exact_approximate_expressions_cell] Fix background --- apps/shared/scrollable_exact_approximate_expressions_cell.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/shared/scrollable_exact_approximate_expressions_cell.cpp b/apps/shared/scrollable_exact_approximate_expressions_cell.cpp index 5dd92de68..e9c456b75 100644 --- a/apps/shared/scrollable_exact_approximate_expressions_cell.cpp +++ b/apps/shared/scrollable_exact_approximate_expressions_cell.cpp @@ -17,6 +17,7 @@ void ScrollableExactApproximateExpressionsCell::setHighlighted(bool highlight) { void ScrollableExactApproximateExpressionsCell::setEven(bool even) { EvenOddCell::setEven(even); + m_view.setBackgroundColor(backgroundColor()); m_view.evenOddCell()->setEven(even); } From 9ea63678e16fc2b2423b09bf240da07352aa8ced Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Fri, 15 Feb 2019 13:45:09 +0100 Subject: [PATCH 332/373] [escher] Inline ScrollView::setCommonMargins --- escher/include/escher/scroll_view.h | 1 - escher/src/scroll_view.cpp | 7 ------- escher/src/selectable_table_view.cpp | 8 +++++++- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index 78cc1c70d..90555ff67 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -24,7 +24,6 @@ public: setTopMargin(top); setRightMargin(right); setBottomMargin(bottom); setLeftMargin(left); } void setMargins(KDCoordinate m) { setMargins(m, m, m, m); } - void setCommonMargins(); class Decorator { public: diff --git a/escher/src/scroll_view.cpp b/escher/src/scroll_view.cpp index 681273fdc..75d07ec11 100644 --- a/escher/src/scroll_view.cpp +++ b/escher/src/scroll_view.cpp @@ -1,6 +1,5 @@ #include #include -#include #include @@ -45,12 +44,6 @@ KDSize ScrollView::minimalSizeForOptimalDisplay() const { ); } -void ScrollView::setCommonMargins() { - setTopMargin(Metric::CommonTopMargin); - setRightMargin(Metric::CommonRightMargin); - setBottomMargin(Metric::CommonBottomMargin); - setLeftMargin(Metric::CommonLeftMargin); -} void ScrollView::scrollToContentPoint(KDPoint p, bool allowOverscroll) { if (!allowOverscroll && !m_contentView->bounds().contains(p)) { diff --git a/escher/src/selectable_table_view.cpp b/escher/src/selectable_table_view.cpp index 05c003d3b..9924a9cd7 100644 --- a/escher/src/selectable_table_view.cpp +++ b/escher/src/selectable_table_view.cpp @@ -1,5 +1,6 @@ #include #include +#include #include SelectableTableView::SelectableTableView(Responder * parentResponder, TableViewDataSource * dataSource, SelectableTableViewDataSource * selectionDataSource, SelectableTableViewDelegate * delegate) : @@ -8,8 +9,13 @@ SelectableTableView::SelectableTableView(Responder * parentResponder, TableViewD m_selectionDataSource(selectionDataSource), m_delegate(delegate) { - setCommonMargins(); assert(m_selectionDataSource != nullptr); + setMargins( + Metric::CommonTopMargin, + Metric::CommonRightMargin, + Metric::CommonBottomMargin, + Metric::CommonLeftMargin + ); } int SelectableTableView::selectedRow() { From 1ac829ca18832645be19966d27dc32f31aa27f67 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Mon, 18 Feb 2019 12:02:15 +0100 Subject: [PATCH 333/373] [escher/scroll_view_indicator] Fix rounding issues for bars --- escher/src/scroll_view_indicator.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/escher/src/scroll_view_indicator.cpp b/escher/src/scroll_view_indicator.cpp index 6786566ca..4e1eb3dec 100644 --- a/escher/src/scroll_view_indicator.cpp +++ b/escher/src/scroll_view_indicator.cpp @@ -3,6 +3,7 @@ extern "C" { #include } +#include ScrollViewIndicator::ScrollViewIndicator() : View(), @@ -46,7 +47,7 @@ void ScrollViewHorizontalBar::drawRect(KDContext * ctx, KDRect rect) const { ctx->fillRect( KDRect( m_margin+m_offset*totalLength(), (m_frame.height() - k_indicatorThickness)/2, - m_visibleLength*totalLength(), k_indicatorThickness + std::ceil(m_visibleLength*totalLength()), k_indicatorThickness ), m_color ); @@ -66,7 +67,7 @@ void ScrollViewVerticalBar::drawRect(KDContext * ctx, KDRect rect) const { ctx->fillRect( KDRect( (m_frame.width() - k_indicatorThickness)/2, m_margin+m_offset*totalLength(), - k_indicatorThickness, m_visibleLength*totalLength() + k_indicatorThickness, std::ceil(m_visibleLength*totalLength()) ), m_color ); From b5dc7f738eb77fdf41c9d508c96a3ca7719ee466 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Mon, 18 Feb 2019 15:10:38 +0100 Subject: [PATCH 334/373] [escher/table_view] scrollToCell includes CellOverlap In passing, factorize duplicate code. --- escher/include/escher/table_view.h | 2 +- escher/src/table_view.cpp | 22 +++++++++------------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/escher/include/escher/table_view.h b/escher/include/escher/table_view.h index 7fde8754c..ca2db0d32 100644 --- a/escher/include/escher/table_view.h +++ b/escher/include/escher/table_view.h @@ -56,7 +56,7 @@ protected: /* realCellWidth enables to handle list view for which * TableViewDataSource->cellWidht = 0 */ - KDCoordinate columnWidth(int x) const; + KDRect cellFrame(int i, int j) const; /* These two methods transform an index (of subview for instance) into * coordinates that refer to the data source entire table */ int absoluteColumnNumberFromSubviewIndex(int index) const; diff --git a/escher/src/table_view.cpp b/escher/src/table_view.cpp index adb859b8d..08b2859da 100644 --- a/escher/src/table_view.cpp +++ b/escher/src/table_view.cpp @@ -73,10 +73,14 @@ TableViewDataSource * TableView::ContentView::dataSource() { return m_dataSource; } -KDCoordinate TableView::ContentView::columnWidth(int i) const { - int columnWidth = m_dataSource->columnWidth(i); +KDRect TableView::ContentView::cellFrame(int i, int j) const { + KDCoordinate columnWidth = m_dataSource->columnWidth(i); columnWidth = columnWidth ? columnWidth : m_tableView->maxContentWidthDisplayableWithoutScrolling(); - return columnWidth; + return KDRect( + m_dataSource->cumulatedWidthFromIndex(i), m_dataSource->cumulatedHeightFromIndex(j), + columnWidth + m_horizontalCellOverlap, + m_dataSource->rowHeight(j) + m_verticalCellOverlap + ); } KDCoordinate TableView::ContentView::height() const { @@ -90,8 +94,7 @@ KDCoordinate TableView::ContentView::width() const { } void TableView::ContentView::scrollToCell(int x, int y) const { - KDRect cellRect = KDRect(m_dataSource->cumulatedWidthFromIndex(x), m_dataSource->cumulatedHeightFromIndex(y), columnWidth(x), m_dataSource->rowHeight(y)); - m_tableView->scrollToContentRect(cellRect, true); + m_tableView->scrollToContentRect(cellFrame(x, y), true); } void TableView::ContentView::reloadCellAtLocation(int i, int j) { @@ -172,14 +175,7 @@ void TableView::ContentView::layoutSubviews() { int i = absoluteColumnNumberFromSubviewIndex(index); int j = absoluteRowNumberFromSubviewIndex(index); m_dataSource->willDisplayCellAtLocation((HighlightCell *)cell, i, j); - - KDCoordinate rowHeight = m_dataSource->rowHeight(j); - KDCoordinate columnWidth = this->columnWidth(i); - KDCoordinate verticalOffset = m_dataSource->cumulatedHeightFromIndex(j); - KDCoordinate horizontalOffset = m_dataSource->cumulatedWidthFromIndex(i); - KDRect cellFrame(horizontalOffset, verticalOffset, - columnWidth+m_horizontalCellOverlap, rowHeight+m_verticalCellOverlap); - cell->setFrame(cellFrame); + cell->setFrame(cellFrame(i,j)); } } From b3d15d7e7fc09964e942982b401fe138eff29f02 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Mon, 18 Feb 2019 15:50:14 +0100 Subject: [PATCH 335/373] [escher/table_view] layoutSubviews of m_contentView first --- escher/src/table_view.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/escher/src/table_view.cpp b/escher/src/table_view.cpp index 08b2859da..ed0ae9c7c 100644 --- a/escher/src/table_view.cpp +++ b/escher/src/table_view.cpp @@ -34,10 +34,7 @@ const char * TableView::className() const { #endif void TableView::layoutSubviews() { - ScrollView::layoutSubviews(); - m_contentView.layoutSubviews(); - /* FIXME: - * On the one hand, ScrollView::layoutSubviews() + /* On the one hand, ScrollView::layoutSubviews() * calls setFrame(...) over m_contentView, * which typically calls layoutSubviews() over m_contentView. * However, if the frame happens to be unchanged, @@ -46,8 +43,14 @@ void TableView::layoutSubviews() { * does not relayout ScrollView when the offset * or the content's size changes. * For those reasons, we call both of them explicitly. + * Besides, one must call layoutSubviews() over + * m_contentView first, in order to reload the table's data, + * otherwise the table's size might be miscomputed... + * FIXME: * Finally, this solution is not optimal at all since * layoutSubviews is called twice over m_contentView. */ + m_contentView.layoutSubviews(); + ScrollView::layoutSubviews(); } void TableView::reloadCellAtLocation(int i, int j) { From ac6f23684d760787191b60353311e17070959b41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 28 Jan 2019 17:44:08 +0100 Subject: [PATCH 336/373] [poincare] Clean Expression and Layout builders Before: Opposite(Opposite(Rational(1))) misleadingly created the expression "-1"; now, Opposite::Builder(Opposite::Builder(Rational(1))) creates "--1" --- apps/regression/calculation_controller.cpp | 2 +- apps/regression/model/cubic_model.cpp | 18 +- apps/regression/model/exponential_model.cpp | 6 +- apps/regression/model/linear_model.cpp | 2 +- apps/regression/model/logarithmic_model.cpp | 2 +- apps/regression/model/logistic_model.cpp | 8 +- apps/regression/model/power_model.cpp | 4 +- apps/regression/model/quadratic_model.cpp | 12 +- apps/regression/model/quartic_model.cpp | 24 +-- apps/regression/model/trigonometric_model.cpp | 10 +- apps/sequence/graph/term_sum_controller.cpp | 4 +- apps/sequence/list/sequence_toolbox.cpp | 12 +- .../list/type_parameter_controller.cpp | 4 +- apps/sequence/sequence.cpp | 24 +-- .../sub_menu/preferences_controller.cpp | 10 +- apps/shared/storage_expression_model.cpp | 2 +- apps/shared/storage_sum_graph_controller.cpp | 6 +- apps/shared/sum_graph_controller.cpp | 6 +- apps/solver/equation_store.cpp | 48 ++--- apps/solver/solutions_controller.cpp | 2 +- escher/src/layout_field.cpp | 2 +- .../include/poincare/absolute_value_layout.h | 2 + poincare/include/poincare/addition.h | 20 +-- poincare/include/poincare/array_builder.h | 20 +++ .../poincare/binomial_coefficient_layout.h | 3 + poincare/include/poincare/ceiling_layout.h | 2 + .../include/poincare/condensed_sum_layout.h | 10 +- poincare/include/poincare/conjugate_layout.h | 2 + poincare/include/poincare/division.h | 15 +- poincare/include/poincare/factorial.h | 9 +- poincare/include/poincare/floor_layout.h | 2 + poincare/include/poincare/fraction_layout.h | 9 +- poincare/include/poincare/ghost.h | 2 + poincare/include/poincare/grid_layout.h | 3 +- poincare/include/poincare/horizontal_layout.h | 23 ++- poincare/include/poincare/integral_layout.h | 2 + .../poincare/left_parenthesis_layout.h | 4 +- .../poincare/left_square_bracket_layout.h | 4 +- poincare/include/poincare/matrix.h | 11 +- poincare/include/poincare/matrix_layout.h | 16 +- poincare/include/poincare/multiplication.h | 23 +-- poincare/include/poincare/nth_root_layout.h | 13 +- poincare/include/poincare/opposite.h | 10 +- poincare/include/poincare/parenthesis.h | 7 +- poincare/include/poincare/power.h | 9 +- poincare/include/poincare/product_layout.h | 2 + .../poincare/right_parenthesis_layout.h | 4 +- .../poincare/right_square_bracket_layout.h | 5 +- poincare/include/poincare/store.h | 10 +- poincare/include/poincare/subtraction.h | 13 +- poincare/include/poincare/sum_layout.h | 2 + .../include/poincare/vertical_offset_layout.h | 10 +- poincare/src/absolute_value.cpp | 4 +- poincare/src/addition.cpp | 21 ++- poincare/src/binomial_coefficient.cpp | 2 +- poincare/src/ceiling.cpp | 2 +- poincare/src/complex_cartesian.cpp | 78 ++++---- poincare/src/condensed_sum_layout.cpp | 10 +- poincare/src/confidence_interval.cpp | 8 +- poincare/src/conjugate.cpp | 4 +- poincare/src/decimal.cpp | 2 +- poincare/src/division.cpp | 10 +- poincare/src/equal.cpp | 4 +- poincare/src/expression.cpp | 24 +-- poincare/src/factor.cpp | 8 +- poincare/src/factorial.cpp | 6 +- poincare/src/floor.cpp | 2 +- poincare/src/fraction_layout.cpp | 9 +- poincare/src/function.cpp | 2 +- poincare/src/horizontal_layout.cpp | 29 +-- poincare/src/integral.cpp | 2 +- poincare/src/layout.cpp | 6 +- poincare/src/layout_cursor.cpp | 30 ++-- poincare/src/layout_helper.cpp | 16 +- poincare/src/left_parenthesis_layout.cpp | 2 - poincare/src/left_square_bracket_layout.cpp | 2 - poincare/src/logarithm.cpp | 12 +- poincare/src/matrix.cpp | 8 +- poincare/src/matrix_complex.cpp | 2 +- poincare/src/matrix_dimension.cpp | 6 +- poincare/src/matrix_inverse.cpp | 4 +- poincare/src/matrix_layout.cpp | 12 -- poincare/src/multiplication.cpp | 48 +++-- poincare/src/nth_root.cpp | 6 +- poincare/src/nth_root_layout.cpp | 12 -- poincare/src/opposite.cpp | 6 +- poincare/src/parsing/parser.cpp | 30 ++-- poincare/src/power.cpp | 98 +++++----- poincare/src/prediction_interval.cpp | 10 +- poincare/src/product.cpp | 2 +- poincare/src/rational.cpp | 4 +- poincare/src/right_parenthesis_layout.cpp | 2 - poincare/src/right_square_bracket_layout.cpp | 2 - poincare/src/sign_function.cpp | 2 +- poincare/src/simplification_helper.cpp | 2 +- poincare/src/square_root.cpp | 4 +- poincare/src/store.cpp | 2 +- poincare/src/subtraction.cpp | 6 +- poincare/src/sum.cpp | 2 +- poincare/src/symbol.cpp | 18 +- poincare/src/tangent.cpp | 2 +- poincare/src/tree_handle.cpp | 2 +- poincare/src/trigonometry.cpp | 30 ++-- poincare/src/vertical_offset_layout.cpp | 11 +- poincare/test/addition.cpp | 6 +- poincare/test/expression_order.cpp | 60 +++---- poincare/test/fraction_layout.cpp | 10 +- poincare/test/layouts.cpp | 142 ++++++++------- poincare/test/parentheses_layout.cpp | 12 +- poincare/test/parser.cpp | 167 +++++++++--------- poincare/test/properties.cpp | 14 +- poincare/test/user_variable.cpp | 4 +- poincare/test/vertical_offset_layout.cpp | 4 +- 113 files changed, 779 insertions(+), 743 deletions(-) create mode 100644 poincare/include/poincare/array_builder.h diff --git a/apps/regression/calculation_controller.cpp b/apps/regression/calculation_controller.cpp index 39f0458d9..3b21ba53f 100644 --- a/apps/regression/calculation_controller.cpp +++ b/apps/regression/calculation_controller.cpp @@ -25,7 +25,7 @@ CalculationController::CalculationController(Responder * parentResponder, Button m_hideableCell(), m_store(store) { - m_r2Layout = HorizontalLayout(CharLayout('r', KDFont::SmallFont), VerticalOffsetLayout(CharLayout('2', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Superscript)); + m_r2Layout = HorizontalLayout::Builder(CharLayout('r', KDFont::SmallFont), VerticalOffsetLayout::Builder(CharLayout('2', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Superscript)); m_selectableTableView.setVerticalCellOverlap(0); m_selectableTableView.setBackgroundColor(Palette::WallScreenDark); m_selectableTableView.setMargins(k_margin, k_scrollBarMargin, k_scrollBarMargin, k_margin); diff --git a/apps/regression/model/cubic_model.cpp b/apps/regression/model/cubic_model.cpp index bac69876d..1452ccf53 100644 --- a/apps/regression/model/cubic_model.cpp +++ b/apps/regression/model/cubic_model.cpp @@ -23,7 +23,7 @@ Layout CubicModel::layout() { CharLayout('a', KDFont::SmallFont), CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), CharLayout('X', KDFont::SmallFont), - VerticalOffsetLayout( + VerticalOffsetLayout::Builder( CharLayout('3', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Superscript ), @@ -31,7 +31,7 @@ Layout CubicModel::layout() { CharLayout('b', KDFont::SmallFont), CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), CharLayout('X', KDFont::SmallFont), - VerticalOffsetLayout( + VerticalOffsetLayout::Builder( CharLayout('2', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Superscript ), @@ -42,7 +42,7 @@ Layout CubicModel::layout() { CharLayout('+', KDFont::SmallFont), CharLayout('d', KDFont::SmallFont), }; - m_layout = HorizontalLayout(layoutChildren, 15); + m_layout = HorizontalLayout::Builder(layoutChildren, 15); } return m_layout; } @@ -53,23 +53,23 @@ Expression CubicModel::simplifiedExpression(double * modelCoefficients, Poincare double c = modelCoefficients[2]; double d = modelCoefficients[3]; Expression addChildren[] = { - Multiplication( + Multiplication::Builder( Number::DecimalNumber(a), - Power( + Power::Builder( Symbol('x'), Decimal(3.0))), - Multiplication( + Multiplication::Builder( Number::DecimalNumber(b), - Power( + Power::Builder( Symbol('x'), Decimal(2.0))), - Multiplication( + Multiplication::Builder( Number::DecimalNumber(c), Symbol('x')), Number::DecimalNumber(d) }; // a*x^3+b*x^2+c*x+d - Expression result = Addition(addChildren, 4); + Expression result = Addition::Builder(addChildren, 4); PoincareHelpers::Simplify(&result, *context); return result; } diff --git a/apps/regression/model/exponential_model.cpp b/apps/regression/model/exponential_model.cpp index fb7522802..e7097bcf8 100644 --- a/apps/regression/model/exponential_model.cpp +++ b/apps/regression/model/exponential_model.cpp @@ -15,8 +15,8 @@ Layout ExponentialModel::layout() { CharLayout('a', KDFont::SmallFont), CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), CharLayout('e', KDFont::SmallFont), - VerticalOffsetLayout( - HorizontalLayout( + VerticalOffsetLayout::Builder( + HorizontalLayout::Builder( CharLayout('b', KDFont::SmallFont), CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), CharLayout('X', KDFont::SmallFont) @@ -24,7 +24,7 @@ Layout ExponentialModel::layout() { VerticalOffsetLayoutNode::Type::Superscript ) }; - m_layout = HorizontalLayout(layoutChildren, 4); + m_layout = HorizontalLayout::Builder(layoutChildren, 4); } return m_layout; } diff --git a/apps/regression/model/linear_model.cpp b/apps/regression/model/linear_model.cpp index 42fb203ec..11992808c 100644 --- a/apps/regression/model/linear_model.cpp +++ b/apps/regression/model/linear_model.cpp @@ -18,7 +18,7 @@ Layout LinearModel::layout() { CharLayout('+', KDFont::SmallFont), CharLayout('b', KDFont::SmallFont), }; - m_layout = HorizontalLayout(layoutChildren, 5); + m_layout = HorizontalLayout::Builder(layoutChildren, 5); } return m_layout; } diff --git a/apps/regression/model/logarithmic_model.cpp b/apps/regression/model/logarithmic_model.cpp index fa1930d4a..546f434ea 100644 --- a/apps/regression/model/logarithmic_model.cpp +++ b/apps/regression/model/logarithmic_model.cpp @@ -22,7 +22,7 @@ Layout LogarithmicModel::layout() { CharLayout('+', KDFont::SmallFont), CharLayout('b', KDFont::SmallFont) }; - m_layout = HorizontalLayout(layoutChildren, 9); + m_layout = HorizontalLayout::Builder(layoutChildren, 9); } return m_layout; } diff --git a/apps/regression/model/logistic_model.cpp b/apps/regression/model/logistic_model.cpp index b7649dcc8..79b8d3bdc 100644 --- a/apps/regression/model/logistic_model.cpp +++ b/apps/regression/model/logistic_model.cpp @@ -24,14 +24,14 @@ Layout LogisticModel::layout() { CharLayout('a', KDFont::SmallFont), CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), CharLayout('e', KDFont::SmallFont), - VerticalOffsetLayout( - HorizontalLayout(exponentLayoutChildren, 4), + VerticalOffsetLayout::Builder( + HorizontalLayout::Builder(exponentLayoutChildren, 4), VerticalOffsetLayoutNode::Type::Superscript ) }; - m_layout = FractionLayout( + m_layout = FractionLayout::Builder( CharLayout('c', KDFont::SmallFont), - HorizontalLayout(layoutChildren, 6) + HorizontalLayout::Builder(layoutChildren, 6) ); } return m_layout; diff --git a/apps/regression/model/power_model.cpp b/apps/regression/model/power_model.cpp index 51ebdd6c2..9825d0afa 100644 --- a/apps/regression/model/power_model.cpp +++ b/apps/regression/model/power_model.cpp @@ -16,12 +16,12 @@ Layout PowerModel::layout() { CharLayout('a', KDFont::SmallFont), CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), CharLayout('X', KDFont::SmallFont), - VerticalOffsetLayout( + VerticalOffsetLayout::Builder( CharLayout('b', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Superscript ), }; - m_layout = HorizontalLayout(layoutChildren, 4); + m_layout = HorizontalLayout::Builder(layoutChildren, 4); } return m_layout; } diff --git a/apps/regression/model/quadratic_model.cpp b/apps/regression/model/quadratic_model.cpp index c1a3ca6ee..698680ba6 100644 --- a/apps/regression/model/quadratic_model.cpp +++ b/apps/regression/model/quadratic_model.cpp @@ -23,7 +23,7 @@ Layout QuadraticModel::layout() { CharLayout('a', KDFont::SmallFont), CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), CharLayout('X', KDFont::SmallFont), - VerticalOffsetLayout( + VerticalOffsetLayout::Builder( CharLayout('2', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Superscript ), @@ -34,7 +34,7 @@ Layout QuadraticModel::layout() { CharLayout('+', KDFont::SmallFont), CharLayout('c', KDFont::SmallFont), }; - m_layout = HorizontalLayout(layoutChildren, 10); + m_layout = HorizontalLayout::Builder(layoutChildren, 10); } return m_layout; } @@ -45,17 +45,17 @@ Expression QuadraticModel::simplifiedExpression(double * modelCoefficients, Poin double c = modelCoefficients[2]; // a*x^2+b*x+c Expression addChildren[] = { - Multiplication( + Multiplication::Builder( Number::DecimalNumber(a), - Power( + Power::Builder( Symbol('x'), Decimal(2.0))), - Multiplication( + Multiplication::Builder( Number::DecimalNumber(b), Symbol('x')), Number::DecimalNumber(c) }; - Expression result = Addition(addChildren, 3); + Expression result = Addition::Builder(addChildren, 3); PoincareHelpers::Simplify(&result, *context); return result; } diff --git a/apps/regression/model/quartic_model.cpp b/apps/regression/model/quartic_model.cpp index d2e012a39..3c7382fa8 100644 --- a/apps/regression/model/quartic_model.cpp +++ b/apps/regression/model/quartic_model.cpp @@ -23,7 +23,7 @@ Layout QuarticModel::layout() { CharLayout('a', KDFont::SmallFont), CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), CharLayout('X', KDFont::SmallFont), - VerticalOffsetLayout( + VerticalOffsetLayout::Builder( CharLayout('4', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Superscript ), @@ -31,7 +31,7 @@ Layout QuarticModel::layout() { CharLayout('b', KDFont::SmallFont), CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), CharLayout('X', KDFont::SmallFont), - VerticalOffsetLayout( + VerticalOffsetLayout::Builder( CharLayout('3', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Superscript ), @@ -39,7 +39,7 @@ Layout QuarticModel::layout() { CharLayout('c', KDFont::SmallFont), CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), CharLayout('X', KDFont::SmallFont), - VerticalOffsetLayout( + VerticalOffsetLayout::Builder( CharLayout('2', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Superscript ), @@ -50,7 +50,7 @@ Layout QuarticModel::layout() { CharLayout('+', KDFont::SmallFont), CharLayout('e', KDFont::SmallFont), }; - m_layout = HorizontalLayout(layoutChildren, 20); + m_layout = HorizontalLayout::Builder(layoutChildren, 20); } return m_layout; } @@ -63,31 +63,31 @@ Expression QuarticModel::simplifiedExpression(double * modelCoefficients, Poinca double e = modelCoefficients[4]; Expression addChildren[] = { // a*x^4 - Multiplication( + Multiplication::Builder( Number::DecimalNumber(a), - Power( + Power::Builder( Symbol('x'), Decimal(4.0))), // b*x^3 - Multiplication( + Multiplication::Builder( Number::DecimalNumber(b), - Power( + Power::Builder( Symbol('x'), Decimal(3.0))), // c*x^2 - Multiplication( + Multiplication::Builder( Number::DecimalNumber(c), - Power( + Power::Builder( Symbol('x'), Decimal(2.0))), // d*x - Multiplication( + Multiplication::Builder( Number::DecimalNumber(d), Symbol('x')), // e Number::DecimalNumber(e) }; - Expression result = Addition(addChildren, 5); + Expression result = Addition::Builder(addChildren, 5); PoincareHelpers::Simplify(&result, *context); return result; } diff --git a/apps/regression/model/trigonometric_model.cpp b/apps/regression/model/trigonometric_model.cpp index f7e5380ef..f1151036a 100644 --- a/apps/regression/model/trigonometric_model.cpp +++ b/apps/regression/model/trigonometric_model.cpp @@ -36,7 +36,7 @@ Layout TrigonometricModel::layout() { CharLayout('+', KDFont::SmallFont), CharLayout('d', KDFont::SmallFont) }; - m_layout = HorizontalLayout(layoutChildren, 14); + m_layout = HorizontalLayout::Builder(layoutChildren, 14); } return m_layout; } @@ -48,12 +48,12 @@ Expression TrigonometricModel::simplifiedExpression(double * modelCoefficients, double d = modelCoefficients[3]; // a*sin(bx+c)+d Expression result = - Addition( - Multiplication( + Addition::Builder( + Multiplication::Builder( Number::DecimalNumber(a), Sine::Builder( - Addition( - Multiplication( + Addition::Builder( + Multiplication::Builder( Number::DecimalNumber(b), Symbol('x')), Number::DecimalNumber(c)))), diff --git a/apps/sequence/graph/term_sum_controller.cpp b/apps/sequence/graph/term_sum_controller.cpp index 8a006eb24..033a0ce65 100644 --- a/apps/sequence/graph/term_sum_controller.cpp +++ b/apps/sequence/graph/term_sum_controller.cpp @@ -50,9 +50,9 @@ double TermSumController::cursorNextStep(double x, int direction) { } Layout TermSumController::createFunctionLayout(const char * functionName) { - return HorizontalLayout( + return HorizontalLayout::Builder( CharLayout(functionName[0], KDFont::SmallFont), - VerticalOffsetLayout( + VerticalOffsetLayout::Builder( CharLayout('n', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Subscript ) diff --git a/apps/sequence/list/sequence_toolbox.cpp b/apps/sequence/list/sequence_toolbox.cpp index e5797e160..ab0468c5c 100644 --- a/apps/sequence/list/sequence_toolbox.cpp +++ b/apps/sequence/list/sequence_toolbox.cpp @@ -76,20 +76,20 @@ void SequenceToolbox::buildExtraCellsLayouts(const char * sequenceName, int recu const char * otherSequenceName = SequenceStore::k_sequenceNames[1-sequenceIndex]; for (int j = 0; j < recurrenceDepth; j++) { const char * indice = j == 0 ? "n" : "n+1"; - m_addedCellLayout[j] = HorizontalLayout( + m_addedCellLayout[j] = HorizontalLayout::Builder( CharLayout(sequenceName[0], KDFont::LargeFont), - VerticalOffsetLayout(LayoutHelper::String(indice, strlen(indice), KDFont::LargeFont), VerticalOffsetLayoutNode::Type::Subscript) + VerticalOffsetLayout::Builder(LayoutHelper::String(indice, strlen(indice), KDFont::LargeFont), VerticalOffsetLayoutNode::Type::Subscript) ); - m_addedCellLayout[j+recurrenceDepth] = HorizontalLayout( + m_addedCellLayout[j+recurrenceDepth] = HorizontalLayout::Builder( CharLayout(otherSequenceName[0], KDFont::LargeFont), - VerticalOffsetLayout(LayoutHelper::String(indice, strlen(indice), KDFont::LargeFont), VerticalOffsetLayoutNode::Type::Subscript) + VerticalOffsetLayout::Builder(LayoutHelper::String(indice, strlen(indice), KDFont::LargeFont), VerticalOffsetLayoutNode::Type::Subscript) ); } if (recurrenceDepth < 2) { const char * indice = recurrenceDepth == 0 ? "n" : (recurrenceDepth == 1 ? "n+1" : "n+2"); - m_addedCellLayout[2*recurrenceDepth] = HorizontalLayout( + m_addedCellLayout[2*recurrenceDepth] = HorizontalLayout::Builder( CharLayout(otherSequenceName[0], KDFont::LargeFont), - VerticalOffsetLayout(LayoutHelper::String(indice, strlen(indice), KDFont::LargeFont), VerticalOffsetLayoutNode::Type::Subscript) + VerticalOffsetLayout::Builder(LayoutHelper::String(indice, strlen(indice), KDFont::LargeFont), VerticalOffsetLayoutNode::Type::Subscript) ); } } diff --git a/apps/sequence/list/type_parameter_controller.cpp b/apps/sequence/list/type_parameter_controller.cpp index 5ddcfd003..80ae5ec85 100644 --- a/apps/sequence/list/type_parameter_controller.cpp +++ b/apps/sequence/list/type_parameter_controller.cpp @@ -115,9 +115,9 @@ void TypeParameterController::willDisplayCellAtLocation(HighlightCell * cell, in font = KDFont::SmallFont; } const char * subscripts[3] = {"n", "n+1", "n+2"}; - m_layouts[j] = HorizontalLayout( + m_layouts[j] = HorizontalLayout::Builder( CharLayout(nextName[0], font), - VerticalOffsetLayout(LayoutHelper::String(subscripts[j], strlen(subscripts[j]), font), VerticalOffsetLayoutNode::Type::Subscript) + VerticalOffsetLayout::Builder(LayoutHelper::String(subscripts[j], strlen(subscripts[j]), font), VerticalOffsetLayoutNode::Type::Subscript) ); ExpressionTableCellWithPointer * myCell = (ExpressionTableCellWithPointer *)cell; myCell->setLayout(m_layouts[j]); diff --git a/apps/sequence/sequence.cpp b/apps/sequence/sequence.cpp index 04f3e652a..ff7555ee2 100644 --- a/apps/sequence/sequence.cpp +++ b/apps/sequence/sequence.cpp @@ -146,9 +146,9 @@ int Sequence::numberOfElements() { Poincare::Layout Sequence::nameLayout() { if (m_nameLayout.isUninitialized()) { - m_nameLayout = HorizontalLayout( + m_nameLayout = HorizontalLayout::Builder( CharLayout(name()[0], KDFont::SmallFont), - VerticalOffsetLayout(CharLayout('n', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Subscript) + VerticalOffsetLayout::Builder(CharLayout('n', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Subscript) ); } return m_nameLayout; @@ -157,18 +157,18 @@ Poincare::Layout Sequence::nameLayout() { Poincare::Layout Sequence::definitionName() { if (m_definitionName.isUninitialized()) { if (m_type == Type::Explicit) { - m_definitionName = HorizontalLayout( + m_definitionName = HorizontalLayout::Builder( CharLayout(name()[0], k_layoutFont), - VerticalOffsetLayout(LayoutHelper::String("n", 1, k_layoutFont), VerticalOffsetLayoutNode::Type::Subscript)); + VerticalOffsetLayout::Builder(LayoutHelper::String("n", 1, k_layoutFont), VerticalOffsetLayoutNode::Type::Subscript)); } else if (m_type == Type::SingleRecurrence) { - m_definitionName = HorizontalLayout( + m_definitionName = HorizontalLayout::Builder( CharLayout(name()[0], k_layoutFont), - VerticalOffsetLayout(LayoutHelper::String("n+1", 3, k_layoutFont), VerticalOffsetLayoutNode::Type::Subscript)); + VerticalOffsetLayout::Builder(LayoutHelper::String("n+1", 3, k_layoutFont), VerticalOffsetLayoutNode::Type::Subscript)); } else { assert(m_type == Type::DoubleRecurrence); - m_definitionName = HorizontalLayout( + m_definitionName = HorizontalLayout::Builder( CharLayout(name()[0], k_layoutFont), - VerticalOffsetLayout(LayoutHelper::String("n+2", 3, k_layoutFont), VerticalOffsetLayoutNode::Type::Subscript)); + VerticalOffsetLayout::Builder(LayoutHelper::String("n+2", 3, k_layoutFont), VerticalOffsetLayoutNode::Type::Subscript)); } } return m_definitionName; @@ -182,9 +182,9 @@ Poincare::Layout Sequence::firstInitialConditionName() { || m_type == Type::DoubleRecurrence)) { Layout indexLayout = LayoutHelper::String(buffer, strlen(buffer), k_layoutFont); - m_firstInitialConditionName = HorizontalLayout( + m_firstInitialConditionName = HorizontalLayout::Builder( CharLayout(name()[0], k_layoutFont), - VerticalOffsetLayout(indexLayout, VerticalOffsetLayoutNode::Type::Subscript)); + VerticalOffsetLayout::Builder(indexLayout, VerticalOffsetLayoutNode::Type::Subscript)); } return m_firstInitialConditionName; } @@ -195,9 +195,9 @@ Poincare::Layout Sequence::secondInitialConditionName() { if (m_secondInitialConditionName.isUninitialized()) { if (m_type == Type::DoubleRecurrence) { Layout indexLayout = LayoutHelper::String(buffer, strlen(buffer), k_layoutFont); - m_secondInitialConditionName = HorizontalLayout( + m_secondInitialConditionName = HorizontalLayout::Builder( CharLayout(name()[0], k_layoutFont), - VerticalOffsetLayout(indexLayout, VerticalOffsetLayoutNode::Type::Subscript)); + VerticalOffsetLayout::Builder(indexLayout, VerticalOffsetLayoutNode::Type::Subscript)); } } return m_secondInitialConditionName; diff --git a/apps/settings/sub_menu/preferences_controller.cpp b/apps/settings/sub_menu/preferences_controller.cpp index 9660b567a..ccc052317 100644 --- a/apps/settings/sub_menu/preferences_controller.cpp +++ b/apps/settings/sub_menu/preferences_controller.cpp @@ -60,7 +60,7 @@ Layout layoutForPreferences(I18n::Message message) { case I18n::Message::Radian: { const char pi[] = {Ion::Charset::SmallPi}; - return FractionLayout( + return FractionLayout::Builder( LayoutHelper::String(pi, sizeof(pi), KDFont::SmallFont), LayoutHelper::String("2", 1, KDFont::SmallFont) ); @@ -75,9 +75,9 @@ Layout layoutForPreferences(I18n::Message message) { } // Edition mode case I18n::Message::Edition2D: - return HorizontalLayout( + return HorizontalLayout::Builder( LayoutHelper::String("1+", 2, KDFont::SmallFont), - FractionLayout(LayoutHelper::String("2", 1, KDFont::SmallFont), LayoutHelper::String("3", 1, KDFont::SmallFont)) + FractionLayout::Builder(LayoutHelper::String("2", 1, KDFont::SmallFont), LayoutHelper::String("3", 1, KDFont::SmallFont)) ); case I18n::Message::EditionLinear: return LayoutHelper::String("1+2/3", 5, KDFont::SmallFont); @@ -95,9 +95,9 @@ Layout layoutForPreferences(I18n::Message message) { { const char base[] = {'r', Ion::Charset::Exponential}; const char superscript[] = {Ion::Charset::IComplex, Ion::Charset::SmallTheta}; - return HorizontalLayout( + return HorizontalLayout::Builder( LayoutHelper::String(base, sizeof(base), KDFont::SmallFont), - VerticalOffsetLayout(LayoutHelper::String(superscript, sizeof(superscript), KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Superscript) + VerticalOffsetLayout::Builder(LayoutHelper::String(superscript, sizeof(superscript), KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Superscript) ); } default: diff --git a/apps/shared/storage_expression_model.cpp b/apps/shared/storage_expression_model.cpp index 234875015..1a6aabf17 100644 --- a/apps/shared/storage_expression_model.cpp +++ b/apps/shared/storage_expression_model.cpp @@ -60,7 +60,7 @@ Layout StorageExpressionModel::layout() { if (m_layout.isUninitialized()) { m_layout = PoincareHelpers::CreateLayout(expressionClone()); if (m_layout.isUninitialized()) { - m_layout = HorizontalLayout(); + m_layout = HorizontalLayout::Builder(); } } return m_layout; diff --git a/apps/shared/storage_sum_graph_controller.cpp b/apps/shared/storage_sum_graph_controller.cpp index 6d2997718..0e950cebb 100644 --- a/apps/shared/storage_sum_graph_controller.cpp +++ b/apps/shared/storage_sum_graph_controller.cpp @@ -240,7 +240,7 @@ void StorageSumGraphController::LegendView::setSumSymbol(Step step, double start } else if (step == Step::SecondParameter) { char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits)]; PrintFloat::convertFloatToText(start, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits), Constant::MediumNumberOfSignificantDigits, Preferences::PrintFloatMode::Decimal); - m_sumLayout = CondensedSumLayout( + m_sumLayout = CondensedSumLayout::Builder( LayoutHelper::String(sigma, sizeof(sigma)), LayoutHelper::String(buffer, strlen(buffer), k_font), EmptyLayout(EmptyLayoutNode::Color::Yellow, false, k_font, false)); @@ -251,13 +251,13 @@ void StorageSumGraphController::LegendView::setSumSymbol(Step step, double start Layout start = LayoutHelper::String(buffer, strlen(buffer), KDFont::SmallFont); PrintFloat::convertFloatToText(end, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Preferences::PrintFloatMode::Decimal); Layout end = LayoutHelper::String(buffer, strlen(buffer), k_font); - m_sumLayout = CondensedSumLayout( + m_sumLayout = CondensedSumLayout::Builder( LayoutHelper::String(sigma, sizeof(sigma)), start, end); strlcpy(buffer, "= ", 3); PoincareHelpers::ConvertFloatToText(result, buffer+2, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); - m_sumLayout = HorizontalLayout( + m_sumLayout = HorizontalLayout::Builder( m_sumLayout, functionLayout, LayoutHelper::String(buffer, strlen(buffer), k_font)); diff --git a/apps/shared/sum_graph_controller.cpp b/apps/shared/sum_graph_controller.cpp index 09b299b4b..384279450 100644 --- a/apps/shared/sum_graph_controller.cpp +++ b/apps/shared/sum_graph_controller.cpp @@ -239,7 +239,7 @@ void SumGraphController::LegendView::setSumSymbol(Step step, double start, doubl } else if (step == Step::SecondParameter) { char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits)]; PrintFloat::convertFloatToText(start, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits), Constant::MediumNumberOfSignificantDigits, Preferences::PrintFloatMode::Decimal); - m_sumLayout = CondensedSumLayout( + m_sumLayout = CondensedSumLayout::Builder( LayoutHelper::String(sigma, sizeof(sigma)), LayoutHelper::String(buffer, strlen(buffer), KDFont::SmallFont), EmptyLayout(EmptyLayoutNode::Color::Yellow, false, KDFont::SmallFont, false)); @@ -251,13 +251,13 @@ void SumGraphController::LegendView::setSumSymbol(Step step, double start, doubl Layout start = LayoutHelper::String(buffer, strlen(buffer), KDFont::SmallFont); PrintFloat::convertFloatToText(end, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Preferences::PrintFloatMode::Decimal); Layout end = LayoutHelper::String(buffer, strlen(buffer), KDFont::SmallFont); - m_sumLayout = CondensedSumLayout( + m_sumLayout = CondensedSumLayout::Builder( LayoutHelper::String(sigma, sizeof(sigma)), start, end); strlcpy(buffer, "= ", bufferSize); PoincareHelpers::ConvertFloatToText(result, buffer+2, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); - m_sumLayout = HorizontalLayout( + m_sumLayout = HorizontalLayout::Builder( m_sumLayout, functionLayout, LayoutHelper::String(buffer, strlen(buffer), KDFont::SmallFont)); diff --git a/apps/solver/equation_store.cpp b/apps/solver/equation_store.cpp index bc146c371..8f9e841af 100644 --- a/apps/solver/equation_store.cpp +++ b/apps/solver/equation_store.cpp @@ -211,7 +211,7 @@ EquationStore::Error EquationStore::resolveLinearSystem(Expression exactSolution while (m_variables[n][0] != 0) { n++; } int m = numberOfDefinedModels(); // m equations /* Create the matrix (A | b) for the equation Ax=b */ - Matrix Ab; + Matrix Ab = Matrix::Builder(); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { Ab.addChildAtIndexInPlace(coefficients[i][j], Ab.numberOfChildren(), Ab.numberOfChildren()); @@ -257,20 +257,20 @@ EquationStore::Error EquationStore::oneDimensialPolynomialSolve(Expression exact /* Equation ax^2+bx+c = 0 */ assert(degree == 2); // Compute delta = b*b-4ac - Expression delta = Subtraction(Power(coefficients[1].clone(), Rational(2)), Multiplication(Rational(4), coefficients[0].clone(), coefficients[2].clone())); + Expression delta = Subtraction::Builder(Power::Builder(coefficients[1].clone(), Rational(2)), Multiplication::Builder(Rational(4), coefficients[0].clone(), coefficients[2].clone())); delta = delta.simplify(*context, updatedComplexFormat(), Poincare::Preferences::sharedPreferences()->angleUnit()); if (delta.isUninitialized()) { delta = Poincare::Undefined(); } if (delta.isRationalZero()) { // if delta = 0, x0=x1= -b/(2a) - exactSolutions[0] = Division(Opposite(coefficients[1]), Multiplication(Rational(2), coefficients[2])); + exactSolutions[0] = Division::Builder(Opposite::Builder(coefficients[1]), Multiplication::Builder(Rational(2), coefficients[2])); m_numberOfSolutions = 2; } else { // x0 = (-b-sqrt(delta))/(2a) - exactSolutions[0] = Division(Subtraction(Opposite(coefficients[1].clone()), SquareRoot::Builder(delta.clone())), Multiplication(Rational(2), coefficients[2].clone())); + exactSolutions[0] = Division::Builder(Subtraction::Builder(Opposite::Builder(coefficients[1].clone()), SquareRoot::Builder(delta.clone())), Multiplication::Builder(Rational(2), coefficients[2].clone())); // x1 = (-b+sqrt(delta))/(2a) - exactSolutions[1] = Division(Addition(Opposite(coefficients[1]), SquareRoot::Builder(delta.clone())), Multiplication(Rational(2), coefficients[2])); + exactSolutions[1] = Division::Builder(Addition::Builder(Opposite::Builder(coefficients[1]), SquareRoot::Builder(delta.clone())), Multiplication::Builder(Rational(2), coefficients[2])); m_numberOfSolutions = 3; } exactSolutions[m_numberOfSolutions-1] = delta; @@ -285,23 +285,23 @@ EquationStore::Error EquationStore::oneDimensialPolynomialSolve(Expression exact Expression * c = coefficients[1]; Expression * d = coefficients[0]; // Delta = b^2*c^2+18abcd-27a^2*d^2-4ac^3-4db^3 - Expression * mult0Operands[2] = {new Power(b->clone(), new Rational(2), false), new Power(c->clone(), new Rational(2), false)}; + Expression * mult0Operands[2] = {new Power::Builder(b->clone(), new Rational(2), false), new Power::Builder(c->clone(), new Rational(2), false)}; Expression * mult1Operands[5] = {new Rational(18), a->clone(), b->clone(), c->clone(), d->clone()}; - Expression * mult2Operands[3] = {new Rational(-27), new Power(a->clone(), new Rational(2), false), new Power(d->clone(), new Rational(2), false)}; - Expression * mult3Operands[3] = {new Rational(-4), a->clone(), new Power(c->clone(), new Rational(3), false)}; - Expression * mult4Operands[3] = {new Rational(-4), d->clone(), new Power(b->clone(), new Rational(3), false)}; - Expression * add0Operands[5] = {new Multiplication(mult0Operands, 2, false), new Multiplication(mult1Operands, 5, false), new Multiplication(mult2Operands, 3, false), new Multiplication(mult3Operands, 3, false), new Multiplication(mult4Operands, 3, false)}; + Expression * mult2Operands[3] = {new Rational(-27), new Power::Builder(a->clone(), new Rational(2), false), new Power::Builder(d->clone(), new Rational(2), false)}; + Expression * mult3Operands[3] = {new Rational(-4), a->clone(), new Power::Builder(c->clone(), new Rational(3), false)}; + Expression * mult4Operands[3] = {new Rational(-4), d->clone(), new Power::Builder(b->clone(), new Rational(3), false)}; + Expression * add0Operands[5] = {new Multiplication::Builder(mult0Operands, 2, false), new Multiplication::Builder(mult1Operands, 5, false), new Multiplication::Builder(mult2Operands, 3, false), new Multiplication::Builder(mult3Operands, 3, false), new Multiplication::Builder(mult4Operands, 3, false)}; Expression * delta = new Addition(add0Operands, 5, false); PoincareHelpers::Simplify(&delta, *context); // Delta0 = b^2-3ac Expression * mult5Operands[3] = {new Rational(3), a->clone(), c->clone()}; - Expression * delta0 = new Subtraction(new Power(b->clone(), new Rational(2), false), new Multiplication(mult5Operands, 3, false), false); + Expression * delta0 = new Subtraction::Builder(new Power::Builder(b->clone(), new Rational(2), false), new Multiplication::Builder(mult5Operands, 3, false), false); Reduce(&delta0, *context); if (delta->isRationalZero()) { if (delta0->isRationalZero()) { // delta0 = 0 && delta = 0 --> x0 = -b/(3a) delete delta0; - m_exactSolutions[0] = new Opposite(new Division(b, new Multiplication(new Rational(3), a, false), false), false); + m_exactSolutions[0] = new Opposite::Builder(new Division::Builder(b, new Multiplication::Builder(new Rational(3), a, false), false), false); m_numberOfSolutions = 1; delete c; delete d; @@ -309,33 +309,33 @@ EquationStore::Error EquationStore::oneDimensialPolynomialSolve(Expression exact // delta = 0 --> x0 = (9ad-bc)/(2delta0) // --> x1 = (4abc-9a^2d-b^3)/(a*delta0) Expression * mult6Operands[3] = {new Rational(9), a, d}; - m_exactSolutions[0] = new Division(new Subtraction(new Multiplication(mult6Operands, 3, false), new Multiplication(b, c, false), false), new Multiplication(new Rational(2), delta0, false), false); + m_exactSolutions[0] = new Division::Builder(new Subtraction::Builder(new Multiplication::Builder(mult6Operands, 3, false), new Multiplication::Builder(b, c, false), false), new Multiplication::Builder(new Rational(2), delta0, false), false); Expression * mult7Operands[4] = {new Rational(4), a->clone(), b->clone(), c->clone()}; - Expression * mult8Operands[3] = {new Rational(-9), new Power(a->clone(), new Rational(2), false), d->clone()}; - Expression * add1Operands[3] = {new Multiplication(mult7Operands, 4, false), new Multiplication(mult8Operands,3, false), new Opposite(new Power(b->clone(), new Rational(3), false), false)}; - m_exactSolutions[1] = new Division(new Addition(add1Operands, 3, false), new Multiplication(a->clone(), delta0, false), false); + Expression * mult8Operands[3] = {new Rational(-9), new Power::Builder(a->clone(), new Rational(2), false), d->clone()}; + Expression * add1Operands[3] = {new Multiplication::Builder(mult7Operands, 4, false), new Multiplication::Builder(mult8Operands,3, false), new Opposite::Builder(new Power::Builder(b->clone(), new Rational(3), false), false)}; + m_exactSolutions[1] = new Division::Builder(new Addition(add1Operands, 3, false), new Multiplication::Builder(a->clone(), delta0, false), false); m_numberOfSolutions = 2; } } else { // delta1 = 2b^3-9abc+27a^2*d Expression * mult9Operands[4] = {new Rational(-9), a, b, c}; - Expression * mult10Operands[3] = {new Rational(27), new Power(a->clone(), new Rational(2), false), d}; - Expression * add2Operands[3] = {new Multiplication(new Rational(2), new Power(b->clone(), new Rational(3), false), false), new Multiplication(mult9Operands, 4, false), new Multiplication(mult10Operands, 3, false)}; + Expression * mult10Operands[3] = {new Rational(27), new Power::Builder(a->clone(), new Rational(2), false), d}; + Expression * add2Operands[3] = {new Multiplication::Builder(new Rational(2), new Power::Builder(b->clone(), new Rational(3), false), false), new Multiplication::Builder(mult9Operands, 4, false), new Multiplication::Builder(mult10Operands, 3, false)}; Expression * delta1 = new Addition(add2Operands, 3, false); // C = Root((delta1+sqrt(-27a^2*delta))/2, 3) - Expression * mult11Operands[3] = {new Rational(-27), new Power(a->clone(), new Rational(2), false), (*delta)->clone()}; - Expression * c = new Power(new Division(new Addition(delta1, new SquareRoot(new Multiplication(mult11Operands, 3, false), false), false), new Rational(2), false), new Rational(1,3), false); - Expression * unary3roots[2] = {new Addition(new Rational(-1,2), new Division(new Multiplication(new SquareRoot(new Rational(3), false), new Constant(Ion::Charset::IComplex), false), new Rational(2), false), false), new Subtraction(new Rational(-1,2), new Division(new Multiplication(new SquareRoot(new Rational(3), false), new Constant(Ion::Charset::IComplex), false), new Rational(2), false), false)}; + Expression * mult11Operands[3] = {new Rational(-27), new Power::Builder(a->clone(), new Rational(2), false), (*delta)->clone()}; + Expression * c = new Power::Builder(new Division::Builder(new Addition(delta1, new SquareRoot(new Multiplication::Builder(mult11Operands, 3, false), false), false), new Rational(2), false), new Rational(1,3), false); + Expression * unary3roots[2] = {new Addition(new Rational(-1,2), new Division::Builder(new Multiplication::Builder(new SquareRoot(new Rational(3), false), new Constant(Ion::Charset::IComplex), false), new Rational(2), false), false), new Subtraction::Builder(new Rational(-1,2), new Division::Builder(new Multiplication::Builder(new SquareRoot(new Rational(3), false), new Constant(Ion::Charset::IComplex), false), new Rational(2), false), false)}; // x_k = -1/(3a)*(b+C*z+delta0/(zC)) with z = unary cube root for (int k = 0; k < 3; k++) { Expression * ccopy = c; Expression * delta0copy = delta0; if (k < 2) { - ccopy = new Multiplication(c->clone(), unary3roots[k], false); + ccopy = new Multiplication::Builder(c->clone(), unary3roots[k], false); delta0copy = delta0->clone(); } - Expression * add3Operands[3] = {b->clone(), ccopy, new Division(delta0copy, ccopy->clone(), false)}; - m_exactSolutions[k] = new Multiplication(new Division(new Rational(-1), new Multiplication(new Rational(3), a->clone(), false), false), new Addition(add3Operands, 3, false), false); + Expression * add3Operands[3] = {b->clone(), ccopy, new Division::Builder(delta0copy, ccopy->clone(), false)}; + m_exactSolutions[k] = new Multiplication::Builder(new Division::Builder(new Rational(-1), new Multiplication::Builder(new Rational(3), a->clone(), false), false), new Addition(add3Operands, 3, false), false); } m_numberOfSolutions = 3; } diff --git a/apps/solver/solutions_controller.cpp b/apps/solver/solutions_controller.cpp index 3cf912611..5783f4287 100644 --- a/apps/solver/solutions_controller.cpp +++ b/apps/solver/solutions_controller.cpp @@ -75,7 +75,7 @@ SolutionsController::SolutionsController(Responder * parentResponder, EquationSt m_delta2Layout(), m_contentView(this) { - m_delta2Layout = HorizontalLayout(VerticalOffsetLayout(CharLayout('2', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Superscript), LayoutHelper::String("-4ac", 4, KDFont::SmallFont)); + m_delta2Layout = HorizontalLayout::Builder(VerticalOffsetLayout::Builder(CharLayout('2', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Superscript), LayoutHelper::String("-4ac", 4, KDFont::SmallFont)); char deltaB[] = {Ion::Charset::CapitalDelta, '=', 'b'}; static_cast(m_delta2Layout).addOrMergeChildAtIndex(LayoutHelper::String(deltaB, 3, KDFont::SmallFont), 0, false); for (int i = 0; i < EquationStore::k_maxNumberOfExactSolutions; i++) { diff --git a/escher/src/layout_field.cpp b/escher/src/layout_field.cpp index 866875eb2..b31123263 100644 --- a/escher/src/layout_field.cpp +++ b/escher/src/layout_field.cpp @@ -25,7 +25,7 @@ void LayoutField::ContentView::setEditing(bool isEditing) { } void LayoutField::ContentView::clearLayout() { - HorizontalLayout h; + HorizontalLayout h = HorizontalLayout::Builder(); m_expressionView.setLayout(h); m_cursor.setLayout(h); } diff --git a/poincare/include/poincare/absolute_value_layout.h b/poincare/include/poincare/absolute_value_layout.h index 098b7f3ee..a0dfde873 100644 --- a/poincare/include/poincare/absolute_value_layout.h +++ b/poincare/include/poincare/absolute_value_layout.h @@ -33,6 +33,8 @@ private: class AbsoluteValueLayout final : public Layout { public: + static AbsoluteValueLayout Builder(Layout l) { return AbsoluteValueLayout(l); } +private: explicit AbsoluteValueLayout(Layout l) : Layout(TreePool::sharedPool()->createTreeNode()) { diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index fd6f95dba..6c4348130 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -2,6 +2,7 @@ #define POINCARE_ADDITION_H #include +#include #include #include @@ -60,24 +61,23 @@ private: class Addition final : public NAryExpression { public: Addition(const AdditionNode * n) : NAryExpression(n) {} - Addition(); - explicit Addition(Expression e1) : Addition() { - addChildAtIndexInPlace(e1, 0, 0); - } - Addition(Expression e1, Expression e2) : Addition() { - addChildAtIndexInPlace(e2, 0, 0); - addChildAtIndexInPlace(e1, 0, numberOfChildren()); - } - Addition(Expression * children, size_t numberOfChildren) : Addition() { + static Addition Builder() { return Addition(); } + static Addition Builder(Expression e1) { return Addition::Builder(&e1, 1); } + static Addition Builder(Expression e1, Expression e2) { return Addition::Builder(ArrayBuilder(e1, e2).array(), 2); } + static Addition Builder(Expression * children, size_t numberOfChildren) { + Addition a = Addition::Builder(); for (size_t i = 0; i < numberOfChildren; i++) { - addChildAtIndexInPlace(children[i], i, i); + a.addChildAtIndexInPlace(children[i], i, i); } + return a; } // Expression Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const; private: + Addition() : NAryExpression(TreePool::sharedPool()->createTreeNode()) {} + static const Number NumeralFactor(const Expression & e); static inline int NumberOfNonNumeralFactors(const Expression & e); static inline const Expression FirstNonNumeralFactor(const Expression & e); diff --git a/poincare/include/poincare/array_builder.h b/poincare/include/poincare/array_builder.h new file mode 100644 index 000000000..ed7b232f1 --- /dev/null +++ b/poincare/include/poincare/array_builder.h @@ -0,0 +1,20 @@ +#ifndef POINCARE_ARRAY_BUILDER_H +#define POINCARE_ARRAY_BUILDER_H + + +namespace Poincare { + +template +class ArrayBuilder { +public: + ArrayBuilder(T e1 = T(), T e2 = T(), T e3 = T(), T e4 = T()) : + m_data{e1, e2, e3, e4} + {} + T * array() { return const_cast(m_data); } +private: + T m_data[4]; +}; + +} + +#endif diff --git a/poincare/include/poincare/binomial_coefficient_layout.h b/poincare/include/poincare/binomial_coefficient_layout.h index 222d2e9b0..756f8862e 100644 --- a/poincare/include/poincare/binomial_coefficient_layout.h +++ b/poincare/include/poincare/binomial_coefficient_layout.h @@ -43,6 +43,9 @@ private: class BinomialCoefficientLayout final : public Layout { public: + static BinomialCoefficientLayout Builder(Layout n, Layout k) { return BinomialCoefficientLayout(n, k); } + +private: BinomialCoefficientLayout(Layout n, Layout k) : Layout(TreePool::sharedPool()->createTreeNode()) { diff --git a/poincare/include/poincare/ceiling_layout.h b/poincare/include/poincare/ceiling_layout.h index 4264e318f..72ce65484 100644 --- a/poincare/include/poincare/ceiling_layout.h +++ b/poincare/include/poincare/ceiling_layout.h @@ -30,6 +30,8 @@ protected: class CeilingLayout final : public Layout { public: + static CeilingLayout Builder(Layout l) { return CeilingLayout(l); } +private: explicit CeilingLayout(Layout l) : Layout(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, l); } diff --git a/poincare/include/poincare/condensed_sum_layout.h b/poincare/include/poincare/condensed_sum_layout.h index a705afbf2..59d2f6a7c 100644 --- a/poincare/include/poincare/condensed_sum_layout.h +++ b/poincare/include/poincare/condensed_sum_layout.h @@ -51,7 +51,15 @@ private: class CondensedSumLayout final : public Layout { public: - CondensedSumLayout(Layout base, Layout subscript, Layout superscript); + static CondensedSumLayout Builder(Layout base, Layout subscript, Layout superscript) { return CondensedSumLayout(base, subscript, superscript); } +private: + CondensedSumLayout(Layout base, Layout subscript, Layout superscript) : + Layout(TreePool::sharedPool()->createTreeNode()) + { + replaceChildAtIndexInPlace(0, base); + replaceChildAtIndexInPlace(1, subscript); + replaceChildAtIndexInPlace(2, superscript); + } }; } diff --git a/poincare/include/poincare/conjugate_layout.h b/poincare/include/poincare/conjugate_layout.h index 4e04da6f4..d95dde4f7 100644 --- a/poincare/include/poincare/conjugate_layout.h +++ b/poincare/include/poincare/conjugate_layout.h @@ -40,6 +40,8 @@ private: class ConjugateLayout final : public Layout { public: + static ConjugateLayout Builder(Layout l) { return ConjugateLayout(l); } +private: explicit ConjugateLayout(Layout l) : Layout(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, l); } diff --git a/poincare/include/poincare/division.h b/poincare/include/poincare/division.h index d330d34ec..b620eba3d 100644 --- a/poincare/include/poincare/division.h +++ b/poincare/include/poincare/division.h @@ -60,14 +60,19 @@ private: class Division final : public Expression { public: - Division(); - Division(Expression numerator, Expression denominator) : Division() { - replaceChildAtIndexInPlace(0, numerator); - replaceChildAtIndexInPlace(1, denominator); - } Division(const DivisionNode * n) : Expression(n) {} + static Division Builder() { return Division(); } + static Division Builder(Expression numerator, Expression denominator) { + Division d; + d.replaceChildAtIndexInPlace(0, numerator); + d.replaceChildAtIndexInPlace(1, denominator); + return d; + } Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + +private: + Division() : Expression(TreePool::sharedPool()->createTreeNode()) {} }; } diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index 315010f42..2a1f2774d 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -51,16 +51,19 @@ private: class Factorial final : public Expression { public: - Factorial(); Factorial(const FactorialNode * n) : Expression(n) {} - explicit Factorial(Expression child) : Factorial() { - replaceChildAtIndexInPlace(0, child); + static Factorial Builder() { return Factorial(); } + static Factorial Builder(Expression child) { + Factorial f; + f.replaceChildAtIndexInPlace(0, child); + return f; } Expression shallowReduce(); Expression shallowBeautify(); private: constexpr static int k_maxOperandValue = 100; + Factorial() : Expression(TreePool::sharedPool()->createTreeNode()) {} }; } diff --git a/poincare/include/poincare/floor_layout.h b/poincare/include/poincare/floor_layout.h index eaada21f5..7caf67ed0 100644 --- a/poincare/include/poincare/floor_layout.h +++ b/poincare/include/poincare/floor_layout.h @@ -29,6 +29,8 @@ protected: class FloorLayout final : public Layout { public: + static FloorLayout Builder(Layout l) { return FloorLayout(l); } +private: explicit FloorLayout(Layout l) : Layout(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, l); } diff --git a/poincare/include/poincare/fraction_layout.h b/poincare/include/poincare/fraction_layout.h index 9239ccd6e..23ee39f8f 100644 --- a/poincare/include/poincare/fraction_layout.h +++ b/poincare/include/poincare/fraction_layout.h @@ -58,7 +58,14 @@ private: class FractionLayout final : public Layout { public: - FractionLayout(Layout numerator, Layout denominator); + static FractionLayout Builder(Layout numerator, Layout denominator) { return FractionLayout(numerator, denominator); } +private: + FractionLayout(Layout numerator, Layout denominator) : + Layout(TreePool::sharedPool()->createTreeNode()) + { + replaceChildAtIndexInPlace(0, numerator); + replaceChildAtIndexInPlace(1, denominator); + } }; } diff --git a/poincare/include/poincare/ghost.h b/poincare/include/poincare/ghost.h index a00098aee..d27eff5e9 100644 --- a/poincare/include/poincare/ghost.h +++ b/poincare/include/poincare/ghost.h @@ -12,6 +12,8 @@ namespace Poincare { class Ghost final : public TreeHandle { public: + static Ghost Builder() { return Ghost(); } +private: Ghost() : TreeHandle(TreePool::sharedPool()->createTreeNode()) {} }; diff --git a/poincare/include/poincare/grid_layout.h b/poincare/include/poincare/grid_layout.h index 562928911..46e0b8e2e 100644 --- a/poincare/include/poincare/grid_layout.h +++ b/poincare/include/poincare/grid_layout.h @@ -89,7 +89,7 @@ private: class GridLayout : public Layout { public: GridLayout(const GridLayoutNode * n) : Layout(n) {} - GridLayout() : Layout(TreePool::sharedPool()->createTreeNode()) {} + static GridLayout Builder() { return GridLayout(); } void setDimensions(int rows, int columns); void addChildAtIndex(Layout l, int index, int currentNumberOfChildren, LayoutCursor * cursor) { Layout::addChildAtIndex(l, index, currentNumberOfChildren, cursor); @@ -97,6 +97,7 @@ public: int numberOfRows() const { return node()->numberOfRows(); } int numberOfColumns() const { return node()->numberOfColumns(); } private: + GridLayout() : Layout(TreePool::sharedPool()->createTreeNode()) {} virtual GridLayoutNode * node() const { return static_cast(Layout::node()); } void setNumberOfRows(int rows) { assert(rows >= 0); diff --git a/poincare/include/poincare/horizontal_layout.h b/poincare/include/poincare/horizontal_layout.h index 9a2c06811..5cb32b211 100644 --- a/poincare/include/poincare/horizontal_layout.h +++ b/poincare/include/poincare/horizontal_layout.h @@ -1,6 +1,7 @@ #ifndef POINCARE_HORIZONTAL_LAYOUT_NODE_H #define POINCARE_HORIZONTAL_LAYOUT_NODE_H +#include #include #include @@ -65,13 +66,21 @@ private: class HorizontalLayout final : public Layout { friend class HorizontalLayoutNode; public: + // Constructors HorizontalLayout(HorizontalLayoutNode * n) : Layout(n) {} - HorizontalLayout(); - explicit HorizontalLayout(Layout l); - HorizontalLayout(Layout l1, Layout l2); - HorizontalLayout(Layout l1, Layout l2, Layout l3); - HorizontalLayout(Layout l1, Layout l2, Layout l3, Layout l4); - HorizontalLayout(const Layout * children, size_t numberOfChildren); + static HorizontalLayout Builder() { return HorizontalLayout(); } + static HorizontalLayout Builder(Layout l) { return HorizontalLayout::Builder(&l, 1); } + static HorizontalLayout Builder(Layout l1, Layout l2) { return HorizontalLayout::Builder(ArrayBuilder(l1, l2).array(), 2); } + static HorizontalLayout Builder(Layout l1, Layout l2, Layout l3) { return HorizontalLayout::Builder(ArrayBuilder(l1, l2, l3).array(), 3); } + static HorizontalLayout Builder(Layout l1, Layout l2, Layout l3, Layout l4) { return HorizontalLayout::Builder(ArrayBuilder(l1, l2, l3, l4).array(), 4); } + static HorizontalLayout Builder(const Layout * children, size_t numberOfChildren) { + HorizontalLayout h = HorizontalLayout::Builder(); + for (size_t i = 0; i < numberOfChildren; i++) { + h.addChildAtIndexInPlace(children[i], i, i); + } + return h; + } + void addChildAtIndex(Layout l, int index, int currentNumberOfChildren, LayoutCursor * cursor, bool removeEmptyChildren = false); // Remove puts a child at the end of the pool void removeChild(Layout l, LayoutCursor * cursor, bool force = false) { @@ -82,7 +91,9 @@ public: } void addOrMergeChildAtIndex(Layout l, int index, bool removeEmptyChildren, LayoutCursor * cursor = nullptr); void mergeChildrenAtIndex(HorizontalLayout h, int index, bool removeEmptyChildren, LayoutCursor * cursor = nullptr); + private: + HorizontalLayout() : Layout(TreePool::sharedPool()->createTreeNode()) {} void removeEmptyChildBeforeInsertionAtIndex(int * index, int * currentNumberOfChildren, bool shouldRemoveOnLeft, LayoutCursor * cursor = nullptr); }; diff --git a/poincare/include/poincare/integral_layout.h b/poincare/include/poincare/integral_layout.h index f252c308f..26fc711a0 100644 --- a/poincare/include/poincare/integral_layout.h +++ b/poincare/include/poincare/integral_layout.h @@ -56,6 +56,8 @@ private: class IntegralLayout final : public Layout { public: + static IntegralLayout Builder(Layout integrand, Layout differential, Layout lowerBound, Layout upperBound) { return IntegralLayout(integrand, differential, lowerBound, upperBound); } +private: IntegralLayout(Layout integrand, Layout differential, Layout lowerBound, Layout upperBound) : Layout(TreePool::sharedPool()->createTreeNode()) { diff --git a/poincare/include/poincare/left_parenthesis_layout.h b/poincare/include/poincare/left_parenthesis_layout.h index 59747765a..5bf6d25e0 100644 --- a/poincare/include/poincare/left_parenthesis_layout.h +++ b/poincare/include/poincare/left_parenthesis_layout.h @@ -35,7 +35,9 @@ protected: class LeftParenthesisLayout final : public Layout { public: - LeftParenthesisLayout(); + static LeftParenthesisLayout Builder() { return LeftParenthesisLayout(); } +private: + LeftParenthesisLayout() : Layout(TreePool::sharedPool()->createTreeNode()) {} }; } diff --git a/poincare/include/poincare/left_square_bracket_layout.h b/poincare/include/poincare/left_square_bracket_layout.h index 80dc2e75e..c0dfed6cd 100644 --- a/poincare/include/poincare/left_square_bracket_layout.h +++ b/poincare/include/poincare/left_square_bracket_layout.h @@ -29,7 +29,9 @@ protected: class LeftSquareBracketLayout final : public Layout { public: - LeftSquareBracketLayout(); + static LeftSquareBracketLayout Builder() { return LeftSquareBracketLayout(); } +private: + LeftSquareBracketLayout() : Layout(TreePool::sharedPool()->createTreeNode()) {} }; } diff --git a/poincare/include/poincare/matrix.h b/poincare/include/poincare/matrix.h index cbe0a2c16..1c07e0708 100644 --- a/poincare/include/poincare/matrix.h +++ b/poincare/include/poincare/matrix.h @@ -62,14 +62,8 @@ class Matrix final : public Expression { template friend class MatrixComplexNode; friend class GlobalContext; public: - static Matrix EmptyMatrix() { - return Matrix(TreePool::sharedPool()->createTreeNode()); - } - Matrix() : Matrix(TreePool::sharedPool()->createTreeNode()) {} Matrix(const MatrixNode * node) : Expression(node) {} - explicit Matrix(Expression e) : Matrix() { - addChildAtIndexInPlace(e, 0, 0); - } + static Matrix Builder() { return Matrix(); } void setDimensions(int rows, int columns); int numberOfRows() const { return node()->numberOfRows(); } @@ -91,6 +85,7 @@ public: Expression inverse(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; #endif private: + Matrix() : Matrix(TreePool::sharedPool()->createTreeNode()) {} // TODO: find another solution for inverse and determinant (avoid capping the matrix) static constexpr int k_maxNumberOfCoefficients = 100; @@ -98,7 +93,7 @@ private: void setNumberOfRows(int rows) { assert(rows >= 0); node()->setNumberOfRows(rows); } void setNumberOfColumns(int columns) { assert(columns >= 0); node()->setNumberOfColumns(columns); } /* rowCanonize turns a matrix in its reduced row echelon form. */ - Matrix rowCanonize(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, Multiplication m = Multiplication()); + Matrix rowCanonize(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, Multiplication m = Multiplication::Builder()); // Row canonize the array in place template static void ArrayRowCanonize(T * array, int numberOfRows, int numberOfColumns, T * c = nullptr); }; diff --git a/poincare/include/poincare/matrix_layout.h b/poincare/include/poincare/matrix_layout.h index 28374c557..9f3420136 100644 --- a/poincare/include/poincare/matrix_layout.h +++ b/poincare/include/poincare/matrix_layout.h @@ -57,13 +57,23 @@ private: class MatrixLayout /*final*/ : public GridLayout { friend class MatrixLayoutNode; public: - MatrixLayout(const MatrixLayoutNode * n); - MatrixLayout(); - MatrixLayout(Layout l1, Layout l2, Layout l3, Layout l4); + static MatrixLayout Builder() { return MatrixLayout(); } + MatrixLayout(const MatrixLayoutNode * n) : GridLayout(n) {} + static MatrixLayout Builder(Layout l1, Layout l2, Layout l3, Layout l4) { + MatrixLayout m = MatrixLayout::Builder(); + m.addChildAtIndexInPlace(l1, 0, 0); + m.addChildAtIndexInPlace(l2, 1, 1); + m.addChildAtIndexInPlace(l3, 2, 2); + m.addChildAtIndexInPlace(l4, 3, 3); + m.setDimensions(2, 2); + return m; + } + bool hasGreySquares() const { return node()->hasGreySquares(); } void addGreySquares() { node()->addGreySquares(); } void removeGreySquares() { node()->removeGreySquares(); } private: + MatrixLayout() : GridLayout(TreePool::sharedPool()->createTreeNode()) {} MatrixLayoutNode * node() const { return static_cast(Layout::node()); } }; diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index fadc6780a..b41bde2ce 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -2,6 +2,7 @@ #define POINCARE_MULTIPLICATION_H #include +#include #include namespace Poincare { @@ -66,17 +67,10 @@ class Multiplication final : public NAryExpression { friend class Power; public: Multiplication(const MultiplicationNode * n) : NAryExpression(n) {} - Multiplication(); - explicit Multiplication(Expression e1) : Multiplication() { - addChildAtIndexInPlace(e1, 0, 0); - } - Multiplication(Expression e1, Expression e2) : Multiplication() { - addChildAtIndexInPlace(e2, 0, 0); - addChildAtIndexInPlace(e1, 0, numberOfChildren()); - } - Multiplication(Expression e1, Expression e2, Expression e3) : Multiplication(e2, e3) { - addChildAtIndexInPlace(e1, 0, numberOfChildren()); - } + static Multiplication Builder() { return Multiplication(); } + static Multiplication Builder(Expression e1) { return Multiplication(&e1, 1); } + static Multiplication Builder(Expression e1, Expression e2) { return Multiplication(ArrayBuilder(e1, e2).array(), 2); } + static Multiplication Builder(Expression e1, Expression e2, Expression e3) { return Multiplication(ArrayBuilder(e1, e2, e3).array(), 3); } template static void computeOnArrays(T * m, T * n, T * result, int mNumberOfColumns, int mNumberOfRows, int nNumberOfColumns); // Expression @@ -86,6 +80,13 @@ public: int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const; Expression denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; private: + // Constructors + Multiplication() : NAryExpression(TreePool::sharedPool()->createTreeNode()) {} + explicit Multiplication(Expression * children, size_t numberOfChildren) : Multiplication() { + for (size_t i = 0; i < numberOfChildren; i++) { + addChildAtIndexInPlace(children[i], i, i); + } + } // Simplification Expression privateShallowReduce(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target, bool expand, bool canBeInterrupted); void mergeMultiplicationChildrenInPlace(); diff --git a/poincare/include/poincare/nth_root_layout.h b/poincare/include/poincare/nth_root_layout.h index 8f9e59ebf..5cb5d51e3 100644 --- a/poincare/include/poincare/nth_root_layout.h +++ b/poincare/include/poincare/nth_root_layout.h @@ -67,10 +67,17 @@ private: class NthRootLayout final : public Layout { public: - explicit NthRootLayout(Layout radicand); - NthRootLayout(Layout radicand, Layout index); + static NthRootLayout Builder(Layout radicand) { return NthRootLayout(radicand); } + static NthRootLayout Builder(Layout radicand, Layout index) { + NthRootLayout n(radicand); + n.addChildAtIndexInPlace(index, 1, 1); + static_cast(n.node())->setNumberOfChildren(2); + return n; + } private: - NthRootLayout(); + NthRootLayout(Layout radicand) : Layout(TreePool::sharedPool()->createTreeNode()) { + replaceChildAtIndexInPlace(0, radicand); + } }; } diff --git a/poincare/include/poincare/opposite.h b/poincare/include/poincare/opposite.h index 9db4dd53d..23f1f19df 100644 --- a/poincare/include/poincare/opposite.h +++ b/poincare/include/poincare/opposite.h @@ -46,13 +46,17 @@ public: class Opposite final : public Expression { public: - Opposite(); Opposite(const OppositeNode * n) : Expression(n) {} + static Opposite Builder() { return Opposite(); } + static Opposite Builder(Expression child) { return Opposite(child); } + + Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + +private: + Opposite() : Expression(TreePool::sharedPool()->createTreeNode()) {} explicit Opposite(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); } - - Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); }; } diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index ed3fd93b0..d4b940bea 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -38,11 +38,14 @@ private: class Parenthesis final : public Expression { public: Parenthesis(const ParenthesisNode * n) : Expression(n) {} + static Parenthesis Builder(Expression child) { return Parenthesis(child); } + // Expression + Expression shallowReduce(); + +private: Parenthesis(Expression exp) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, exp); } - // Expression - Expression shallowReduce(); }; } diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index b506cac49..8ddc1d6b0 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -66,8 +66,9 @@ class Power final : public Expression { friend class PowerNode; friend class Round; public: - Power(Expression base, Expression exponent); Power(const PowerNode * n) : Expression(n) {} + static Power Builder(Expression base, Expression exponent) { return Power(base, exponent); } + Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const; Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); @@ -77,6 +78,12 @@ private: constexpr static int k_maxExactPowerMatrix = 100; constexpr static int k_maxNumberOfTermsInExpandedMultinome = 25; + // Constructors + Power(Expression base, Expression exponent) : Expression(TreePool::sharedPool()->createTreeNode()) { + replaceChildAtIndexInPlace(0, base); + replaceChildAtIndexInPlace(1, exponent); + } + // Simplification Expression denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; diff --git a/poincare/include/poincare/product_layout.h b/poincare/include/poincare/product_layout.h index 8eb2adccd..7c2298d95 100644 --- a/poincare/include/poincare/product_layout.h +++ b/poincare/include/poincare/product_layout.h @@ -25,6 +25,8 @@ private: class ProductLayout final : public Layout { public: + static ProductLayout Builder(Layout argument, Layout variable, Layout lowerB, Layout upperB) { return ProductLayout(argument, variable, lowerB, upperB); } +private: ProductLayout(Layout argument, Layout variable, Layout lowerB, Layout upperB) : Layout(TreePool::sharedPool()->createTreeNode()) { diff --git a/poincare/include/poincare/right_parenthesis_layout.h b/poincare/include/poincare/right_parenthesis_layout.h index 6f127afb3..342634b7f 100644 --- a/poincare/include/poincare/right_parenthesis_layout.h +++ b/poincare/include/poincare/right_parenthesis_layout.h @@ -36,7 +36,9 @@ protected: class RightParenthesisLayout final : public Layout { public: - RightParenthesisLayout(); + static RightParenthesisLayout Builder() { return RightParenthesisLayout(); } +private: + RightParenthesisLayout() : Layout(TreePool::sharedPool()->createTreeNode()) {} }; } diff --git a/poincare/include/poincare/right_square_bracket_layout.h b/poincare/include/poincare/right_square_bracket_layout.h index 1f6c5925f..860c15e20 100644 --- a/poincare/include/poincare/right_square_bracket_layout.h +++ b/poincare/include/poincare/right_square_bracket_layout.h @@ -29,7 +29,10 @@ protected: class RightSquareBracketLayout final : public Layout { public: - RightSquareBracketLayout(); + static RightSquareBracketLayout Builder() { return RightSquareBracketLayout(); } + +private: + RightSquareBracketLayout() : Layout(TreePool::sharedPool()->createTreeNode()) {} }; } diff --git a/poincare/include/poincare/store.h b/poincare/include/poincare/store.h index b4c9e61a5..0d780cd75 100644 --- a/poincare/include/poincare/store.h +++ b/poincare/include/poincare/store.h @@ -40,10 +40,7 @@ class Store final : public Expression { friend class StoreNode; public: Store(const StoreNode * n) : Expression(n) {} - Store(Expression value, SymbolAbstract symbol) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, value); - replaceChildAtIndexInPlace(1, symbol); - } + static Store Builder(Expression value, SymbolAbstract symbol) { return Store(value, symbol); } // Store const SymbolAbstract symbol() const { @@ -58,6 +55,11 @@ public: // Expression Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: + Store(Expression value, SymbolAbstract symbol) : Expression(TreePool::sharedPool()->createTreeNode()) { + replaceChildAtIndexInPlace(0, value); + replaceChildAtIndexInPlace(1, symbol); + } + Expression storeValueForSymbol(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; StoreNode * node() const { return static_cast(Expression::node()); } }; diff --git a/poincare/include/poincare/subtraction.h b/poincare/include/poincare/subtraction.h index 393c0e13a..faae9c66b 100644 --- a/poincare/include/poincare/subtraction.h +++ b/poincare/include/poincare/subtraction.h @@ -54,15 +54,20 @@ private: class Subtraction final : public Expression { public: - Subtraction(); Subtraction(const SubtractionNode * n) : Expression(n) {} - Subtraction(Expression child0, Expression child1) : Subtraction() { - replaceChildAtIndexInPlace(0, child0); - replaceChildAtIndexInPlace(1, child1); + static Subtraction Builder() { return Subtraction(); } + static Subtraction Builder(Expression child0, Expression child1) { + Subtraction s = Subtraction::Builder(); + s.replaceChildAtIndexInPlace(0, child0); + s.replaceChildAtIndexInPlace(1, child1); + return s; } // Expression Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + +private: + Subtraction() : Expression(TreePool::sharedPool()->createTreeNode()) {} }; } diff --git a/poincare/include/poincare/sum_layout.h b/poincare/include/poincare/sum_layout.h index f201a8e69..a21b6fd38 100644 --- a/poincare/include/poincare/sum_layout.h +++ b/poincare/include/poincare/sum_layout.h @@ -23,6 +23,8 @@ private: class SumLayout final : public Layout { public: + static SumLayout Builder(Layout argument, Layout variable, Layout lowerB, Layout upperB) { return SumLayout(argument, variable, lowerB, upperB); } +private: SumLayout(Layout argument, Layout variable, Layout lowerB, Layout upperB) : Layout(TreePool::sharedPool()->createTreeNode()) { diff --git a/poincare/include/poincare/vertical_offset_layout.h b/poincare/include/poincare/vertical_offset_layout.h index c46caba12..8ac17b24f 100644 --- a/poincare/include/poincare/vertical_offset_layout.h +++ b/poincare/include/poincare/vertical_offset_layout.h @@ -59,7 +59,15 @@ private: class VerticalOffsetLayout final : public Layout { public: - VerticalOffsetLayout(Layout l, VerticalOffsetLayoutNode::Type type); + static VerticalOffsetLayout Builder(Layout l, VerticalOffsetLayoutNode::Type type) { return VerticalOffsetLayout(l, type); } + +private: + VerticalOffsetLayout(Layout l, VerticalOffsetLayoutNode::Type type) : + Layout(TreePool::sharedPool()->createTreeNode()) + { + static_cast(node())->setType(type); + replaceChildAtIndexInPlace(0,l); + } }; } diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index dcb428794..a057ae5f0 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -20,7 +20,7 @@ Expression AbsoluteValueNode::setSign(Sign s, Context * context, Preferences::Co } Layout AbsoluteValueNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { - return AbsoluteValueLayout(childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits)); + return AbsoluteValueLayout::Builder(childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits)); } int AbsoluteValueNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -62,7 +62,7 @@ Expression AbsoluteValue::shallowReduce(Context & context, Preferences::ComplexF } else if (!std::isnan(app) && ((c.isNumber() && app < 0.0f) || app <= -Expression::Epsilon())) { // abs(a) = -a with a < 0 (same comment as above to check that a < 0) - Multiplication m(Rational(-1), c); + Multiplication m = Multiplication::Builder(Rational(-1), c); replaceWithInPlace(m); return m.shallowReduce(context, complexFormat, angleUnit, target); } diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 6a34b2243..73814db1e 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -59,7 +59,6 @@ Expression AdditionNode::shallowBeautify(Context & context, Preferences::Complex } // Addition -Addition::Addition() : NAryExpression(TreePool::sharedPool()->createTreeNode()) {} const Number Addition::NumeralFactor(const Expression & e) { if (e.type() == ExpressionNode::Type::Multiplication && e.childAtIndex(0).isNumber()) { @@ -94,7 +93,7 @@ Expression Addition::shallowBeautify(Context & context, Preferences::ComplexForm * In practice, we want to turn "a+(-1)*b" into "a-b". Or, more precisely, any * "a+(-r)*b" into "a-r*b" where r is a positive Rational. * Note: the process will slightly differ if the negative product occurs on - * the first term: we want to turn "AdditionNode(Multiplication(-1,b))" into + * the first term: we want to turn "Addition(Multiplication::Builder(-1,b))" into * "Opposite(b)". * Last but not least, special care must be taken when iterating over children * since we may remove some during the process. */ @@ -115,7 +114,7 @@ Expression Addition::shallowBeautify(Context & context, Preferences::ComplexForm } if (i == 0) { - Opposite o = Opposite(subtractant); + Opposite o = Opposite::Builder(subtractant); replaceChildAtIndexInPlace(i, o); } else { Expression leftSibling = childAtIndex(i-1); @@ -123,7 +122,7 @@ Expression Addition::shallowBeautify(Context & context, Preferences::ComplexForm /* CAUTION: we removed a child. So we need to decrement i to make sure * the next iteration is actually on the next child. */ i--; - Subtraction s = Subtraction(leftSibling, subtractant); + Subtraction s = Subtraction::Builder(leftSibling, subtractant); /* We stole subtractant from this which replaced it by a ghost. We thus * need to put the subtraction at the previous index of subtractant, which * is still i because we updated i after removing a child. */ @@ -262,7 +261,7 @@ Expression Addition::shallowReduce(Context & context, Preferences::ComplexFormat * We can bubble up ComplexCartesian nodes. */ if (allChildrenAreReal(context) == 0) { /* We turn (a+ib)+(c+id) into (a+c)+i(c+d)*/ - Addition imag; // we store all imaginary parts in 'imag' + Addition imag = Addition::Builder(); // we store all imaginary parts in 'imag' Addition real = *this; // we store all real parts in 'real' i = numberOfChildren() - 1; while (i >= 0) { @@ -341,7 +340,7 @@ Expression Addition::factorizeOnCommonDenominator(Context & context, Preferences // We want to turn (a/b+c/d+e/b) into (a*d+b*c+e*d)/(b*d) // Step 1: We want to compute the common denominator, b*d - Multiplication commonDenominator = Multiplication(); + Multiplication commonDenominator; for (int i = 0; i < numberOfChildren(); i++) { Expression currentDenominator = childAtIndex(i).denominator(context, complexFormat, angleUnit); if (!currentDenominator.isUninitialized()) { @@ -356,16 +355,16 @@ Expression Addition::factorizeOnCommonDenominator(Context & context, Preferences /* Step 2: Create the numerator. We start with this being a/b+c/d+e/b and we * want to create numerator = a/b*b*d + c/d*b*d + e/b*b*d = a*d + c*b + e*d */ - Addition numerator = Addition(); + Addition numerator = Addition::Builder(); for (int i = 0; i < numberOfChildren(); i++) { - Multiplication m = Multiplication(childAtIndex(i), commonDenominator.clone()); + Multiplication m = Multiplication::Builder(childAtIndex(i), commonDenominator.clone()); numerator.addChildAtIndexInPlace(m, numerator.numberOfChildren(), numerator.numberOfChildren()); m.privateShallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User, true, false); } // Step 3: Add the denominator - Power inverseDenominator = Power(commonDenominator, Rational(-1)); - Multiplication result = Multiplication(numerator, inverseDenominator); + Power inverseDenominator = Power::Builder(commonDenominator, Rational(-1)); + Multiplication result = Multiplication::Builder(numerator, inverseDenominator); // Step 4: Simplify the numerator numerator.shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); @@ -396,7 +395,7 @@ void Addition::factorizeChildrenAtIndexesInPlace(int index1, int index2, Context removeChildAtIndexInPlace(index2); // Step 3: Create a multiplication - Multiplication m; + Multiplication m = Multiplication::Builder(); if (e1.type() == ExpressionNode::Type::Multiplication) { m = static_cast(e1); } else { diff --git a/poincare/src/binomial_coefficient.cpp b/poincare/src/binomial_coefficient.cpp index 84ad781fb..72661df33 100644 --- a/poincare/src/binomial_coefficient.cpp +++ b/poincare/src/binomial_coefficient.cpp @@ -19,7 +19,7 @@ Expression BinomialCoefficientNode::shallowReduce(Context & context, Preferences } Layout BinomialCoefficientNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { - return BinomialCoefficientLayout( + return BinomialCoefficientLayout::Builder( childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits), childAtIndex(1)->createLayout(floatDisplayMode, numberOfSignificantDigits)); } diff --git a/poincare/src/ceiling.cpp b/poincare/src/ceiling.cpp index 8c28d54d2..cd8ddf05c 100644 --- a/poincare/src/ceiling.cpp +++ b/poincare/src/ceiling.cpp @@ -16,7 +16,7 @@ constexpr Expression::FunctionHelper Ceiling::s_functionHelper; int CeilingNode::numberOfChildren() const { return Ceiling::s_functionHelper.numberOfChildren(); } Layout CeilingNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { - return CeilingLayout(childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits)); + return CeilingLayout::Builder(childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits)); } int CeilingNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { diff --git a/poincare/src/complex_cartesian.cpp b/poincare/src/complex_cartesian.cpp index fc2241a96..65ea33af3 100644 --- a/poincare/src/complex_cartesian.cpp +++ b/poincare/src/complex_cartesian.cpp @@ -106,13 +106,13 @@ Expression ComplexCartesian::squareNorm(Context & context, Preferences::ComplexF factorAndArgumentOfFunction(a, ExpressionNode::Type::Cosine, &aFactor, &aArgument, context, complexFormat, angleUnit, target); factorAndArgumentOfFunction(b, ExpressionNode::Type::Sine, &bFactor, &bArgument, context, complexFormat, angleUnit, target); if (!aFactor.isUninitialized() && !aArgument.isUninitialized() && !bFactor.isUninitialized() && !bArgument.isUninitialized() && aFactor.isIdenticalTo(bFactor) && aArgument.isIdenticalTo(bArgument)) { - Power result(aFactor, Rational(2)); + Power result = Power::Builder(aFactor, Rational(2)); aFactor.shallowReduce(context, complexFormat, angleUnit, target); return result; } - Expression a2 = Power(a, Rational(2)); - Expression b2 = Power(b, Rational(2)); - Addition add(a2, b2); + Expression a2 = Power::Builder(a, Rational(2)); + Expression b2 = Power::Builder(b, Rational(2)); + Addition add = Addition::Builder(a2, b2); a2.shallowReduce(context, complexFormat, angleUnit, target); b2.shallowReduce(context, complexFormat, angleUnit, target); return add; @@ -142,7 +142,7 @@ Expression ComplexCartesian::argument(Context & context, Preferences::ComplexFor if (!b.isRationalZero()) { // if b != 0, argument = sign(b) * Pi/2 - arctan(a/b) // First, compute arctan(a/b) or (Pi/180)*arctan(a/b) - Expression divab = Division(a, b.clone()); + Expression divab = Division::Builder(a, b.clone()); Expression arcTangent = ArcTangent::Builder(divab); divab.shallowReduce(context, complexFormat, angleUnit, target); if (angleUnit == Preferences::AngleUnit::Degree) { @@ -152,18 +152,18 @@ Expression ComplexCartesian::argument(Context & context, Preferences::ComplexFor } // Then, compute sign(b) * Pi/2 - arctan(a/b) Expression signb = SignFunction::Builder(b); - Expression signbPi2 = Multiplication(Rational(1,2), signb, Constant(Ion::Charset::SmallPi)); + Expression signbPi2 = Multiplication::Builder(Rational(1,2), signb, Constant(Ion::Charset::SmallPi)); signb.shallowReduce(context, complexFormat, angleUnit, target); - Expression sub = Subtraction(signbPi2, arcTangent); + Expression sub = Subtraction::Builder(signbPi2, arcTangent); signbPi2.shallowReduce(context, complexFormat, angleUnit, target); arcTangent.shallowReduce(context, complexFormat, angleUnit, target); return sub; } else { // if b == 0, argument = (1-sign(a))*Pi/2 Expression signa = SignFunction::Builder(a).shallowReduce(context, complexFormat, angleUnit, target); - Subtraction sub(Rational(1), signa); + Subtraction sub = Subtraction::Builder(Rational(1), signa); signa.shallowReduce(context, complexFormat, angleUnit, target); - Multiplication mul(Rational(1,2), Constant(Ion::Charset::SmallPi), sub); + Multiplication mul = Multiplication::Builder(Rational(1,2), Constant(Ion::Charset::SmallPi), sub); sub.shallowReduce(context, complexFormat, angleUnit, target); return mul; } @@ -175,14 +175,14 @@ ComplexCartesian ComplexCartesian::inverse(Context & context, Preferences::Compl // 1/(a+ib) = a/(a^2+b^2)+i*(-b/(a^2+b^2)) Expression denominatorReal = clone().convert().squareNorm(context, complexFormat, angleUnit, target); Expression denominatorImag = denominatorReal.clone(); - Expression denominatorRealInv = Power(denominatorReal, Rational(-1)); + Expression denominatorRealInv = Power::Builder(denominatorReal, Rational(-1)); denominatorReal.shallowReduce(context, complexFormat, angleUnit, target); - Expression denominatorImagInv = Power(denominatorImag, Rational(-1)); + Expression denominatorImagInv = Power::Builder(denominatorImag, Rational(-1)); denominatorImag.shallowReduce(context, complexFormat, angleUnit, target); - Multiplication A(a, denominatorRealInv); + Multiplication A = Multiplication::Builder(a, denominatorRealInv); denominatorRealInv.shallowReduce(context, complexFormat, angleUnit, target); - Expression numeratorImag = Multiplication(Rational(-1), b); - Multiplication B(numeratorImag, denominatorImagInv); + Expression numeratorImag = Multiplication::Builder(Rational(-1), b); + Multiplication B = Multiplication::Builder(numeratorImag, denominatorImagInv); numeratorImag.shallowReduce(context, complexFormat, angleUnit, target); denominatorImagInv.shallowReduce(context, complexFormat, angleUnit, target); ComplexCartesian result(A,B); @@ -193,11 +193,11 @@ ComplexCartesian ComplexCartesian::inverse(Context & context, Preferences::Compl Multiplication ComplexCartesian::squareRootHelper(Expression e, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { //(1/2)*sqrt(2*e) - Multiplication doubleE(Rational(2), e); + Multiplication doubleE = Multiplication::Builder(Rational(2), e); e.shallowReduce(context, complexFormat, angleUnit, target); Expression sqrt = SquareRoot::Builder(doubleE); doubleE.shallowReduce(context, complexFormat, angleUnit, target); - Multiplication result(Rational(1,2), sqrt); + Multiplication result = Multiplication::Builder(Rational(1,2), sqrt); sqrt.shallowReduce(context, complexFormat, angleUnit, target); return result; } @@ -210,11 +210,11 @@ ComplexCartesian ComplexCartesian::squareRoot(Context & context, Preferences::Co Expression normA = clone().convert().norm(context, complexFormat, angleUnit, target); Expression normB = normA.clone(); // A = (1/2)*sqrt(2*(sqrt(a^2+b^2)+a)) - Addition normAdda(normA, a.clone()); + Addition normAdda = Addition::Builder(normA, a.clone()); normA.shallowReduce(context, complexFormat, angleUnit, target); Multiplication A = squareRootHelper(normAdda, context, complexFormat, angleUnit, target); // B = B: (1/2)*sqrt(2*(sqrt(a^2+b^2)-a)) - Subtraction normSuba(normB, a); + Subtraction normSuba = Subtraction::Builder(normB, a); normB.shallowReduce(context, complexFormat, angleUnit, target); Multiplication B = squareRootHelper(normSuba, context, complexFormat, angleUnit, target); // B = B: (1/2)*sqrt(2*(sqrt(a^2+b^2)-a))*sign(b) @@ -238,9 +238,9 @@ ComplexCartesian ComplexCartesian::powerInteger(int n, Context & context, Prefer // (b*i)^n = b^n*i^n with i^n == i, -i, 1 or -1 if (a.isRationalZero()) { ComplexCartesian result; - Expression bpow = Power(b, Rational(n)); + Expression bpow = Power::Builder(b, Rational(n)); if (n/2%2 == 1) { - Expression temp = Multiplication(Rational(-1), bpow); + Expression temp = Multiplication::Builder(Rational(-1), bpow); bpow.shallowReduce(context, complexFormat, angleUnit, target); bpow = temp; } @@ -255,16 +255,16 @@ ComplexCartesian ComplexCartesian::powerInteger(int n, Context & context, Prefer // (a+ib) = a^n+i*b*a^(n-1)+(-1)*b^2*a^(n-2)+(-i)*b^3*a^(n-3)+b^3*a^(n-4)+... // Real part: A = a^n+(-1)*b^2*a^(n-2)+... // Imaginary part: B = b*a^(n-1) - Addition A; - Addition B; + Addition A = Addition::Builder(); + Addition B = Addition::Builder(); ComplexCartesian result = ComplexCartesian::Builder(A, B); for (int i = 0; i <= n; i++) { BinomialCoefficient binom = BinomialCoefficient::Builder(Rational(n), Rational(i)); Expression aclone = i == n ? a : a.clone(); Expression bclone = i == n ? b : b.clone(); - Power apow(aclone, Rational(n-i)); - Power bpow(bclone, Rational(i)); - Multiplication m(binom, apow, bpow); + Power apow = Power::Builder(aclone, Rational(n-i)); + Power bpow = Power::Builder(bclone, Rational(i)); + Multiplication m = Multiplication::Builder(binom, apow, bpow); binom.shallowReduce(); apow.shallowReduce(context, complexFormat, angleUnit, target); bpow.shallowReduce(context, complexFormat, angleUnit, target); @@ -294,15 +294,15 @@ ComplexCartesian ComplexCartesian::multiply(ComplexCartesian & other, Context & Expression d = other.imag(); // (a+ib) * (c+id) = (ac-bd)+i*(ad+bc) // Compute ac-bd - Expression ac = Multiplication(a.clone(), c.clone()); - Expression bd = Multiplication(b.clone(), d.clone()); - Subtraction A(ac, bd); + Expression ac = Multiplication::Builder(a.clone(), c.clone()); + Expression bd = Multiplication::Builder(b.clone(), d.clone()); + Subtraction A = Subtraction::Builder(ac, bd); ac.shallowReduce(context, complexFormat, angleUnit, target); bd.shallowReduce(context, complexFormat, angleUnit, target); // Compute ad+bc - Expression ad = Multiplication(a, d); - Expression bc = Multiplication(b, c); - Addition B(ad, bc); + Expression ad = Multiplication::Builder(a, d); + Expression bc = Multiplication::Builder(b, c); + Addition B = Addition::Builder(ad, bc); ad.shallowReduce(context, complexFormat, angleUnit, target); bc.shallowReduce(context, complexFormat, angleUnit, target); ComplexCartesian result = ComplexCartesian::Builder(A, B); @@ -312,7 +312,7 @@ ComplexCartesian ComplexCartesian::multiply(ComplexCartesian & other, Context & } Expression ComplexCartesian::powerHelper(Expression norm, Expression trigo, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { - Multiplication m(norm, trigo); + Multiplication m = Multiplication::Builder(norm, trigo); norm.shallowReduce(context, complexFormat, angleUnit, target); trigo.shallowReduce(context, complexFormat, angleUnit, target); return m; @@ -326,24 +326,24 @@ ComplexCartesian ComplexCartesian::power(ComplexCartesian & other, Context & con Expression c = other.real(); Expression d = other.imag(); // R = r^c*e^(-th*d) - Expression rpowc = Power(rclone, c.clone()); + Expression rpowc = Power::Builder(rclone, c.clone()); rclone.shallowReduce(context, complexFormat, angleUnit, target); - Expression thmuld = Multiplication(Rational(-1), thclone, d.clone()); + Expression thmuld = Multiplication::Builder(Rational(-1), thclone, d.clone()); thclone.shallowReduce(context, complexFormat, angleUnit, target); - Expression exp = Power(Constant(Ion::Charset::Exponential), thmuld); + Expression exp = Power::Builder(Constant(Ion::Charset::Exponential), thmuld); thmuld.shallowReduce(context, complexFormat, angleUnit, target); - Multiplication norm(rpowc, exp); + Multiplication norm = Multiplication::Builder(rpowc, exp); rpowc.shallowReduce(context, complexFormat, angleUnit, target); exp.shallowReduce(context, complexFormat, angleUnit, target); // TH = d*ln(r)+c*th Expression lnr = NaperianLogarithm::Builder(r); r.shallowReduce(context, complexFormat, angleUnit, target); - Multiplication dlnr(d, lnr); + Multiplication dlnr = Multiplication::Builder(d, lnr); lnr.shallowReduce(context, complexFormat, angleUnit, target); - Multiplication thc(th, c); + Multiplication thc = Multiplication::Builder(th, c); th.shallowReduce(context, complexFormat, angleUnit, target); - Expression argument = Addition(thc, dlnr); + Expression argument = Addition::Builder(thc, dlnr); thc.shallowReduce(context, complexFormat, angleUnit, target); dlnr.shallowReduce(context, complexFormat, angleUnit, target); diff --git a/poincare/src/condensed_sum_layout.cpp b/poincare/src/condensed_sum_layout.cpp index 68a74e188..3204fe357 100644 --- a/poincare/src/condensed_sum_layout.cpp +++ b/poincare/src/condensed_sum_layout.cpp @@ -37,12 +37,4 @@ KDPoint CondensedSumLayoutNode::positionOfChild(LayoutNode * child) { return KDPoint(x,y); } -CondensedSumLayout::CondensedSumLayout(Layout base, Layout subscript, Layout superscript) : - Layout(TreePool::sharedPool()->createTreeNode()) -{ - replaceChildAtIndexInPlace(0, base); - replaceChildAtIndexInPlace(1, subscript); - replaceChildAtIndexInPlace(2, superscript); -} - -} +} \ No newline at end of file diff --git a/poincare/src/confidence_interval.cpp b/poincare/src/confidence_interval.cpp index 1bf839197..c56b756a2 100644 --- a/poincare/src/confidence_interval.cpp +++ b/poincare/src/confidence_interval.cpp @@ -88,10 +88,10 @@ Expression ConfidenceInterval::shallowReduce(Context & context, Preferences::Com Rational r0 = static_cast(c0); Rational r1 = static_cast(c1); // Compute [r0-1/sqr(r1), r0+1/sqr(r1)] - Expression sqr = Power(r1, Rational(-1, 2)); - Matrix matrix; - matrix.addChildAtIndexInPlace(Addition(r0.clone(), Multiplication(Rational(-1), sqr.clone())), 0, 0); - matrix.addChildAtIndexInPlace(Addition(r0, sqr), 1, 1); + Expression sqr = Power::Builder(r1, Rational(-1, 2)); + Matrix matrix = Matrix::Builder(); + matrix.addChildAtIndexInPlace(Addition::Builder(r0.clone(), Multiplication::Builder(Rational(-1), sqr.clone())), 0, 0); + matrix.addChildAtIndexInPlace(Addition::Builder(r0, sqr), 1, 1); matrix.setDimensions(1, 2); replaceWithInPlace(matrix); matrix.deepReduceChildren(context, complexFormat, angleUnit, target); diff --git a/poincare/src/conjugate.cpp b/poincare/src/conjugate.cpp index 1b4467812..27ed8cc88 100644 --- a/poincare/src/conjugate.cpp +++ b/poincare/src/conjugate.cpp @@ -16,7 +16,7 @@ constexpr Expression::FunctionHelper Conjugate::s_functionHelper; int ConjugateNode::numberOfChildren() const { return Conjugate::s_functionHelper.numberOfChildren(); } Layout ConjugateNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { - return ConjugateLayout(childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits)); + return ConjugateLayout::Builder(childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits)); } int ConjugateNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -51,7 +51,7 @@ Expression Conjugate::shallowReduce(Context & context, Preferences::ComplexForma } if (c.type() == ExpressionNode::Type::ComplexCartesian) { ComplexCartesian complexChild = static_cast(c); - Multiplication m(Rational(-1), complexChild.imag()); + Multiplication m = Multiplication::Builder(Rational(-1), complexChild.imag()); complexChild.replaceChildAtIndexInPlace(1, m); m.shallowReduce(context, complexFormat, angleUnit, target); replaceWithInPlace(complexChild); diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index ebb6e2246..8272a2a79 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -378,7 +378,7 @@ Expression Decimal::shallowReduce() { Expression Decimal::shallowBeautify() { if (sign() == ExpressionNode::Sign::Negative) { Expression abs = setSign(ExpressionNode::Sign::Positive); - Opposite o; + Opposite o = Opposite::Builder(); replaceWithInPlace(o); o.replaceChildAtIndexInPlace(0, abs); return o; diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index 9f57e8286..48c6734c1 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -35,7 +35,7 @@ bool DivisionNode::childNeedsParenthesis(const TreeNode * child) const { Layout DivisionNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { const ExpressionNode * numerator = childAtIndex(0)->type() == Type::Parenthesis ? childAtIndex(0)->childAtIndex(0) : childAtIndex(0); const ExpressionNode * denominator = childAtIndex(1)->type() == Type::Parenthesis ? childAtIndex(1)->childAtIndex(0) : childAtIndex(1); - return FractionLayout(numerator->createLayout(floatDisplayMode, numberOfSignificantDigits), denominator->createLayout(floatDisplayMode, numberOfSignificantDigits)); + return FractionLayout::Builder(numerator->createLayout(floatDisplayMode, numberOfSignificantDigits), denominator->createLayout(floatDisplayMode, numberOfSignificantDigits)); } int DivisionNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -70,8 +70,6 @@ template MatrixComplex DivisionNode::computeOnMatrices(const Matr // Division -Division::Division() : Expression(TreePool::sharedPool()->createTreeNode()) {} - Expression Division::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { Expression e = Expression::defaultShallowReduce(); @@ -79,9 +77,9 @@ Expression Division::shallowReduce(Context & context, Preferences::ComplexFormat return e; } } - Expression p = Power(childAtIndex(1), Rational(-1)); - Multiplication m = Multiplication(childAtIndex(0), p); - p.shallowReduce(context, complexFormat, angleUnit, target); // Imagine Division(2,1). p would be 1^(-1) which can be simplified + Expression p = Power::Builder(childAtIndex(1), Rational(-1)); + Multiplication m = Multiplication::Builder(childAtIndex(0), p); + p.shallowReduce(context, complexFormat, angleUnit, target); // Imagine Division::Builder(2,1). p would be 1^(-1) which can be simplified replaceWithInPlace(m); return m.shallowReduce(context, complexFormat, angleUnit, target); } diff --git a/poincare/src/equal.cpp b/poincare/src/equal.cpp index ccb105e1a..dbcb1abaa 100644 --- a/poincare/src/equal.cpp +++ b/poincare/src/equal.cpp @@ -25,7 +25,7 @@ Expression EqualNode::shallowReduce(Context & context, Preferences::ComplexForma } Layout EqualNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { - HorizontalLayout result; + HorizontalLayout result = HorizontalLayout::Builder(); result.addOrMergeChildAtIndex(childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits), 0, false); result.addChildAtIndex(CharLayout('='), result.numberOfChildren(), result.numberOfChildren(), nullptr); result.addOrMergeChildAtIndex(childAtIndex(1)->createLayout(floatDisplayMode, numberOfSignificantDigits), result.numberOfChildren(), false); @@ -42,7 +42,7 @@ Evaluation EqualNode::templatedApproximate(Context& context, Preferences::Com } Expression Equal::standardEquation(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { - Expression sub = Subtraction(childAtIndex(0).clone(), childAtIndex(1).clone()); + Expression sub = Subtraction::Builder(childAtIndex(0).clone(), childAtIndex(1).clone()); return sub.reduce(context, complexFormat, angleUnit); } diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index cf1b1bbaf..544814670 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -184,7 +184,7 @@ bool Expression::getLinearCoefficients(char * variables, int maxVariableSize, Ex equation = polynomialCoefficients[0]; index++; } - constant[0] = Opposite(equation.clone()).reduce(context, complexFormat, angleUnit); + constant[0] = Opposite::Builder(equation.clone()).reduce(context, complexFormat, angleUnit); /* The expression can be linear on all coefficients taken one by one but * non-linear (ex: xy = 2). We delete the results and return false if one of * the coefficients contains a variable. */ @@ -519,12 +519,12 @@ Expression Expression::ExpressionWithoutSymbols(Expression e, Context & context) Expression Expression::radianToDegree() { // e*180/Pi - return Multiplication(*this, Rational(180), Power(Constant(Ion::Charset::SmallPi), Rational(-1))); + return Multiplication::Builder(*this, Rational(180), Power::Builder(Constant(Ion::Charset::SmallPi), Rational(-1))); } Expression Expression::degreeToRadian() { // e*Pi/180 - return Multiplication(*this, Rational(1, 180), Constant(Ion::Charset::SmallPi)); + return Multiplication::Builder(*this, Rational(1, 180), Constant(Ion::Charset::SmallPi)); } Expression Expression::reduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { @@ -619,7 +619,7 @@ Expression Expression::CreateComplexExpression(Expression ra, Expression tb, Pre Expression imag; if (!isZeroRa || isZeroTb) { if (isNegativeRa) { - real = Opposite(ra); + real = Opposite::Builder(ra); } else { real = ra; } @@ -628,21 +628,21 @@ Expression Expression::CreateComplexExpression(Expression ra, Expression tb, Pre if (isOneTb) { imag = Constant(Ion::Charset::IComplex); } else { - imag = Multiplication(tb , Constant(Ion::Charset::IComplex)); + imag = Multiplication::Builder(tb , Constant(Ion::Charset::IComplex)); } } if (imag.isUninitialized()) { return real; } else if (real.isUninitialized()) { if (isNegativeTb) { - return Opposite(imag); + return Opposite::Builder(imag); } else { return imag; } } else if (isNegativeTb) { - return Subtraction(real, imag); + return Subtraction::Builder(real, imag); } else { - return Addition(real, imag); + return Addition::Builder(real, imag); } } default: @@ -659,19 +659,19 @@ Expression Expression::CreateComplexExpression(Expression ra, Expression tb, Pre if (isOneTb) { arg = Constant(Ion::Charset::IComplex); } else { - arg = Multiplication(tb, Constant(Ion::Charset::IComplex)); + arg = Multiplication::Builder(tb, Constant(Ion::Charset::IComplex)); } if (isNegativeTb) { - arg = Opposite(arg); + arg = Opposite::Builder(arg); } - exp = Power(Constant(Ion::Charset::Exponential), arg); + exp = Power::Builder(Constant(Ion::Charset::Exponential), arg); } if (exp.isUninitialized()) { return norm; } else if (norm.isUninitialized()) { return exp; } else { - return Multiplication(norm, exp); + return Multiplication::Builder(norm, exp); } } } diff --git a/poincare/src/factor.cpp b/poincare/src/factor.cpp index 0f9ae90a3..d303b3a06 100644 --- a/poincare/src/factor.cpp +++ b/poincare/src/factor.cpp @@ -56,10 +56,10 @@ Expression Factor::shallowBeautify(Context & context, Preferences::ComplexFormat replaceWithInPlace(result); return result; } - result = Division(result, denominatorDecomp.squashUnaryHierarchyInPlace()); + result = Division::Builder(result, denominatorDecomp.squashUnaryHierarchyInPlace()); } if (r.sign() == ExpressionNode::Sign::Negative) { - result = Opposite(result); + result = Opposite::Builder(result); } replaceWithInPlace(result); return result; @@ -68,7 +68,7 @@ Expression Factor::shallowBeautify(Context & context, Preferences::ComplexFormat Multiplication Factor::createMultiplicationOfIntegerPrimeDecomposition(Integer i, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { assert(!i.isZero()); assert(!i.isNegative()); - Multiplication m; + Multiplication m = Multiplication::Builder(); Integer factors[Arithmetic::k_maxNumberOfPrimeFactors]; Integer coefficients[Arithmetic::k_maxNumberOfPrimeFactors]; int numberOfPrimeFactors = Arithmetic::PrimeFactorization(i, factors, coefficients, Arithmetic::k_maxNumberOfPrimeFactors); @@ -83,7 +83,7 @@ Multiplication Factor::createMultiplicationOfIntegerPrimeDecomposition(Integer i for (int index = 0; index < numberOfPrimeFactors; index++) { Expression factor = Rational(factors[index]); if (!coefficients[index].isOne()) { - factor = Power(factor, Rational(coefficients[index])); + factor = Power::Builder(factor, Rational(coefficients[index])); } m.addChildAtIndexInPlace(factor, m.numberOfChildren(), m.numberOfChildren()); } diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index 289c504ab..94a03f10b 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -59,7 +59,7 @@ Complex FactorialNode::computeOnComplex(const std::complex c, Preferences: } Layout FactorialNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { - HorizontalLayout result; + HorizontalLayout result = HorizontalLayout::Builder(); result.addOrMergeChildAtIndex(childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits), 0, false); int childrenCount = result.numberOfChildren(); result.addChildAtIndex(CharLayout('!'), childrenCount, childrenCount, nullptr); @@ -89,8 +89,6 @@ int FactorialNode::serialize(char * buffer, int bufferSize, Preferences::PrintFl return numberOfChar; } -Factorial::Factorial() : Expression(TreePool::sharedPool()->createTreeNode()) {} - Expression Factorial::shallowReduce() { { Expression e = Expression::defaultShallowReduce(); @@ -133,7 +131,7 @@ Expression Factorial::shallowBeautify() { || childAtIndex(0).type() == ExpressionNode::Type::Multiplication || childAtIndex(0).type() == ExpressionNode::Type::Power) { - Expression result = Factorial(Parenthesis(childAtIndex(0))); + Expression result = Factorial::Builder(Parenthesis::Builder(childAtIndex(0))); replaceWithInPlace(result); return result; } diff --git a/poincare/src/floor.cpp b/poincare/src/floor.cpp index 94ef4d3f4..8694f4509 100644 --- a/poincare/src/floor.cpp +++ b/poincare/src/floor.cpp @@ -16,7 +16,7 @@ constexpr Expression::FunctionHelper Floor::s_functionHelper; int FloorNode::numberOfChildren() const { return Floor::s_functionHelper.numberOfChildren(); } Layout FloorNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { - return FloorLayout(childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits)); + return FloorLayout::Builder(childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits)); } int FloorNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { diff --git a/poincare/src/fraction_layout.cpp b/poincare/src/fraction_layout.cpp index da2053c95..f18e88600 100644 --- a/poincare/src/fraction_layout.cpp +++ b/poincare/src/fraction_layout.cpp @@ -216,11 +216,4 @@ void FractionLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionCo ctx->fillRect(KDRect(p.x()+Metric::FractionAndConjugateHorizontalMargin, fractionLineY, layoutSize().width()-2*Metric::FractionAndConjugateHorizontalMargin, k_fractionLineHeight), expressionColor); } -FractionLayout::FractionLayout(Layout numerator, Layout denominator) : - Layout(TreePool::sharedPool()->createTreeNode()) -{ - replaceChildAtIndexInPlace(0, numerator); - replaceChildAtIndexInPlace(1, denominator); -} - -} +} \ No newline at end of file diff --git a/poincare/src/function.cpp b/poincare/src/function.cpp index 5ad9a6cbe..1eada76cb 100644 --- a/poincare/src/function.cpp +++ b/poincare/src/function.cpp @@ -105,7 +105,7 @@ Expression Function::replaceSymbolWithExpression(const SymbolAbstract & symbol, value = value.replaceSymbolWithExpression(xSymbol, xValue); Expression p = parent(); if (!p.isUninitialized() && p.node()->childNeedsParenthesis(value.node())) { - value = Parenthesis(value); + value = Parenthesis::Builder(value); } replaceWithInPlace(value); return value; diff --git a/poincare/src/horizontal_layout.cpp b/poincare/src/horizontal_layout.cpp index d3ad2c1d6..871ff5af3 100644 --- a/poincare/src/horizontal_layout.cpp +++ b/poincare/src/horizontal_layout.cpp @@ -226,7 +226,7 @@ KDPoint HorizontalLayoutNode::positionOfChild(LayoutNode * l) { bool HorizontalLayoutNode::willAddChildAtIndex(LayoutNode * l, int * index, int * currentNumberOfChildren, LayoutCursor * cursor) { if (m_numberOfChildren > 0) { - HorizontalLayout thisRef = HorizontalLayout(this); + HorizontalLayout thisRef(this); thisRef.removeEmptyChildBeforeInsertionAtIndex(index, currentNumberOfChildren, !l->mustHaveLeftSibling(), cursor); *currentNumberOfChildren = thisRef.numberOfChildren(); } @@ -353,33 +353,6 @@ bool HorizontalLayoutNode::willReplaceChild(LayoutNode * oldChild, LayoutNode * // HorizontalLayout -HorizontalLayout::HorizontalLayout() : Layout(TreePool::sharedPool()->createTreeNode()) {} - -HorizontalLayout::HorizontalLayout(Layout l) : HorizontalLayout() { - addChildAtIndexInPlace(l, 0, 0); -} - -HorizontalLayout::HorizontalLayout(Layout l1, Layout l2) : HorizontalLayout() { - addChildAtIndexInPlace(l1, 0, 0); - addChildAtIndexInPlace(l2, 1, 1); -} -HorizontalLayout::HorizontalLayout(Layout l1, Layout l2, Layout l3) : HorizontalLayout() { - addChildAtIndexInPlace(l1, 0, 0); - addChildAtIndexInPlace(l2, 1, 1); - addChildAtIndexInPlace(l3, 2, 2); -} -HorizontalLayout::HorizontalLayout(Layout l1, Layout l2, Layout l3, Layout l4) : HorizontalLayout() { - addChildAtIndexInPlace(l1, 0, 0); - addChildAtIndexInPlace(l2, 1, 1); - addChildAtIndexInPlace(l3, 2, 2); - addChildAtIndexInPlace(l4, 3, 3); -} -HorizontalLayout::HorizontalLayout(const Layout * children, size_t numberOfChildren) : HorizontalLayout() { - for (size_t i = 0; i < numberOfChildren; i++) { - addChildAtIndexInPlace(children[i], i, i); - } -} - void HorizontalLayout::addOrMergeChildAtIndex(Layout l, int index, bool removeEmptyChildren, LayoutCursor * cursor) { if (l.isHorizontal()) { mergeChildrenAtIndex(HorizontalLayout(static_cast(l.node())), index, removeEmptyChildren, cursor); diff --git a/poincare/src/integral.cpp b/poincare/src/integral.cpp index 77e59259f..00d64baad 100644 --- a/poincare/src/integral.cpp +++ b/poincare/src/integral.cpp @@ -33,7 +33,7 @@ Expression IntegralNode::replaceUnknown(const Symbol & symbol) { } Layout IntegralNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { - return IntegralLayout( + return IntegralLayout::Builder( childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits), childAtIndex(1)->createLayout(floatDisplayMode, numberOfSignificantDigits), childAtIndex(2)->createLayout(floatDisplayMode, numberOfSignificantDigits), diff --git a/poincare/src/layout.cpp b/poincare/src/layout.cpp index fb43bfa2e..da2c66c5e 100644 --- a/poincare/src/layout.cpp +++ b/poincare/src/layout.cpp @@ -97,7 +97,7 @@ void Layout::replaceWithJuxtapositionOf(Layout leftChild, Layout rightChild, Lay if (!p.isHorizontal()) { /* One of the children to juxtapose might be "this", so we cannot just call * replaceWith. */ - HorizontalLayout horizontalLayoutR; + HorizontalLayout horizontalLayoutR = HorizontalLayout::Builder(); p.replaceChild(*this, horizontalLayoutR, cursor); horizontalLayoutR.addOrMergeChildAtIndex(leftChild, 0, false); if (putCursorInTheMiddle) { @@ -286,7 +286,7 @@ void Layout::collapseSiblings(LayoutCursor * cursor) { if (node()->shouldCollapseSiblingsOnRight()) { Layout absorbingChild = childAtIndex(rightCollapsingAbsorbingChildIndex()); if (!absorbingChild.isHorizontal()) { - Layout horRef = HorizontalLayout(); + Layout horRef = HorizontalLayout::Builder(); replaceChild(absorbingChild, horRef, cursor, true); horRef.addChildAtIndexInPlace(absorbingChild, 0, 0); } @@ -295,7 +295,7 @@ void Layout::collapseSiblings(LayoutCursor * cursor) { if (node()->shouldCollapseSiblingsOnLeft()) { Layout absorbingChild = childAtIndex(leftCollapsingAbsorbingChildIndex()); if (!absorbingChild.isHorizontal()) { - Layout horRef = HorizontalLayout(); + Layout horRef = HorizontalLayout::Builder(); replaceChild(absorbingChild, horRef, cursor, true); horRef.addChildAtIndexInPlace(absorbingChild, 0, 0); } diff --git a/poincare/src/layout_cursor.cpp b/poincare/src/layout_cursor.cpp index 77a39a976..22a7915b4 100644 --- a/poincare/src/layout_cursor.cpp +++ b/poincare/src/layout_cursor.cpp @@ -74,15 +74,15 @@ void LayoutCursor::move(MoveDirection direction, bool * shouldRecomputeLayout) { void LayoutCursor::addEmptyExponentialLayout() { EmptyLayout emptyLayout; - HorizontalLayout sibling = HorizontalLayout( + HorizontalLayout sibling = HorizontalLayout::Builder( CharLayout(Ion::Charset::Exponential), - VerticalOffsetLayout(emptyLayout, VerticalOffsetLayoutNode::Type::Superscript)); + VerticalOffsetLayout::Builder(emptyLayout, VerticalOffsetLayoutNode::Type::Superscript)); m_layout.addSibling(this, sibling, false); m_layout = emptyLayout; } void LayoutCursor::addEmptyMatrixLayout() { - MatrixLayout matrixLayout = MatrixLayout( + MatrixLayout matrixLayout = MatrixLayout::Builder( EmptyLayout(EmptyLayoutNode::Color::Yellow), EmptyLayout(EmptyLayoutNode::Color::Grey), EmptyLayout(EmptyLayoutNode::Color::Grey), @@ -93,31 +93,31 @@ void LayoutCursor::addEmptyMatrixLayout() { } void LayoutCursor::addEmptySquareRootLayout() { - HorizontalLayout child1 = HorizontalLayout(EmptyLayout()); - NthRootLayout newChild = NthRootLayout(child1); + HorizontalLayout child1 = HorizontalLayout::Builder(EmptyLayout()); + NthRootLayout newChild = NthRootLayout::Builder(child1); m_layout.addSibling(this, newChild, false); m_layout = newChild.childAtIndex(0); ((Layout *)&newChild)->collapseSiblings(this); } void LayoutCursor::addEmptyPowerLayout() { - VerticalOffsetLayout offsetLayout = VerticalOffsetLayout(EmptyLayout(), VerticalOffsetLayoutNode::Type::Superscript); + VerticalOffsetLayout offsetLayout = VerticalOffsetLayout::Builder(EmptyLayout(), VerticalOffsetLayoutNode::Type::Superscript); privateAddEmptyPowerLayout(offsetLayout); m_layout = offsetLayout.childAtIndex(0); } void LayoutCursor::addEmptySquarePowerLayout() { - VerticalOffsetLayout offsetLayout = VerticalOffsetLayout(CharLayout('2'), VerticalOffsetLayoutNode::Type::Superscript); + VerticalOffsetLayout offsetLayout = VerticalOffsetLayout::Builder(CharLayout('2'), VerticalOffsetLayoutNode::Type::Superscript); privateAddEmptyPowerLayout(offsetLayout); } void LayoutCursor::addEmptyTenPowerLayout() { EmptyLayout emptyLayout; - HorizontalLayout sibling = HorizontalLayout( + HorizontalLayout sibling = HorizontalLayout::Builder( CharLayout(Ion::Charset::MiddleDot), CharLayout('1'), CharLayout('0'), - VerticalOffsetLayout( + VerticalOffsetLayout::Builder( emptyLayout, VerticalOffsetLayoutNode::Type::Superscript)); m_layout.addSibling(this, sibling, false); @@ -125,9 +125,9 @@ void LayoutCursor::addEmptyTenPowerLayout() { } void LayoutCursor::addFractionLayoutAndCollapseSiblings() { - HorizontalLayout child1 = HorizontalLayout(EmptyLayout()); - HorizontalLayout child2 = HorizontalLayout(EmptyLayout()); - FractionLayout newChild = FractionLayout(child1, child2); + HorizontalLayout child1 = HorizontalLayout::Builder(EmptyLayout()); + HorizontalLayout child2 = HorizontalLayout::Builder(EmptyLayout()); + FractionLayout newChild = FractionLayout::Builder(child1, child2); m_layout.addSibling(this, newChild, true); Layout(newChild.node()).collapseSiblings(this); } @@ -150,12 +150,12 @@ void LayoutCursor::insertText(const char * text) { if (text[i] == Ion::Charset::MultiplicationSign) { newChild = CharLayout(Ion::Charset::MiddleDot); } else if (text[i] == '(') { - newChild = LeftParenthesisLayout(); + newChild = LeftParenthesisLayout::Builder(); if (pointedChild.isUninitialized()) { pointedChild = newChild; } } else if (text[i] == ')') { - newChild = RightParenthesisLayout(); + newChild = RightParenthesisLayout::Builder(); } /* We never insert text with brackets for now. Removing this code saves the * binary file 2K. */ @@ -218,7 +218,7 @@ void LayoutCursor::privateAddEmptyPowerLayout(VerticalOffsetLayout v) { } // Else, add an empty base EmptyLayout e = EmptyLayout(); - HorizontalLayout newChild = HorizontalLayout(e, v); + HorizontalLayout newChild = HorizontalLayout::Builder(e, v); m_layout.addSibling(this, newChild, true); } diff --git a/poincare/src/layout_helper.cpp b/poincare/src/layout_helper.cpp index 750bfe098..9d7c584a6 100644 --- a/poincare/src/layout_helper.cpp +++ b/poincare/src/layout_helper.cpp @@ -11,7 +11,7 @@ namespace Poincare { Layout LayoutHelper::Infix(const Expression & expression, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits, const char * operatorName) { int numberOfChildren = expression.numberOfChildren(); assert(numberOfChildren > 1); - HorizontalLayout result; + HorizontalLayout result = HorizontalLayout::Builder(); result.addOrMergeChildAtIndex(expression.childAtIndex(0).createLayout(floatDisplayMode, numberOfSignificantDigits), 0, true); for (int i = 1; i < numberOfChildren; i++) { result.addOrMergeChildAtIndex(String(operatorName, strlen(operatorName)), result.numberOfChildren(), true); @@ -24,12 +24,12 @@ Layout LayoutHelper::Infix(const Expression & expression, Preferences::PrintFloa } Layout LayoutHelper::Prefix(const Expression & expression, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits, const char * operatorName) { - HorizontalLayout result; + HorizontalLayout result = HorizontalLayout::Builder(); // Add the operator name. result.addOrMergeChildAtIndex(String(operatorName, strlen(operatorName)), 0, true); // Create the layout of arguments separated by commas. - HorizontalLayout args; + HorizontalLayout args = HorizontalLayout::Builder(); int numberOfChildren = expression.numberOfChildren(); if (numberOfChildren > 0) { args.addOrMergeChildAtIndex(expression.childAtIndex(0).createLayout(floatDisplayMode, numberOfSignificantDigits), 0, true); @@ -44,18 +44,18 @@ Layout LayoutHelper::Prefix(const Expression & expression, Preferences::PrintFlo } Layout LayoutHelper::Parentheses(Layout layout, bool cloneLayout) { - HorizontalLayout result; - result.addChildAtIndex(LeftParenthesisLayout(), 0, 0, nullptr); + HorizontalLayout result = HorizontalLayout::Builder(); + result.addChildAtIndex(LeftParenthesisLayout::Builder(), 0, 0, nullptr); if (!layout.isUninitialized()) { result.addOrMergeChildAtIndex(cloneLayout ? layout.clone() : layout, 1, true); } - result.addChildAtIndex(RightParenthesisLayout(), result.numberOfChildren(), result.numberOfChildren(), nullptr); + result.addChildAtIndex(RightParenthesisLayout::Builder(), result.numberOfChildren(), result.numberOfChildren(), nullptr); return result; } HorizontalLayout LayoutHelper::String(const char * buffer, int bufferLen, const KDFont * font) { assert(bufferLen > 0); - HorizontalLayout resultLayout; + HorizontalLayout resultLayout = HorizontalLayout::Builder(); for (int i = 0; i < bufferLen; i++) { resultLayout.addChildAtIndex(CharLayout(buffer[i], font), i, i, nullptr); } @@ -64,7 +64,7 @@ HorizontalLayout LayoutHelper::String(const char * buffer, int bufferLen, const Layout LayoutHelper::Logarithm(Layout argument, Layout index) { HorizontalLayout resultLayout = String("log", 3); - VerticalOffsetLayout offsetLayout = VerticalOffsetLayout(index, VerticalOffsetLayoutNode::Type::Subscript); + VerticalOffsetLayout offsetLayout = VerticalOffsetLayout::Builder(index, VerticalOffsetLayoutNode::Type::Subscript); resultLayout.addChildAtIndex(offsetLayout, resultLayout.numberOfChildren(), resultLayout.numberOfChildren(), nullptr); resultLayout.addOrMergeChildAtIndex(Parentheses(argument, false), resultLayout.numberOfChildren(), true); return resultLayout; diff --git a/poincare/src/left_parenthesis_layout.cpp b/poincare/src/left_parenthesis_layout.cpp index 150af8b98..8ddd2dea5 100644 --- a/poincare/src/left_parenthesis_layout.cpp +++ b/poincare/src/left_parenthesis_layout.cpp @@ -59,6 +59,4 @@ void LeftParenthesisLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expre RenderWithChildHeight(ParenthesisLayoutNode::ChildHeightGivenLayoutHeight(layoutSize().height()), ctx, p, expressionColor, backgroundColor); } -LeftParenthesisLayout::LeftParenthesisLayout() : Layout(TreePool::sharedPool()->createTreeNode()) {} - } diff --git a/poincare/src/left_square_bracket_layout.cpp b/poincare/src/left_square_bracket_layout.cpp index b380e9b8c..2a8d85c92 100644 --- a/poincare/src/left_square_bracket_layout.cpp +++ b/poincare/src/left_square_bracket_layout.cpp @@ -8,6 +8,4 @@ void LeftSquareBracketLayoutNode::render(KDContext * ctx, KDPoint p, KDColor exp ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y() + childHeight(), k_bracketWidth, k_lineThickness), expressionColor); } -LeftSquareBracketLayout::LeftSquareBracketLayout() : Layout(TreePool::sharedPool()->createTreeNode()) {} - } diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index e812c4a39..9e69d9de8 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -160,7 +160,7 @@ Expression Logarithm::shallowReduce(Context & context, Preferences::ComplexForma Expression x = p.childAtIndex(0); Expression y = p.childAtIndex(1); replaceChildInPlace(p, x); - Multiplication mult(y); + Multiplication mult = Multiplication::Builder(y); replaceWithInPlace(mult); mult.addChildAtIndexInPlace(*this, 1, 1); // --> y*log(x,b) shallowReduce(context, complexFormat, angleUnit, target); // reduce log (ie log(e, e) = 1) @@ -168,7 +168,7 @@ Expression Logarithm::shallowReduce(Context & context, Preferences::ComplexForma } // log(x*y, b)->log(x,b)+log(y, b) if x,y>0 if (!letLogAtRoot && c.type() == ExpressionNode::Type::Multiplication) { - Addition a = Addition(); + Addition a = Addition::Builder(); for (int i = 0; i < c.numberOfChildren()-1; i++) { Expression factor = c.childAtIndex(i); if (factor.sign(&context) == ExpressionNode::Sign::Positive) { @@ -190,7 +190,7 @@ Expression Logarithm::shallowReduce(Context & context, Preferences::ComplexForma // log(r) with r Rational if (!letLogAtRoot && c.type() == ExpressionNode::Type::Rational) { Rational r = static_cast(c); - Addition a; + Addition a = Addition::Builder(); // if the log base is Integer: log_b(r) = c + log_b(r') with r = b^c*r' if (childAtIndex(1).type() == ExpressionNode::Type::Rational && childAtIndex(1).convert().integerDenominator().isOne()) { Integer b = childAtIndex(1).convert().signedIntegerNumerator(); @@ -320,17 +320,17 @@ Expression Logarithm::splitLogarithmInteger(Integer i, bool isDenominator, Conte if (!isDenominator) { return e; } - Multiplication m = Multiplication(Rational(-1), e); + Multiplication m = Multiplication::Builder(Rational(-1), e); return m; } - Addition a; + Addition a = Addition::Builder(); for (int index = 0; index < numberOfPrimeFactors; index++) { if (isDenominator) { coefficients[index].setNegative(true); } Logarithm e = clone().convert(); e.replaceChildAtIndexInPlace(0, Rational(factors[index])); - Multiplication m = Multiplication(Rational(coefficients[index]), e); + Multiplication m = Multiplication::Builder(Rational(coefficients[index]), e); e.simpleShallowReduce(context, complexFormat, angleUnit); a.addChildAtIndexInPlace(m, a.numberOfChildren(), a.numberOfChildren()); m.shallowReduce(context, complexFormat, angleUnit, target); diff --git a/poincare/src/matrix.cpp b/poincare/src/matrix.cpp index 181fc72a3..66177d840 100644 --- a/poincare/src/matrix.cpp +++ b/poincare/src/matrix.cpp @@ -23,7 +23,7 @@ int MatrixNode::polynomialDegree(Context & context, const char * symbolName) con Layout MatrixNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { assert(numberOfChildren() > 0); - MatrixLayout layout; + MatrixLayout layout = MatrixLayout::Builder(); for (ExpressionNode * c : children()) { layout.addChildAtIndex(c->createLayout(floatDisplayMode, numberOfSignificantDigits), layout.numberOfChildren(), layout.numberOfChildren(), nullptr); } @@ -196,7 +196,7 @@ Matrix Matrix::rowCanonize(Context & context, Preferences::ComplexFormat complex if (!determinant.isUninitialized()) { determinant.addChildAtIndexInPlace(divisor.clone(), 0, determinant.numberOfChildren()); } for (int j = k+1; j < n; j++) { Expression opHJ = matrixChild(h, j); - Expression newOpHJ = Division(opHJ, divisor.clone()); + Expression newOpHJ = Division::Builder(opHJ, divisor.clone()); replaceChildAtIndexInPlace(h*n+j, newOpHJ); newOpHJ = newOpHJ.shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::System); } @@ -208,7 +208,7 @@ Matrix Matrix::rowCanonize(Context & context, Preferences::ComplexFormat complex Expression factor = matrixChild(i, k); for (int j = k+1; j < n; j++) { Expression opIJ = matrixChild(i, j); - Expression newOpIJ = Subtraction(opIJ, Multiplication(matrixChild(h, j).clone(), factor.clone())); + Expression newOpIJ = Subtraction::Builder(opIJ, Multiplication::Builder(matrixChild(h, j).clone(), factor.clone())); replaceChildAtIndexInPlace(i*n+j, newOpIJ); newOpIJ.childAtIndex(1).shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::System); newOpIJ = newOpIJ.shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::System); @@ -305,7 +305,7 @@ Expression Matrix::inverse(Context & context, Preferences::ComplexFormat complex } int dim = m_numberOfRows; /* Create the matrix inv = (A|I) with A the input matrix and I the dim identity matrix */ - Matrix AI; + Matrix AI = Matrix::Builder(); for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { AI.addChildAtIndexInPlace(matrixChild(i, j), i*2*dim+j, i*2*dim+j); diff --git a/poincare/src/matrix_complex.cpp b/poincare/src/matrix_complex.cpp index 5cabea7a7..7e7d34906 100644 --- a/poincare/src/matrix_complex.cpp +++ b/poincare/src/matrix_complex.cpp @@ -38,7 +38,7 @@ bool MatrixComplexNode::isUndefined() const { template Expression MatrixComplexNode::complexToExpression(Preferences::ComplexFormat complexFormat) const { - Matrix matrix = Matrix::EmptyMatrix(); + Matrix matrix = Matrix::Builder(); int i = 0; for (EvaluationNode * c : this->children()) { if (c->type() == EvaluationNode::Type::Complex) { diff --git a/poincare/src/matrix_dimension.cpp b/poincare/src/matrix_dimension.cpp index cf33a7c03..d9cd3e758 100644 --- a/poincare/src/matrix_dimension.cpp +++ b/poincare/src/matrix_dimension.cpp @@ -48,14 +48,14 @@ Expression MatrixDimension::shallowReduce() { #if MATRIX_EXACT_REDUCING if (c.type() == ExpressionNode::Type::Matrix) { Matrix m = static_cast(c); - Matrix result; + Matrix result = Matrix::Builder(); result.addChildAtIndexInPlace(Rational(m.numberOfRows()), 0, 0); result.addChildAtIndexInPlace(Rational(m.numberOfColumns()), 1, 1); result.setDimensions(1, 2); return result; } if (!c.recursivelyMatches(Expression::IsMatrix)) { - Matrix result; + Matrix result = Matrix::Builder(); result.addChildAtIndexInPlace(Rational(1), 0, 0); result.addChildAtIndexInPlace(Rational(1), 1, 1); result.setDimensions(1, 2); @@ -64,7 +64,7 @@ Expression MatrixDimension::shallowReduce() { return *this; #else if (c.type() != ExpressionNode::Type::Matrix) { - Matrix result; + Matrix result = Matrix::Builder(); result.addChildAtIndexInPlace(Rational(1), 0, 0); result.addChildAtIndexInPlace(Rational(1), 1, 1); result.setDimensions(1, 2); diff --git a/poincare/src/matrix_inverse.cpp b/poincare/src/matrix_inverse.cpp index e00cb9f56..16e29a94a 100644 --- a/poincare/src/matrix_inverse.cpp +++ b/poincare/src/matrix_inverse.cpp @@ -53,7 +53,7 @@ Expression MatrixInverse::shallowReduce(Context & context, Preferences::ComplexF #if MATRIX_EXACT_REDUCING #if 0 if (!c.recursivelyMatches(Expression::IsMatrix)) { - return Power(c, Rational(-1).shallowReduce(context, complexFormat, angleUnit, target); + return Power::Builder(c, Rational(-1).shallowReduce(context, complexFormat, angleUnit, target); } if (c.type() == ExpressionNode::Type::Matrix) { Matrix mat = static_cast(c); @@ -65,7 +65,7 @@ Expression MatrixInverse::shallowReduce(Context & context, Preferences::ComplexF #endif #else if (c.type() != ExpressionNode::Type::Matrix) { - Expression result = Power(c, Rational(-1)); + Expression result = Power::Builder(c, Rational(-1)); replaceWithInPlace(result); result = result.shallowReduce(context, complexFormat, angleUnit, target); return result; diff --git a/poincare/src/matrix_layout.cpp b/poincare/src/matrix_layout.cpp index 57b085ab0..32d07c60f 100644 --- a/poincare/src/matrix_layout.cpp +++ b/poincare/src/matrix_layout.cpp @@ -266,16 +266,4 @@ void MatrixLayoutNode::didReplaceChildAtIndex(int index, LayoutCursor * cursor, } } -MatrixLayout::MatrixLayout(const MatrixLayoutNode * n) : GridLayout(n) {} -MatrixLayout::MatrixLayout() : GridLayout(TreePool::sharedPool()->createTreeNode()) {} -MatrixLayout::MatrixLayout(Layout l1, Layout l2, Layout l3, Layout l4) : - MatrixLayout() -{ - addChildAtIndexInPlace(l1, 0, 0); - addChildAtIndexInPlace(l2, 1, 1); - addChildAtIndexInPlace(l3, 2, 2); - addChildAtIndexInPlace(l4, 3, 3); - setDimensions(2, 2); -} - } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index ac04919e1..7e927711f 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -108,8 +108,6 @@ Expression MultiplicationNode::denominator(Context & context, Preferences::Compl /* Multiplication */ -Multiplication::Multiplication() : NAryExpression(TreePool::sharedPool()->createTreeNode()) {} - template void Multiplication::computeOnArrays(T * m, T * n, T * result, int mNumberOfColumns, int mNumberOfRows, int nNumberOfColumns) { for (int i = 0; i < mNumberOfRows; i++) { @@ -148,7 +146,7 @@ Expression Multiplication::shallowBeautify(Context & context, Preferences::Compl Expression noNegativeNumeral = makePositiveAnyNegativeNumeralFactor(context, complexFormat, angleUnit, target); // If one negative numeral factor was made positive, we turn the expression in an Opposite if (!noNegativeNumeral.isUninitialized()) { - Opposite o = Opposite(); + Opposite o = Opposite::Builder(); noNegativeNumeral.replaceWithInPlace(o); o.replaceChildAtIndexInPlace(0, noNegativeNumeral); return o; @@ -166,7 +164,7 @@ Expression Multiplication::shallowBeautify(Context & context, Preferences::Compl for (int i = 0; i < thisExp.numberOfChildren(); i++) { const Expression o = thisExp.childAtIndex(i); if (o.type() == ExpressionNode::Type::Addition) { - Parenthesis p(o); + Parenthesis p = Parenthesis::Builder(o); thisExp.replaceChildAtIndexInPlace(i, p); } } @@ -190,7 +188,7 @@ Expression Multiplication::shallowBeautify(Context & context, Preferences::Compl numeratorOperand = numeratorChild0; } Expression originalParent = numeratorOperand.parent(); - Division d; + Division d = Division::Builder(); numeratorOperand.replaceWithInPlace(d); d.replaceChildAtIndexInPlace(0, numeratorOperand); d.replaceChildAtIndexInPlace(1, denominatorOperand); @@ -218,18 +216,18 @@ int Multiplication::getPolynomialCoefficients(Context & context, const char * sy assert(degI <= Expression::k_maxPolynomialDegree); for (int j = deg; j > 0; j--) { // new coefficients[j] = b(0)*a(j)+b(1)*a(j-1)+b(2)*a(j-2)+... - Addition a; + Addition a = Addition::Builder(); int jbis = j > degI ? degI : j; for (int l = 0; l <= jbis ; l++) { // Always copy the a and b coefficients are they are used multiple times - a.addChildAtIndexInPlace(Multiplication(intermediateCoefficients[l].clone(), coefficients[j-l].clone()), a.numberOfChildren(), a.numberOfChildren()); + a.addChildAtIndexInPlace(Multiplication::Builder(intermediateCoefficients[l].clone(), coefficients[j-l].clone()), a.numberOfChildren(), a.numberOfChildren()); } /* a(j) and b(j) are used only to compute coefficient at rank >= j, we * can delete them as we compute new coefficient by decreasing ranks. */ coefficients[j] = a; } // new coefficients[0] = a(0)*b(0) - coefficients[0] = Multiplication(coefficients[0], intermediateCoefficients[0]); + coefficients[0] = Multiplication::Builder(coefficients[0], intermediateCoefficients[0]); } return deg; } @@ -322,7 +320,7 @@ Expression Multiplication::privateShallowReduce(Context & context, Preferences:: int i2 = e%m; int i1 = e/m; for (int j = 0; j < n; j++) { - Expression * mult = new Multiplication(currentMatrix->childAtIndex(j+om*i1), resultMatrix->childAtIndex(j*m+i2), true); + Expression * mult = new Multiplication::Builder(currentMatrix->childAtIndex(j+om*i1), resultMatrix->childAtIndex(j*m+i2), true); static_cast(newMatrixOperands[e])->addOperand(mult); mult->shallowReduce(context, complexFormat, angleUnit, target); } @@ -538,8 +536,8 @@ void Multiplication::mergeMultiplicationChildrenInPlace() { void Multiplication::factorizeBase(int i, int j, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { /* This function factorizes two children which have a common base. For example - * if this is Multiplication(pi^2, pi^3), then pi^2 and pi^3 could be merged - * and this turned into Multiplication(pi^5). */ + * if this is Multiplication::Builder(pi^2, pi^3), then pi^2 and pi^3 could be merged + * and this turned into Multiplication::Builder(pi^5). */ Expression e = childAtIndex(j); // Step 1: Get rid of the child j @@ -553,9 +551,9 @@ void Multiplication::mergeInChildByFactorizingBase(int i, Expression e, Context * and childAtIndex(i) are supposed to have a common base. */ // Step 1: Find the new exponent - Expression s = Addition(CreateExponent(childAtIndex(i)), CreateExponent(e)); // pi^2*pi^3 -> pi^(2+3) -> pi^5 + Expression s = Addition::Builder(CreateExponent(childAtIndex(i)), CreateExponent(e)); // pi^2*pi^3 -> pi^(2+3) -> pi^5 // Step 2: Create the new Power - Expression p = Power(Base(childAtIndex(i)), s); // pi^2*pi^-2 -> pi^0 -> 1 + Expression p = Power::Builder(Base(childAtIndex(i)), s); // pi^2*pi^-2 -> pi^0 -> 1 s.shallowReduce(context, complexFormat, angleUnit, target); // Step 3: Replace one of the child replaceChildAtIndexInPlace(i, p); @@ -570,10 +568,10 @@ void Multiplication::mergeInChildByFactorizingBase(int i, Expression e, Context void Multiplication::factorizeExponent(int i, int j, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { /* This function factorizes children which share a common exponent. For - * example, it turns Multiplication(2^x,3^x) into Multiplication(6^x). */ + * example, it turns Multiplication::Builder(2^x,3^x) into Multiplication::Builder(6^x). */ // Step 1: Find the new base - Expression m = Multiplication(Base(childAtIndex(i)), Base(childAtIndex(j))); // 2^x*3^x -> (2*3)^x -> 6^x + Expression m = Multiplication::Builder(Base(childAtIndex(i)), Base(childAtIndex(j))); // 2^x*3^x -> (2*3)^x -> 6^x // Step 2: Get rid of one of the children removeChildAtIndexInPlace(j); // Step 3: Replace the other child @@ -595,7 +593,7 @@ Expression Multiplication::distributeOnOperandAtIndex(int i, Context & context, assert(i >= 0 && i < numberOfChildren()); assert(childAtIndex(i).type() == ExpressionNode::Type::Addition); - Addition a; + Addition a = Addition::Builder(); Expression childI = childAtIndex(i); int numberOfAdditionTerms = childI.numberOfChildren(); for (int j = 0; j < numberOfAdditionTerms; j++) { @@ -635,13 +633,13 @@ void Multiplication::addMissingFactors(Expression factor, Context & context, Pre * base if any. Otherwise, we add it as an new child. */ for (int i = 0; i < numberOfChildren(); i++) { if (TermsHaveIdenticalBase(childAtIndex(i), factor)) { - Expression sub = Subtraction(CreateExponent(childAtIndex(i)), CreateExponent(factor)).deepReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); + Expression sub = Subtraction::Builder(CreateExponent(childAtIndex(i)), CreateExponent(factor)).deepReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); if (sub.sign(&context) == ExpressionNode::Sign::Negative) { // index[0] < index[1] - sub = Opposite(sub); + sub = Opposite::Builder(sub); if (factor.type() == ExpressionNode::Type::Power) { factor.replaceChildAtIndexInPlace(1, sub); } else { - factor = Power(factor, sub); + factor = Power::Builder(factor, sub); } sub.shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); mergeInChildByFactorizingBase(i, factor, context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); @@ -677,20 +675,20 @@ void Multiplication::factorizeSineAndCosine(int i, int j, Context & context, Pre if (p.isRationalOne()) { replaceChildAtIndexInPlace(i, tan); } else { - replaceChildAtIndexInPlace(i, Power(tan, p)); + replaceChildAtIndexInPlace(i, Power::Builder(tan, p)); } childAtIndex(i).shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); // Replace cos(x)^q by cos(x)^(p+q) - replaceChildAtIndexInPlace(j, Power(Base(childAtIndex(j)), sumPQ)); + replaceChildAtIndexInPlace(j, Power::Builder(Base(childAtIndex(j)), sumPQ)); childAtIndex(j).shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); } else { // Replace cos(x)^q by tan(x)^(-q) - Expression newPower = Power(tan, Number::Multiplication(q, Rational(-1))); + Expression newPower = Power::Builder(tan, Number::Multiplication(q, Rational(-1))); newPower.childAtIndex(1).shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); replaceChildAtIndexInPlace(j, newPower); newPower.shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); // Replace sin(x)^p by sin(x)^(p+q) - replaceChildAtIndexInPlace(i, Power(Base(childAtIndex(i)), sumPQ)); + replaceChildAtIndexInPlace(i, Power::Builder(Base(childAtIndex(i)), sumPQ)); childAtIndex(i).shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); } } @@ -745,7 +743,7 @@ bool Multiplication::TermHasNumeralExponent(const Expression & e) { Expression Multiplication::mergeNegativePower(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { /* mergeNegativePower groups all factors that are power of form a^(-b) together * for instance, a^(-1)*b^(-c)*c = c*(a*b^c)^(-1) */ - Multiplication m; + Multiplication m = Multiplication::Builder(); // Special case for rational p/q: if q != 1, q should be at denominator if (childAtIndex(0).type() == ExpressionNode::Type::Rational && !childAtIndex(0).convert().integerDenominator().isOne()) { Rational r = childAtIndex(0).convert(); @@ -780,7 +778,7 @@ Expression Multiplication::mergeNegativePower(Context & context, Preferences::Co return *this; } m.sortChildrenInPlace([](const ExpressionNode * e1, const ExpressionNode * e2, bool canBeInterrupted) { return ExpressionNode::SimplificationOrder(e1, e2, true, canBeInterrupted); }, true); - Power p(m.squashUnaryHierarchyInPlace(), Rational(-1)); + Power p = Power::Builder(m.squashUnaryHierarchyInPlace(), Rational(-1)); addChildAtIndexInPlace(p, 0, numberOfChildren()); sortChildrenInPlace([](const ExpressionNode * e1, const ExpressionNode * e2, bool canBeInterrupted) { return ExpressionNode::SimplificationOrder(e1, e2, true, canBeInterrupted); }, true); return squashUnaryHierarchyInPlace(); diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index e570abd7e..5c1cac751 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -19,7 +19,7 @@ constexpr Expression::FunctionHelper NthRoot::s_functionHelper; int NthRootNode::numberOfChildren() const { return NthRoot::s_functionHelper.numberOfChildren(); } Layout NthRootNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { - return NthRootLayout( + return NthRootLayout::Builder( childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits), childAtIndex(1)->createLayout(floatDisplayMode, numberOfSignificantDigits)); } @@ -75,8 +75,8 @@ Expression NthRoot::shallowReduce(Context & context, Preferences::ComplexFormat return Undefined(); } #endif - Expression invIndex = Power(childAtIndex(1), Rational(-1)); - Power p = Power(childAtIndex(0), invIndex); + Expression invIndex = Power::Builder(childAtIndex(1), Rational(-1)); + Power p = Power::Builder(childAtIndex(0), invIndex); invIndex.shallowReduce(context, complexFormat, angleUnit, target); replaceWithInPlace(p); return p.shallowReduce(context, complexFormat, angleUnit, target); diff --git a/poincare/src/nth_root_layout.cpp b/poincare/src/nth_root_layout.cpp index 208952e46..b19ea55d2 100644 --- a/poincare/src/nth_root_layout.cpp +++ b/poincare/src/nth_root_layout.cpp @@ -270,16 +270,4 @@ void NthRootLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionCol } } -NthRootLayout::NthRootLayout(Layout radicand) : NthRootLayout() { - replaceChildAtIndexInPlace(0, radicand); -} - -NthRootLayout::NthRootLayout(Layout radicand, Layout index) : NthRootLayout() { - replaceChildAtIndexInPlace(0, radicand); - addChildAtIndexInPlace(index, 1, 1); - static_cast(node())->setNumberOfChildren(2); -} - -NthRootLayout::NthRootLayout() : Layout(TreePool::sharedPool()->createTreeNode()) {} - } diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index 927f832c6..12aa72853 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -41,7 +41,7 @@ bool OppositeNode::childNeedsParenthesis(const TreeNode * child) const { } Layout OppositeNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { - HorizontalLayout result = HorizontalLayout(CharLayout('-')); + HorizontalLayout result = HorizontalLayout::Builder(CharLayout('-')); if (childAtIndex(0)->type() == Type::Opposite) { result.addOrMergeChildAtIndex(LayoutHelper::Parentheses(childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits), false), 1, false); } else { @@ -69,8 +69,6 @@ Expression OppositeNode::shallowReduce(Context & context, Preferences::ComplexFo /* Simplification */ -Opposite::Opposite() : Expression(TreePool::sharedPool()->createTreeNode()) {} - Expression Opposite::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { Expression result = Expression::defaultShallowReduce(); if (result.isUndefined()) { @@ -79,7 +77,7 @@ Expression Opposite::shallowReduce(Context & context, Preferences::ComplexFormat Expression child = result.childAtIndex(0); #if MATRIX_EXACT_REDUCING #endif - result = Multiplication(Rational(-1), child); + result = Multiplication::Builder(Rational(-1), child); replaceWithInPlace(result); return result.shallowReduce(context, complexFormat, angleUnit, target); } diff --git a/poincare/src/parsing/parser.cpp b/poincare/src/parsing/parser.cpp index 26eb10d01..ae1024e34 100644 --- a/poincare/src/parsing/parser.cpp +++ b/poincare/src/parsing/parser.cpp @@ -155,7 +155,7 @@ void Parser::parseNumber(Expression & leftHandSide, Token::Type stoppingType) { void Parser::parsePlus(Expression & leftHandSide, Token::Type stoppingType) { Expression rightHandSide; if (parseBinaryOperator(leftHandSide, rightHandSide, Token::Plus)) { - leftHandSide = Addition(leftHandSide, rightHandSide); + leftHandSide = Addition::Builder(leftHandSide, rightHandSide); } } @@ -173,41 +173,41 @@ void Parser::parseMinus(Expression & leftHandSide, Token::Type stoppingType) { if (m_status != Status::Progress) { return; } - leftHandSide = Opposite(rightHandSide); + leftHandSide = Opposite::Builder(rightHandSide); } else { Expression rightHandSide = parseUntil(Token::Minus); // Subtraction is left-associative if (m_status != Status::Progress) { return; } - leftHandSide = Subtraction(leftHandSide, rightHandSide); + leftHandSide = Subtraction::Builder(leftHandSide, rightHandSide); } } void Parser::parseTimes(Expression & leftHandSide, Token::Type stoppingType) { Expression rightHandSide; if (parseBinaryOperator(leftHandSide, rightHandSide, Token::Times)) { - leftHandSide = Multiplication(leftHandSide, rightHandSide); + leftHandSide = Multiplication::Builder(leftHandSide, rightHandSide); } } void Parser::parseSlash(Expression & leftHandSide, Token::Type stoppingType) { Expression rightHandSide; if (parseBinaryOperator(leftHandSide, rightHandSide, Token::Slash)) { - leftHandSide = Division(leftHandSide, rightHandSide); + leftHandSide = Division::Builder(leftHandSide, rightHandSide); } } void Parser::parseImplicitTimes(Expression & leftHandSide, Token::Type stoppingType) { Expression rightHandSide; if (parseBinaryOperator(leftHandSide, rightHandSide, Token::Slash)) { - leftHandSide = Multiplication(leftHandSide, rightHandSide); + leftHandSide = Multiplication::Builder(leftHandSide, rightHandSide); } } void Parser::parseCaret(Expression & leftHandSide, Token::Type stoppingType) { Expression rightHandSide; if (parseBinaryOperator(leftHandSide, rightHandSide, Token::ImplicitTimes)) { - leftHandSide = Power(leftHandSide, rightHandSide); + leftHandSide = Power::Builder(leftHandSide, rightHandSide); } } @@ -252,7 +252,7 @@ void Parser::parseStore(Expression & leftHandSide, Token::Type stoppingType) { m_status = Status::Error; // Store expects a single symbol or function. return; } - leftHandSide = Store(leftHandSide, static_cast(rightHandSide)); + leftHandSide = Store::Builder(leftHandSide, static_cast(rightHandSide)); } void Parser::parseLeftSuperscript(Expression & leftHandSide, Token::Type stoppingType) { @@ -268,7 +268,7 @@ void Parser::parseLeftSuperscript(Expression & leftHandSide, Token::Type stoppin m_status = Status::Error; // Right superscript marker missing. return; } - leftHandSide = Power(leftHandSide, rightHandSide); + leftHandSide = Power::Builder(leftHandSide, rightHandSide); isThereImplicitMultiplication(); } @@ -301,7 +301,7 @@ void Parser::parseLeftParenthesis(Expression & leftHandSide, Token::Type stoppin m_status = Status::Error; // Right parenthesis missing. return; } - leftHandSide = Parenthesis(leftHandSide); + leftHandSide = Parenthesis::Builder(leftHandSide); isThereImplicitMultiplication(); } @@ -309,7 +309,7 @@ void Parser::parseBang(Expression & leftHandSide, Token::Type stoppingType) { if (leftHandSide.isUninitialized()) { m_status = Status::Error; // Left-hand side missing } else { - leftHandSide = Factorial(leftHandSide); + leftHandSide = Factorial::Builder(leftHandSide); } isThereImplicitMultiplication(); } @@ -363,7 +363,7 @@ void Parser::parseSequence(Expression & leftHandSide, const char name, Token::Ty } else if (rank.isIdenticalTo(Symbol("n",1))) { char sym[5] = {name, '(', 'n', ')', 0}; leftHandSide = Symbol(sym, 4); - } else if (rank.isIdenticalTo(Addition(Symbol("n",1),Rational("1")))) { + } else if (rank.isIdenticalTo(Addition::Builder(Symbol("n",1),Rational("1")))) { char sym[7] = {name, '(', 'n', '+', '1', ')', 0}; leftHandSide = Symbol(sym, 6); } else { @@ -459,7 +459,7 @@ Expression Parser::parseFunctionParameters() { return Expression(); } if (popTokenIfType(Token::RightParenthesis)) { - return Matrix(); // The function has no parameter. + return Matrix::Builder(); // The function has no parameter. } Expression commaSeparatedList = parseCommaSeparatedList(); if (m_status != Status::Progress) { @@ -477,7 +477,7 @@ void Parser::parseMatrix(Expression & leftHandSide, Token::Type stoppingType) { m_status = Status::Error; //FIXME return; } - Matrix matrix; + Matrix matrix = Matrix::Builder(); int numberOfRows = 0; int numberOfColumns = 0; while (!popTokenIfType(Token::RightBracket)) { @@ -520,7 +520,7 @@ Expression Parser::parseVector() { } Expression Parser::parseCommaSeparatedList() { - Matrix commaSeparatedList; + Matrix commaSeparatedList = Matrix::Builder(); int length = 0; do { Expression item = parseUntil(Token::Comma); diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 1cfa9a51f..620dcc3e7 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -134,9 +134,9 @@ Layout PowerNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int if (indiceOperand->type() == ExpressionNode::Type::Parenthesis) { indiceOperand = indiceOperand->childAtIndex(0); } - HorizontalLayout result = HorizontalLayout(); + HorizontalLayout result = HorizontalLayout::Builder(); result.addOrMergeChildAtIndex(childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits), 0, false); - result.addChildAtIndex(VerticalOffsetLayout( + result.addChildAtIndex(VerticalOffsetLayout::Builder( indiceOperand->createLayout(floatDisplayMode, numberOfSignificantDigits), VerticalOffsetLayoutNode::Type::Superscript), result.numberOfChildren(), @@ -235,15 +235,11 @@ template MatrixComplex PowerNode::computeOnMatrices(const MatrixC } // Power -Power::Power(Expression base, Expression exponent) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, base); - replaceChildAtIndexInPlace(1, exponent); -} Expression Power::setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { assert(s == ExpressionNode::Sign::Positive); if (childAtIndex(0).sign(context) == ExpressionNode::Sign::Negative) { - Expression result = Power(childAtIndex(0).setSign(ExpressionNode::Sign::Positive, context, complexFormat, angleUnit, target), childAtIndex(1)); + Expression result = Power::Builder(childAtIndex(0).setSign(ExpressionNode::Sign::Positive, context, complexFormat, angleUnit, target), childAtIndex(1)); replaceWithInPlace(result); return result.shallowReduce(*context, complexFormat, angleUnit, target); } @@ -321,7 +317,7 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co if (exp == 0) { return replaceWith(id, true); } - Multiplication * result = new Multiplication(id, mat->clone()); + Multiplication * result = new Multiplication::Builder(id, mat->clone()); // TODO: implement a quick exponentiation for (int k = 1; k < exp; k++) { result->addOperand(mat->clone()); @@ -487,7 +483,7 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co if (childAtIndex(0).sign(&context) == ExpressionNode::Sign::Negative) { // (-inf)^x --> (-1)^x*inf Power p(Rational(-1), childAtIndex(1)); - result = Multiplication(p, result); + result = Multiplication::Builder(p, result); p.shallowReduce(context, complexFormat, angleUnit, target); } } @@ -524,7 +520,7 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co if (!m0.isUninitialized()) { replaceChildAtIndexInPlace(0, m0); // m0 doest not need to be shallowReduce as makePositiveAnyNegativeNumeralFactor returns a reduced expression - Multiplication m1 = Multiplication(); + Multiplication m1; replaceWithInPlace(m1); // Multiply m1 by i complex Constant i(Ion::Charset::IComplex); @@ -546,9 +542,9 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co Expression cos = Cosine::Builder(m); m = m.shallowReduce(context, complexFormat, angleUnit, target); Expression sin = Sine::Builder(m.clone()); - Expression complexPart = Multiplication(sin, i); + Expression complexPart = Multiplication::Builder(sin, i); sin.shallowReduce(context, complexFormat, angleUnit, target); - Expression a = Addition(cos, complexPart); + Expression a = Addition::Builder(cos, complexPart); cos.shallowReduce(context, complexFormat, angleUnit, target); complexPart.shallowReduce(context, complexFormat, angleUnit, target); replaceWithInPlace(a); @@ -624,11 +620,11 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co m.shallowReduce(context, complexFormat, angleUnit, target); // |a|^r - Power p = Power(factor, rCopy); + Power p = Power::Builder(factor, rCopy); // |a|^r*(sign(a)*b*...)^r Power thisRef = *this; - Multiplication root = Multiplication(p); + Multiplication root = Multiplication::Builder(p); replaceWithInPlace(root); root.addChildAtIndexInPlace(thisRef, 1, 1); p.shallowReduce(context, complexFormat, angleUnit, target); @@ -665,12 +661,12 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co if (RationalExponentShouldNotBeReduced(rationalBase, rationalIndex)) { return *this; } - Power p1 = Power(childAtIndex(0).clone(), a.childAtIndex(0)); + Power p1 = Power::Builder(childAtIndex(0).clone(), a.childAtIndex(0)); Power thisRef = *this; childAtIndex(1).convert().removeChildAtIndexInPlace(0); // p2 = a^(c+...) // if addition had only 2 children childAtIndex(1).convert().squashUnaryHierarchyInPlace(); - Multiplication m = Multiplication(p1); + Multiplication m = Multiplication::Builder(p1); replaceWithInPlace(m); m.addChildAtIndexInPlace(thisRef, 1, 1); p1.simplifyRationalRationalPower(context, complexFormat, angleUnit, target); @@ -711,13 +707,13 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co // result = result * (a0+a1+...+a(m-1) in its expanded form if (result.type() == ExpressionNode::Type::Addition) { // We need a 'double' distribution and newA will hold the new expanded form - Expression newA = Addition(); + Expression newA = Addition::Builder(); for (int j = 0; j < a.numberOfChildren(); j++) { - Expression m = Multiplication(result.clone(), a.childAtIndex(j).clone()).distributeOnOperandAtIndex(0, context, complexFormat, angleUnit, target); + Expression m = Multiplication::Builder(result.clone(), a.childAtIndex(j).clone()).distributeOnOperandAtIndex(0, context, complexFormat, angleUnit, target); if (newA.type() == ExpressionNode::Type::Addition) { static_cast(newA).addChildAtIndexInPlace(m, newA.numberOfChildren(), newA.numberOfChildren()); } else { - newA = Addition(newA, m); + newA = Addition::Builder(newA, m); } newA = newA.shallowReduce(context, complexFormat, angleUnit, target); } @@ -725,7 +721,7 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co result = newA; } else { // Just distribute result on a - Multiplication m = Multiplication(a.clone(), result.clone()); + Multiplication m = Multiplication::Builder(a.clone(), result.clone()); Expression distributedM = m.distributeOnOperandAtIndex(0, context, complexFormat, angleUnit, target); result.replaceWithInPlace(distributedM); result = distributedM; @@ -757,10 +753,10 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co Addition * a = new Addition(); for (int i = 0; i <= clippedN; i++) { Rational * r = new Rational(static_cast(BinomialCoefficient::compute(static_cast(i), static_cast(clippedN)))); - Power * p0 = new Power(x0->clone(), new Rational(i), false); - Power * p1 = new Power(x1->clone(), new Rational(clippedN-i), false); + Power * p0 = new Power::Builder(x0->clone(), new Rational(i), false); + Power * p1 = new Power::Builder(x1->clone(), new Rational(clippedN-i), false); const Expression * operands[3] = {r, p0, p1}; - Multiplication * m = new Multiplication(operands, 3, false); + Multiplication * m = new Multiplication::Builder(operands, 3, false); p0->shallowReduce(context, complexFormat, angleUnit, target); p1->shallowReduce(context, complexFormat, angleUnit, target); a->addOperand(m); @@ -783,7 +779,7 @@ Expression Power::shallowBeautify(Context & context, Preferences::ComplexFormat Expression p = denominator(context, complexFormat, angleUnit); // If the denominator is initialized, the index of the power is of form -y if (!p.isUninitialized()) { - Division d = Division(Rational(1), p); + Division d = Division::Builder(Rational(1), p); p.shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); replaceWithInPlace(d); return d.shallowBeautify(context, complexFormat, angleUnit, target); @@ -811,7 +807,7 @@ Expression Power::shallowBeautify(Context & context, Preferences::ComplexFormat Integer p = childAtIndex(1).convert().signedIntegerNumerator(); Integer q = childAtIndex(1).convert().integerDenominator(); Expression nthRoot = q.isOne() ? childAtIndex(0) : NthRoot::Builder(childAtIndex(0), Rational(q)); - Expression result = p.isOne() ? nthRoot : Power(nthRoot, Rational(p)); + Expression result = p.isOne() ? nthRoot : Power::Builder(nthRoot, Rational(p)); replaceWithInPlace(result); return result; } @@ -820,7 +816,7 @@ Expression Power::shallowBeautify(Context & context, Preferences::ComplexFormat if (childAtIndex(0).type() == ExpressionNode::Type::Addition || childAtIndex(0).type() == ExpressionNode::Type::Multiplication) { - Parenthesis p = Parenthesis(childAtIndex(0)); + Parenthesis p = Parenthesis::Builder(childAtIndex(0)); replaceChildAtIndexInPlace(0, p); } return *this; @@ -831,7 +827,7 @@ Expression Power::shallowBeautify(Context & context, Preferences::ComplexFormat // Simplification Expression Power::denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { // Clone the power - Expression clone = Power(childAtIndex(0).clone(), childAtIndex(1).clone()); + Expression clone = Power::Builder(childAtIndex(0).clone(), childAtIndex(1).clone()); // If the power is of form x^(-y), denominator should be x^y Expression positiveIndex = clone.childAtIndex(1).makePositiveAnyNegativeNumeralFactor(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); if (!positiveIndex.isUninitialized()) { @@ -848,7 +844,7 @@ Expression Power::denominator(Context & context, Preferences::ComplexFormat comp Expression Power::simplifyPowerPower(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { // this is p^e = (a^b)^e, we want a^(b*e) Expression p = childAtIndex(0); - Multiplication m(p.childAtIndex(1), childAtIndex(1)); + Multiplication m = Multiplication::Builder(p.childAtIndex(1), childAtIndex(1)); replaceChildAtIndexInPlace(0, p.childAtIndex(0)); replaceChildAtIndexInPlace(1, m); m.shallowReduce(context, complexFormat, angleUnit, target); @@ -860,7 +856,7 @@ Expression Power::simplifyPowerMultiplication(Context& context, Preferences::Com Expression m = childAtIndex(0); Expression r = childAtIndex(1); for (int index = 0; index < m.numberOfChildren(); index++) { - Power p = Power(m.childAtIndex(index).clone(), r.clone()); // We copy r and factor to avoid inheritance issues + Power p = Power::Builder(m.childAtIndex(index).clone(), r.clone()); // We copy r and factor to avoid inheritance issues m.replaceChildAtIndexInPlace(index, p); p.shallowReduce(context, complexFormat, angleUnit, target); } @@ -875,7 +871,7 @@ Expression Power::simplifyRationalRationalPower(Context& context, Preferences::C if (b.integerDenominator().isOne()) { Rational r = Rational::IntegerPower(a, b.signedIntegerNumerator()); if (r.numeratorOrDenominatorIsInfinity()) { - return Power(a, b); + return Power::Builder(a, b); } replaceWithInPlace(r); return r; @@ -890,7 +886,7 @@ Expression Power::simplifyRationalRationalPower(Context& context, Preferences::C n = CreateSimplifiedIntegerRationalPower(a.signedIntegerNumerator(), b, false, context, complexFormat, angleUnit, target); d = CreateSimplifiedIntegerRationalPower(a.integerDenominator(), b, true, context, complexFormat, angleUnit, target); } - Multiplication m = Multiplication(n, d); + Multiplication m = Multiplication::Builder(n, d); replaceWithInPlace(m); return m.shallowReduce(context, complexFormat, angleUnit, target); } @@ -908,7 +904,7 @@ Expression Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational r, bo /* We could not break i in prime factors (it might take either too many * factors or too much time). */ Expression rClone = r.clone().setSign(isDenominator ? ExpressionNode::Sign::Negative : ExpressionNode::Sign::Positive, &context, complexFormat, angleUnit, target); - return Power(Rational(i), rClone); + return Power::Builder(Rational(i), rClone); } Integer r1(1); @@ -921,19 +917,19 @@ Expression Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational r, bo } if (r2.isOverflow() || r1.isOverflow()) { // we overflow Integer at one point: we abort - return Power(Rational(i), r.clone()); + return Power::Builder(Rational(i), r.clone()); } Rational p1 = Rational(r2); Integer oneExponent = isDenominator ? Integer(-1) : Integer(1); Integer rDenominator = r.integerDenominator(); Rational p2 = Rational(oneExponent, rDenominator); - Power p = Power(p1, p2); + Power p = Power::Builder(p1, p2); if (r1.isEqualTo(Integer(1)) && !i.isNegative()) { return p; } Integer one(1); Rational r3 = isDenominator ? Rational(one, r1) : Rational(r1); - Multiplication m; + Multiplication m = Multiplication::Builder(); m.addChildAtIndexInPlace(r3, 0, 0); if (!r2.isOne()) { m.addChildAtIndexInPlace(p, 1, 1); @@ -981,12 +977,12 @@ Expression Power::removeSquareRootsFromDenominator(Context & context, Preference if (pq.isOverflow()) { return result; } - Power sqrt = Power(Rational(pq), Rational(1, 2)); + Power sqrt = Power::Builder(Rational(pq), Rational(1, 2)); Integer one(1); if (castedChild1.isHalf()) { - result = Multiplication(Rational(one, q), sqrt); + result = Multiplication::Builder(Rational(one, q), sqrt); } else { - result = Multiplication(Rational(one, p), sqrt); // We use here the assertion that p != 0 + result = Multiplication::Builder(Rational(one, p), sqrt); // We use here the assertion that p != 0 } sqrt.shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); } @@ -1036,29 +1032,29 @@ Expression Power::removeSquareRootsFromDenominator(Context & context, Preference // Compute the numerator Integer pq1 = Integer::Multiplication(p1, q1); Integer pq2 = Integer::Multiplication(p2, q2); - Power sqrt1 = Power(Rational(pq1), Rational(1, 2)); - Power sqrt2 = Power(Rational(pq2), Rational(1, 2)); + Power sqrt1 = Power::Builder(Rational(pq1), Rational(1, 2)); + Power sqrt2 = Power::Builder(Rational(pq2), Rational(1, 2)); Integer factor1 = Integer::Multiplication( Integer::Multiplication(n1, d1), Integer::Multiplication(Integer::Power(d2, Integer(2)), q2)); - Multiplication m1 = Multiplication(Rational(factor1), sqrt1); + Multiplication m1 = Multiplication::Builder(Rational(factor1), sqrt1); Integer factor2 = Integer::Multiplication( Integer::Multiplication(n2, d2), Integer::Multiplication(Integer::Power(d1, Integer(2)), q1)); - Multiplication m2 = Multiplication(Rational(factor2), sqrt2); + Multiplication m2 = Multiplication::Builder(Rational(factor2), sqrt2); Expression numerator; if (denominator.isNegative()) { - numerator = Subtraction(m2, m1); + numerator = Subtraction::Builder(m2, m1); denominator.setNegative(false); } else { - numerator = Subtraction(m1, m2); + numerator = Subtraction::Builder(m1, m2); } if (denominator.isOverflow() || factor1.isOverflow() || factor2.isOverflow() || pq1.isOverflow() || pq2.isOverflow()) { return result; // Escape } numerator = numerator.deepReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); Integer one(1); - result = Multiplication(numerator, Rational(one, denominator)); + result = Multiplication::Builder(numerator, Rational(one, denominator)); } if (!result.isUninitialized()) { @@ -1127,13 +1123,13 @@ bool Power::isNthRootOfUnity() const { Expression Power::equivalentExpressionUsingStandardExpression() const { if (childAtIndex(1).type() == ExpressionNode::Type::Rational) { if (childAtIndex(1).convert().isMinusOne()) { - return Division(Rational(1), childAtIndex(0).clone()); + return Division::Builder(Rational(1), childAtIndex(0).clone()); } if (childAtIndex(1).convert().isHalf()) { return SquareRoot::Builder(childAtIndex(0).clone()); } if (childAtIndex(1).convert().isMinusHalf()) { - return Division(Rational(1), SquareRoot::Builder(childAtIndex(0).clone())); + return Division::Builder(Rational(1), SquareRoot::Builder(childAtIndex(0).clone())); } } return Expression(); @@ -1144,7 +1140,7 @@ Expression Power::CreateComplexExponent(const Expression & r, Context & context, const Constant exp = Constant(Ion::Charset::Exponential); Constant iComplex = Constant(Ion::Charset::IComplex); const Constant pi = Constant(Ion::Charset::SmallPi); - Multiplication mExp = Multiplication(iComplex, pi, r.clone()); + Multiplication mExp = Multiplication::Builder(iComplex, pi, r.clone()); iComplex.shallowReduce(context, complexFormat, angleUnit, target); Power p(exp, mExp); mExp.shallowReduce(context, complexFormat, angleUnit, target); @@ -1152,11 +1148,11 @@ Expression Power::CreateComplexExponent(const Expression & r, Context & context, #if 0 const Constant iComplex = Constant(Ion::Charset::IComplex); const Constant pi = Constant(Ion::Charset::SmallPi); - Expression op = Multiplication(pi, r).shallowReduce(context, complexFormat, angleUnit, false); + Expression op = Multiplication::Builder(pi, r).shallowReduce(context, complexFormat, angleUnit, false); Cosine cos = Cosine(op).shallowReduce(context, complexFormat, angleUnit, false);; Sine sin = Sine(op).shallowReduce(context, complexFormat, angleUnit, false); - Expression m = Multiplication(iComplex, sin); - Expression a = Addition(cos, m); + Expression m = Multiplication::Builder(iComplex, sin); + Expression a = Addition::Builder(cos, m); const Expression * multExpOperands[3] = {pi, r->clone()}; #endif } diff --git a/poincare/src/prediction_interval.cpp b/poincare/src/prediction_interval.cpp index 12b438031..fd8074ee3 100644 --- a/poincare/src/prediction_interval.cpp +++ b/poincare/src/prediction_interval.cpp @@ -95,11 +95,11 @@ Expression PredictionInterval::shallowReduce(Context & context, Preferences::Com return *this; } // Compute sqr = sqrt(r0*(1-r0)/r1) - Expression sqr = Power(Division(numerator, r1), Rational(1, 2)); - Expression m = Multiplication(Rational(196, 100), sqr); - Matrix matrix; - matrix.addChildAtIndexInPlace(Addition(r0.clone(), Multiplication(Rational(-1), m.clone())), 0, 0); - matrix.addChildAtIndexInPlace(Addition(r0.clone(), m), 1, 1); + Expression sqr = Power::Builder(Division::Builder(numerator, r1), Rational(1, 2)); + Expression m = Multiplication::Builder(Rational(196, 100), sqr); + Matrix matrix = Matrix::Builder(); + matrix.addChildAtIndexInPlace(Addition::Builder(r0.clone(), Multiplication::Builder(Rational(-1), m.clone())), 0, 0); + matrix.addChildAtIndexInPlace(Addition::Builder(r0.clone(), m), 1, 1); matrix.setDimensions(1, 2); replaceWithInPlace(matrix); matrix.deepReduceChildren(context, complexFormat, angleUnit, target); diff --git a/poincare/src/product.cpp b/poincare/src/product.cpp index caa9be26c..f855e9974 100644 --- a/poincare/src/product.cpp +++ b/poincare/src/product.cpp @@ -19,7 +19,7 @@ Expression ProductNode::replaceUnknown(const Symbol & symbol) { } Layout ProductNode::createSequenceLayout(Layout argumentLayout, Layout symbolLayout, Layout subscriptLayout, Layout superscriptLayout) const { - return ProductLayout(argumentLayout, symbolLayout, subscriptLayout, superscriptLayout); + return ProductLayout::Builder(argumentLayout, symbolLayout, subscriptLayout, superscriptLayout); } int ProductNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index bccd82fb1..504aa05cf 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -111,7 +111,7 @@ Layout RationalNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, return numeratorLayout; } HorizontalLayout denominatorLayout = denominator().createLayout(); - return FractionLayout(numeratorLayout, denominatorLayout); + return FractionLayout::Builder(numeratorLayout, denominatorLayout); } // Approximation @@ -266,7 +266,7 @@ Expression Rational::shallowReduce() { Expression Rational::shallowBeautify() { if (sign() == ExpressionNode::Sign::Negative) { Expression abs = setSign(ExpressionNode::Sign::Positive); - Opposite o; + Opposite o = Opposite::Builder(); replaceWithInPlace(o); o.replaceChildAtIndexInPlace(0, abs); return o; diff --git a/poincare/src/right_parenthesis_layout.cpp b/poincare/src/right_parenthesis_layout.cpp index e6a305113..d38345f20 100644 --- a/poincare/src/right_parenthesis_layout.cpp +++ b/poincare/src/right_parenthesis_layout.cpp @@ -59,6 +59,4 @@ void RightParenthesisLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expr RenderWithChildHeight(ParenthesisLayoutNode::ChildHeightGivenLayoutHeight(layoutSize().height()), ctx, p, expressionColor, backgroundColor); } -RightParenthesisLayout::RightParenthesisLayout() : Layout(TreePool::sharedPool()->createTreeNode()) {} - } diff --git a/poincare/src/right_square_bracket_layout.cpp b/poincare/src/right_square_bracket_layout.cpp index f5b6aecc4..cd1608a02 100644 --- a/poincare/src/right_square_bracket_layout.cpp +++ b/poincare/src/right_square_bracket_layout.cpp @@ -8,6 +8,4 @@ void RightSquareBracketLayoutNode::render(KDContext * ctx, KDPoint p, KDColor ex ctx->fillRect(KDRect(p.x()+k_widthMargin-k_bracketWidth+1, p.y() + childHeight(), k_bracketWidth, k_lineThickness), expressionColor); } -RightSquareBracketLayout::RightSquareBracketLayout() : Layout(TreePool::sharedPool()->createTreeNode()) {} - } diff --git a/poincare/src/sign_function.cpp b/poincare/src/sign_function.cpp index 74cd540b3..340beb9a8 100644 --- a/poincare/src/sign_function.cpp +++ b/poincare/src/sign_function.cpp @@ -83,7 +83,7 @@ Expression SignFunction::shallowReduce(Context & context, Preferences::ComplexFo return *this; } Expression sign = *this; - Multiplication m(Rational(-1)); + Multiplication m = Multiplication::Builder(Rational(-1)); replaceWithInPlace(m); m.addChildAtIndexInPlace(sign, 1, 1); // sign does not need to be shallowReduced because -x = NAN --> x = NAN return m; // m does not need to be shallowReduced, -1*sign cannot be reduced diff --git a/poincare/src/simplification_helper.cpp b/poincare/src/simplification_helper.cpp index ce828c6a4..4b3220212 100644 --- a/poincare/src/simplification_helper.cpp +++ b/poincare/src/simplification_helper.cpp @@ -7,7 +7,7 @@ namespace Poincare { Expression SimplificationHelper::Map(const Expression & e, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { assert(e->numberOfChildren() == 1 && e->childAtIndex(0)->type() == ExpressionNode::Type::Matrix); Expression c = e.childAtIndex(0); - Matrix matrix; + Matrix matrix = Matrix::Builder(); for (int i = 0; i < c->numberOfChildren(); i++) { Expression f = e.replaceChildAtIndexInPlace(0, e.childAtIndex(0).childAtIndex(i)); matrix.addChildAtIndexInPlace(f, i, i); diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index 438dab169..8438dd663 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -19,7 +19,7 @@ constexpr Expression::FunctionHelper SquareRoot::s_functionHelper; int SquareRootNode::numberOfChildren() const { return SquareRoot::s_functionHelper.numberOfChildren(); } Layout SquareRootNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { - return NthRootLayout(childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits)); + return NthRootLayout::Builder(childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits)); } int SquareRootNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -54,7 +54,7 @@ Expression SquareRoot::shallowReduce(Context & context, Preferences::ComplexForm return SimplificationHelper::Map(this, context, angleUnit); } #endif - Power p = Power(childAtIndex(0), Rational(1, 2)); + Power p = Power::Builder(childAtIndex(0), Rational(1, 2)); replaceWithInPlace(p); return p.shallowReduce(context, complexFormat, angleUnit, target); } diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index 7039a3fd9..1c1bdc2f3 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -32,7 +32,7 @@ int StoreNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatM } Layout StoreNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { - HorizontalLayout result = HorizontalLayout(); + HorizontalLayout result = HorizontalLayout::Builder(); result.addOrMergeChildAtIndex(childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits), 0, false); result.addChildAtIndex(CharLayout(Ion::Charset::Sto), result.numberOfChildren(), result.numberOfChildren(), nullptr); result.addOrMergeChildAtIndex(childAtIndex(1)->createLayout(floatDisplayMode, numberOfSignificantDigits), result.numberOfChildren(), false); diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index 73daf456b..4dabad1b0 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -56,15 +56,13 @@ Expression SubtractionNode::shallowReduce(Context & context, Preferences::Comple return Subtraction(this).shallowReduce(context, complexFormat, angleUnit, target); } -Subtraction::Subtraction() : Expression(TreePool::sharedPool()->createTreeNode()) {} - Expression Subtraction::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } - Expression m = Multiplication(Rational(-1), childAtIndex(1)); - Addition a(childAtIndex(0), m); + Expression m = Multiplication::Builder(Rational(-1), childAtIndex(1)); + Addition a = Addition::Builder(childAtIndex(0), m); m = m.shallowReduce(context, complexFormat, angleUnit, target); replaceWithInPlace(a); return a.shallowReduce(context, complexFormat, angleUnit, target); diff --git a/poincare/src/sum.cpp b/poincare/src/sum.cpp index 9c7a5305b..ffc0620ad 100644 --- a/poincare/src/sum.cpp +++ b/poincare/src/sum.cpp @@ -19,7 +19,7 @@ Expression SumNode::replaceUnknown(const Symbol & symbol) { } Layout SumNode::createSequenceLayout(Layout argumentLayout, Layout symbolLayout, Layout subscriptLayout, Layout superscriptLayout) const { - return SumLayout(argumentLayout, symbolLayout, subscriptLayout, superscriptLayout); + return SumLayout::Builder(argumentLayout, symbolLayout, subscriptLayout, superscriptLayout); } int SumNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 97144e75e..f497b5458 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -80,30 +80,30 @@ Layout SymbolNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, in return CharLayout(Symbol::k_unknownXReadableChar); } if (strcmp(m_name, "u(n)") == 0) { - return HorizontalLayout( + return HorizontalLayout::Builder( CharLayout('u'), - VerticalOffsetLayout( + VerticalOffsetLayout::Builder( CharLayout('n'), VerticalOffsetLayoutNode::Type::Subscript)); } if (strcmp(m_name, "u(n+1)") == 0) { - return HorizontalLayout( + return HorizontalLayout::Builder( CharLayout('u'), - VerticalOffsetLayout( + VerticalOffsetLayout::Builder( LayoutHelper::String("n+1", 3), VerticalOffsetLayoutNode::Type::Subscript)); } if (strcmp(m_name, "v(n)") == 0) { - return HorizontalLayout( + return HorizontalLayout::Builder( CharLayout('v'), - VerticalOffsetLayout( + VerticalOffsetLayout::Builder( CharLayout('n'), VerticalOffsetLayoutNode::Type::Subscript)); } if (strcmp(m_name, "v(n+1)") == 0) { - return HorizontalLayout( + return HorizontalLayout::Builder( CharLayout('v'), - VerticalOffsetLayout( + VerticalOffsetLayout::Builder( LayoutHelper::String("n+1", 3), VerticalOffsetLayoutNode::Type::Subscript)); } @@ -173,7 +173,7 @@ Expression Symbol::replaceSymbolWithExpression(const SymbolAbstract & symbol, co Expression value = expression.clone(); Expression p = parent(); if (!p.isUninitialized() && p.node()->childNeedsParenthesis(value.node())) { - value = Parenthesis(value); + value = Parenthesis::Builder(value); } replaceWithInPlace(value); return value; diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp index 6d9e7dd1a..01510753c 100644 --- a/poincare/src/tangent.cpp +++ b/poincare/src/tangent.cpp @@ -54,7 +54,7 @@ Expression Tangent::shallowReduce(Context & context, Preferences::ComplexFormat if (newExpression.type() == ExpressionNode::Type::Tangent) { Sine s = Sine::Builder(newExpression.childAtIndex(0).clone()); Cosine c = Cosine::Builder(newExpression.childAtIndex(0)); - Division d = Division(s, c); + Division d = Division::Builder(s, c); s.shallowReduce(context, complexFormat, angleUnit, target); c.shallowReduce(context, complexFormat, angleUnit, target); newExpression.replaceWithInPlace(d); diff --git a/poincare/src/tree_handle.cpp b/poincare/src/tree_handle.cpp index 1ae1abe60..51cd46dc0 100644 --- a/poincare/src/tree_handle.cpp +++ b/poincare/src/tree_handle.cpp @@ -69,7 +69,7 @@ void TreeHandle::replaceChildAtIndexInPlace(int oldChildIndex, TreeHandle newChi } void TreeHandle::replaceChildWithGhostInPlace(TreeHandle t) { - Ghost ghost; + Ghost ghost = Ghost::Builder(); return replaceChildInPlace(t, ghost); } diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index a3832d366..1daeec03f 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -105,12 +105,12 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& co // These equalities are true on complexes if ((e.type() == ExpressionNode::Type::Cosine && e.childAtIndex(0).type() == ExpressionNode::Type::ArcSine) || (e.type() == ExpressionNode::Type::Sine && e.childAtIndex(0).type() == ExpressionNode::Type::ArcCosine)) { Expression sqrt = - Power( - Addition( + Power::Builder( + Addition::Builder( Rational(1), - Multiplication( + Multiplication::Builder( Rational(-1), - Power(e.childAtIndex(0).childAtIndex(0), Rational(2)) + Power::Builder(e.childAtIndex(0).childAtIndex(0), Rational(2)) ) ), Rational(1,2) @@ -134,10 +134,10 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& co Expression x = e.childAtIndex(0).childAtIndex(0); // Build 1/sqrt(1+x^2) Expression res = - Power( - Addition( + Power::Builder( + Addition::Builder( Rational(1), - Power( + Power::Builder( e.type() == ExpressionNode::Type::Cosine ? x : x.clone(), Rational(2)) ), @@ -149,7 +149,7 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& co // reduce 1+*x^2 res.childAtIndex(0).shallowReduce(context, complexFormat, angleUnit, target); if (e.type() == ExpressionNode::Type::Sine) { - res = Multiplication(x, res); + res = Multiplication::Builder(x, res); // reduce (1+x^2)^(-1/2) res.childAtIndex(0).shallowReduce(context, complexFormat, angleUnit, target); } @@ -167,7 +167,7 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& co return e.shallowReduce(context, complexFormat, angleUnit, target); } else { // sin(-a) = -sin(a) or tan(-a) = -tan(a) - Multiplication m(Rational(-1)); + Multiplication m = Multiplication::Builder(Rational(-1)); e.replaceWithInPlace(m); m.addChildAtIndexInPlace(e, 1, 1); e.shallowReduce(context, complexFormat, angleUnit, target); @@ -233,7 +233,7 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& co unaryCoefficient *= -1; } Expression simplifiedCosine = e.shallowReduce(context, complexFormat, angleUnit, target); // recursive - Multiplication m = Multiplication(Rational(unaryCoefficient)); + Multiplication m = Multiplication::Builder(Rational(unaryCoefficient)); simplifiedCosine.replaceWithInPlace(m); m.addChildAtIndexInPlace(simplifiedCosine, 1, 1); return m.shallowReduce(context, complexFormat, angleUnit, target); @@ -278,12 +278,12 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& c * reduced to undef) */ if (target == ExpressionNode::ReductionTarget::User || x.isNumber()) { Expression sign = SignFunction::Builder(x.clone()); - Multiplication m0(Rational(1,2), sign, Constant(Ion::Charset::SmallPi)); + Multiplication m0 = Multiplication::Builder(Rational(1,2), sign, Constant(Ion::Charset::SmallPi)); sign.shallowReduce(context, complexFormat, angleUnit, target); e.replaceChildAtIndexInPlace(0, x); - Addition a(m0); + Addition a = Addition::Builder(m0); e.replaceWithInPlace(a); - Multiplication m1(Rational(-1), e); + Multiplication m1 = Multiplication::Builder(Rational(-1), e); e.shallowReduce(context, complexFormat, angleUnit, target); a.addChildAtIndexInPlace(m1, 1, 1); return a.shallowReduce(context, complexFormat, angleUnit, target); @@ -315,7 +315,7 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& c // acos(-x) = pi-acos(x) if (e.type() == ExpressionNode::Type::ArcCosine) { Expression pi = angleUnit == Preferences::AngleUnit::Radian ? static_cast(Constant(Ion::Charset::SmallPi)) : static_cast(Rational(180)); - Subtraction s; + Subtraction s = Subtraction::Builder(); e.replaceWithInPlace(s); s.replaceChildAtIndexInPlace(0, pi); s.replaceChildAtIndexInPlace(1, e); @@ -323,7 +323,7 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& c return s.shallowReduce(context, complexFormat, angleUnit, target); } else { // asin(-x) = -asin(x) or atan(-x) = -atan(x) - Multiplication m(Rational(-1)); + Multiplication m = Multiplication::Builder(Rational(-1)); e.replaceWithInPlace(m); m.addChildAtIndexInPlace(e, 1, 1); e.shallowReduce(context, complexFormat, angleUnit, target); diff --git a/poincare/src/vertical_offset_layout.cpp b/poincare/src/vertical_offset_layout.cpp index 582b96208..69feb1557 100644 --- a/poincare/src/vertical_offset_layout.cpp +++ b/poincare/src/vertical_offset_layout.cpp @@ -231,7 +231,7 @@ bool VerticalOffsetLayoutNode::willAddSibling(LayoutCursor * cursor, LayoutNode // Add the Left parenthesis int idxInParent = parentRef.indexOfChild(thisRef); int leftParenthesisIndex = idxInParent; - LeftParenthesisLayout leftParenthesis = LeftParenthesisLayout(); + LeftParenthesisLayout leftParenthesis = LeftParenthesisLayout::Builder(); int numberOfOpenParenthesis = 0; while (leftParenthesisIndex > 0 && parentRef.childAtIndex(leftParenthesisIndex-1).isCollapsable(&numberOfOpenParenthesis, true)) @@ -242,7 +242,7 @@ bool VerticalOffsetLayoutNode::willAddSibling(LayoutCursor * cursor, LayoutNode idxInParent = parentRef.indexOfChild(thisRef); // Add the Right parenthesis - RightParenthesisLayout rightParenthesis = RightParenthesisLayout(); + RightParenthesisLayout rightParenthesis = RightParenthesisLayout::Builder(); if (cursor->position() == LayoutCursor::Position::Right) { parentRef.addChildAtIndex(rightParenthesis, idxInParent + 1, parentRef.numberOfChildren(), nullptr); } else { @@ -266,11 +266,4 @@ LayoutNode * VerticalOffsetLayoutNode::baseLayout() { return parentNode->childAtIndex(idxInParent - 1); } -VerticalOffsetLayout::VerticalOffsetLayout(Layout l, VerticalOffsetLayoutNode::Type type) : - Layout(TreePool::sharedPool()->createTreeNode()) -{ - static_cast(node())->setType(type); - replaceChildAtIndexInPlace(0,l); -} - } diff --git a/poincare/test/addition.cpp b/poincare/test/addition.cpp index f47829f2f..49803abba 100644 --- a/poincare/test/addition.cpp +++ b/poincare/test/addition.cpp @@ -24,7 +24,7 @@ static inline void assert_parsed_expression_is_equal_to(const char * exp, Expres QUIZ_CASE(poincare_addition_cast_does_not_copy) { Rational i1(1); Rational i2(2); - Addition j(i1, i2); + Addition j = Addition::Builder(i1, i2); Expression k = j; quiz_assert(k.identifier() == (static_cast(k)).identifier()); quiz_assert(i1.identifier() == (static_cast(i1)).identifier()); @@ -34,14 +34,14 @@ QUIZ_CASE(poincare_addition_cast_does_not_copy) { QUIZ_CASE(poincare_addition_without_parsing) { Rational i1(1); Rational i2(2); - Addition j(i1, i2); + Addition j = Addition::Builder(i1, i2); assert_approximation_equals(j, 3.0f); } QUIZ_CASE(poincare_addition_parsing) { Rational i1(1); Rational i2(2); - Addition j1(i1, i2); + Addition j1 = Addition::Builder(i1, i2); assert_parsed_expression_is_equal_to("1+2", j1); } diff --git a/poincare/test/expression_order.cpp b/poincare/test/expression_order.cpp index 9db677bb9..2b2ca3408 100644 --- a/poincare/test/expression_order.cpp +++ b/poincare/test/expression_order.cpp @@ -23,8 +23,8 @@ void assert_multiplication_or_addition_is_ordered_as(Expression e1, Expression e QUIZ_CASE(poincare_expression_order) { { // 2 * 5 - Expression e1 = Multiplication(Rational(5), Rational(2)); - Expression e2 = Multiplication(Rational(2), Rational(5)); + Expression e1 = Multiplication::Builder(Rational(5), Rational(2)); + Expression e2 = Multiplication::Builder(Rational(2), Rational(5)); assert_multiplication_or_addition_is_ordered_as(e1, e2); } { @@ -32,8 +32,8 @@ QUIZ_CASE(poincare_expression_order) { constexpr int numberOfChildren = 3; Expression children[numberOfChildren] = {Rational(1), Rational(2), Rational(0)}; Expression childrenSorted[numberOfChildren] = {Rational(2), Rational(1), Rational(0)}; - Expression e1 = Addition(children, numberOfChildren); - Expression e2 = Addition(childrenSorted, numberOfChildren); + Expression e1 = Addition::Builder(children, numberOfChildren); + Expression e2 = Addition::Builder(childrenSorted, numberOfChildren); assert_multiplication_or_addition_is_ordered_as(e1, e2); } { @@ -44,65 +44,65 @@ QUIZ_CASE(poincare_expression_order) { constexpr int numberOfChildren = 3; Expression children[numberOfChildren] = {pi.clone(), i.clone(), e.clone()}; Expression childrenSorted[numberOfChildren] = {e, pi, i}; - Expression e1 = Addition(children, numberOfChildren); - Expression e2 = Addition(childrenSorted, numberOfChildren); + Expression e1 = Addition::Builder(children, numberOfChildren); + Expression e2 = Addition::Builder(childrenSorted, numberOfChildren); assert_multiplication_or_addition_is_ordered_as(e1, e2); } { // 2 * root(3) - Expression e1 = Multiplication(SquareRoot::Builder(Rational(3)), Rational(2)); - Expression e2 = Multiplication(Rational(2), SquareRoot::Builder(Rational(3))); + Expression e1 = Multiplication::Builder(SquareRoot::Builder(Rational(3)), Rational(2)); + Expression e2 = Multiplication::Builder(Rational(2), SquareRoot::Builder(Rational(3))); assert_multiplication_or_addition_is_ordered_as(e1, e2); } { constexpr int numberOfChildren = 4; Expression children[numberOfChildren] = { Symbol('c'), - Power(Symbol('b'), Rational(2)), - Power(Symbol('a'), Rational(2)), + Power::Builder(Symbol('b'), Rational(2)), + Power::Builder(Symbol('a'), Rational(2)), Symbol('a') }; Expression childrenSorted[numberOfChildren] = { - Power(Symbol('a'), Rational(2)), + Power::Builder(Symbol('a'), Rational(2)), Symbol('a'), - Power(Symbol('b'), Rational(2)), + Power::Builder(Symbol('b'), Rational(2)), Symbol('c') }; // a^2 + a + b^2 + c - Expression e1 = Addition(children, numberOfChildren); - Expression e2 = Addition(childrenSorted, numberOfChildren); + Expression e1 = Addition::Builder(children, numberOfChildren); + Expression e2 = Addition::Builder(childrenSorted, numberOfChildren); assert_multiplication_or_addition_is_ordered_as(e1, e2); } { // 2*x^3 + 3*x^2 - Expression child1 = Multiplication(Rational(2), Power(Symbol('x'), Rational(3))); - Expression child2 = Multiplication(Rational(3), Power(Symbol('x'), Rational(2))); - Expression e1 = Addition(child2.clone(), child1.clone()); - Expression e2 = Addition(child1, child2); + Expression child1 = Multiplication::Builder(Rational(2), Power::Builder(Symbol('x'), Rational(3))); + Expression child2 = Multiplication::Builder(Rational(3), Power::Builder(Symbol('x'), Rational(2))); + Expression e1 = Addition::Builder(child2.clone(), child1.clone()); + Expression e2 = Addition::Builder(child1, child2); assert_multiplication_or_addition_is_ordered_as(e1, e2); } { // 3*x + 2*x - Expression child1 = Multiplication(Rational(3), Symbol('x')); - Expression child2 = Multiplication(Rational(2), Symbol('x')); - Expression e1 = Addition(child2.clone(), child1.clone()); - Expression e2 = Addition(child1, child2); + Expression child1 = Multiplication::Builder(Rational(3), Symbol('x')); + Expression child2 = Multiplication::Builder(Rational(2), Symbol('x')); + Expression e1 = Addition::Builder(child2.clone(), child1.clone()); + Expression e2 = Addition::Builder(child1, child2); assert_multiplication_or_addition_is_ordered_as(e1, e2); } { // pi^a * pi^b - Expression child1 = Power(Constant(Ion::Charset::SmallPi), Symbol('a')); - Expression child2 = Power(Constant(Ion::Charset::SmallPi), Symbol('b')); - Expression e1 = Multiplication(child2.clone(), child1.clone()); - Expression e2 = Multiplication(child1, child2); + Expression child1 = Power::Builder(Constant(Ion::Charset::SmallPi), Symbol('a')); + Expression child2 = Power::Builder(Constant(Ion::Charset::SmallPi), Symbol('b')); + Expression e1 = Multiplication::Builder(child2.clone(), child1.clone()); + Expression e2 = Multiplication::Builder(child1, child2); assert_multiplication_or_addition_is_ordered_as(e1, e2); } { // pi^2 * pi^3 - Expression child1 = Power(Constant(Ion::Charset::SmallPi), Rational(2)); - Expression child2 = Power(Constant(Ion::Charset::SmallPi), Rational(3)); - Expression e1 = Multiplication(child2.clone(), child1.clone()); - Expression e2 = Multiplication(child1, child2); + Expression child1 = Power::Builder(Constant(Ion::Charset::SmallPi), Rational(2)); + Expression child2 = Power::Builder(Constant(Ion::Charset::SmallPi), Rational(3)); + Expression e1 = Multiplication::Builder(child2.clone(), child1.clone()); + Expression e2 = Multiplication::Builder(child1, child2); assert_multiplication_or_addition_is_ordered_as(e1, e2); } diff --git a/poincare/test/fraction_layout.cpp b/poincare/test/fraction_layout.cpp index 095721bd5..9d38c8691 100644 --- a/poincare/test/fraction_layout.cpp +++ b/poincare/test/fraction_layout.cpp @@ -25,8 +25,8 @@ QUIZ_CASE(poincare_fraction_layout_delete) { * --- -> "BackSpace" -> 12|34 * |34 * */ - HorizontalLayout layout1 = HorizontalLayout( - FractionLayout( + HorizontalLayout layout1 = HorizontalLayout::Builder( + FractionLayout::Builder( LayoutHelper::String("12", 2), LayoutHelper::String("34", 2) ) @@ -40,10 +40,10 @@ QUIZ_CASE(poincare_fraction_layout_delete) { * 1 + --- -> "BackSpace" -> 1+|3 * |3 * */ - HorizontalLayout layout2 = HorizontalLayout( + HorizontalLayout layout2 = HorizontalLayout::Builder( CharLayout('1'), CharLayout('+'), - FractionLayout( + FractionLayout::Builder( EmptyLayout(), CharLayout('3') ) @@ -55,7 +55,7 @@ QUIZ_CASE(poincare_fraction_layout_delete) { } QUIZ_CASE(poincare_fraction_layout_serialize) { - FractionLayout layout = FractionLayout( + FractionLayout layout = FractionLayout::Builder( CharLayout('1'), LayoutHelper::String("2+3", 3) ); diff --git a/poincare/test/layouts.cpp b/poincare/test/layouts.cpp index dff41720e..a69665b59 100644 --- a/poincare/test/layouts.cpp +++ b/poincare/test/layouts.cpp @@ -43,31 +43,37 @@ void assert_parsed_layout_is(Layout l, Poincare::Expression r) { QUIZ_CASE(poincare_create_all_layouts) { EmptyLayout e0; - AbsoluteValueLayout e1(e0); + AbsoluteValueLayout e1 = AbsoluteValueLayout::Builder(e0); CharLayout e2('a'); - BinomialCoefficientLayout e3(e1, e2); - CeilingLayout e4(e3); - RightParenthesisLayout e5; - RightSquareBracketLayout e6; - CondensedSumLayout e7(e4, e5, e6); - ConjugateLayout e8(e7); - LeftParenthesisLayout e10; - FloorLayout e11(e10); - FractionLayout e12(e8, e11); - HorizontalLayout e13; - LeftSquareBracketLayout e14; - IntegralLayout e15(e11, e12, e13, e14); - NthRootLayout e16(e15); - MatrixLayout e17; + BinomialCoefficientLayout e3 = BinomialCoefficientLayout::Builder(e1, e2); + CeilingLayout e4 = CeilingLayout::Builder(e3); + RightParenthesisLayout e5 = RightParenthesisLayout::Builder(); + RightSquareBracketLayout e6 = RightSquareBracketLayout::Builder(); + CondensedSumLayout e7 = CondensedSumLayout::Builder(e4, e5, e6); + ConjugateLayout e8 = ConjugateLayout::Builder(e7); + LeftParenthesisLayout e10 = LeftParenthesisLayout::Builder(); + FloorLayout e11 = FloorLayout::Builder(e10); + FractionLayout e12 = FractionLayout::Builder(e8, e11); + HorizontalLayout e13 = HorizontalLayout::Builder(); + LeftSquareBracketLayout e14 = LeftSquareBracketLayout::Builder(); + IntegralLayout e15 = IntegralLayout::Builder(e11, e12, e13, e14); + NthRootLayout e16 = NthRootLayout::Builder(e15); + MatrixLayout e17 = MatrixLayout::Builder(); EmptyLayout e18; EmptyLayout e19; EmptyLayout e20; - ProductLayout e21(e17, e18, e19, e20); + ProductLayout e21 = ProductLayout::Builder(e17, e18, e19, e20); EmptyLayout e22; EmptyLayout e23; EmptyLayout e24; - SumLayout e25(e21, e22, e23, e24); - VerticalOffsetLayout e26(e25, VerticalOffsetLayoutNode::Type::Superscript); + SumLayout e25 = SumLayout::Builder(e21, e22, e23, e24); + VerticalOffsetLayout e26 = VerticalOffsetLayout::Builder(e25, VerticalOffsetLayoutNode::Type::Superscript); +} + +Matrix BuildOneChildMatrix(Expression entry) { + Matrix m = Matrix::Builder(); + m.addChildAtIndexInPlace(entry, 0, 0); + return m; } QUIZ_CASE(poincare_parse_layouts) { @@ -75,31 +81,31 @@ QUIZ_CASE(poincare_parse_layouts) { Expression e; // 1+2 - l = HorizontalLayout( + l = HorizontalLayout::Builder( CharLayout('1'), CharLayout('+'), CharLayout('2')); - e = Addition(Rational(1), Rational(2)); + e = Addition::Builder(Rational(1), Rational(2)); assert_parsed_layout_is(l, e); // |3+3/6| - l = AbsoluteValueLayout( - HorizontalLayout( + l = AbsoluteValueLayout:: Builder( + HorizontalLayout::Builder( CharLayout('3'), CharLayout('+'), - FractionLayout( + FractionLayout::Builder( CharLayout('3'), CharLayout('6')))); e = AbsoluteValue::Builder( - Addition( + Addition::Builder( Rational(3), - Division( + Division::Builder( Rational(3), Rational(6)))); assert_parsed_layout_is(l, e); // binCoef(4,5) - l = BinomialCoefficientLayout( + l = BinomialCoefficientLayout::Builder( CharLayout('4'), CharLayout('5')); e = BinomialCoefficient::Builder( @@ -108,8 +114,8 @@ QUIZ_CASE(poincare_parse_layouts) { assert_parsed_layout_is(l, e); // ceil(4.6) - l = CeilingLayout( - HorizontalLayout( + l = CeilingLayout::Builder( + HorizontalLayout::Builder( CharLayout('4'), CharLayout('.'), CharLayout('6'))); @@ -118,8 +124,8 @@ QUIZ_CASE(poincare_parse_layouts) { assert_parsed_layout_is(l, e); // floor(7.2) - l = FloorLayout( - HorizontalLayout( + l = FloorLayout::Builder( + HorizontalLayout::Builder( CharLayout('7'), CharLayout('.'), CharLayout('2'))); @@ -128,30 +134,30 @@ QUIZ_CASE(poincare_parse_layouts) { assert_parsed_layout_is(l, e); // 2^(3+4) - l = HorizontalLayout( + l = HorizontalLayout::Builder( CharLayout('2'), - VerticalOffsetLayout( - HorizontalLayout( + VerticalOffsetLayout::Builder( + HorizontalLayout::Builder( CharLayout('3'), CharLayout('+'), CharLayout('4')), VerticalOffsetLayoutNode::Type::Superscript)); - e = Power( + e = Power::Builder( Rational(2), - Addition( + Addition::Builder( Rational(3), Rational(4))); assert_parsed_layout_is(l, e); // log_3(2) - HorizontalLayout l1 = HorizontalLayout(); + HorizontalLayout l1 = HorizontalLayout::Builder(); l1.addChildAtIndex(CharLayout('l'), l1.numberOfChildren(), l1.numberOfChildren(), nullptr); l1.addChildAtIndex(CharLayout('o'), l1.numberOfChildren(), l1.numberOfChildren(), nullptr); l1.addChildAtIndex(CharLayout('g'), l1.numberOfChildren(), l1.numberOfChildren(), nullptr); - l1.addChildAtIndex(VerticalOffsetLayout(CharLayout('3'), VerticalOffsetLayoutNode::Type::Subscript), l1.numberOfChildren(), l1.numberOfChildren(), nullptr); - l1.addChildAtIndex(LeftParenthesisLayout(), l1.numberOfChildren(), l1.numberOfChildren(), nullptr); + l1.addChildAtIndex(VerticalOffsetLayout::Builder(CharLayout('3'), VerticalOffsetLayoutNode::Type::Subscript), l1.numberOfChildren(), l1.numberOfChildren(), nullptr); + l1.addChildAtIndex(LeftParenthesisLayout::Builder(), l1.numberOfChildren(), l1.numberOfChildren(), nullptr); l1.addChildAtIndex(CharLayout('2'), l1.numberOfChildren(), l1.numberOfChildren(), nullptr); - l1.addChildAtIndex(RightParenthesisLayout(), l1.numberOfChildren(), l1.numberOfChildren(), nullptr); + l1.addChildAtIndex(RightParenthesisLayout::Builder(), l1.numberOfChildren(), l1.numberOfChildren(), nullptr); l = l1; e = Logarithm::Builder( Rational(2), @@ -159,14 +165,14 @@ QUIZ_CASE(poincare_parse_layouts) { assert_parsed_layout_is(l, e); // root(5,3) - l = NthRootLayout( + l = NthRootLayout::Builder( CharLayout('5'), CharLayout('3')); e = NthRoot::Builder(Rational(5), Rational(3)); assert_parsed_layout_is(l, e); // int(7, x, 4, 5) - l = IntegralLayout( + l = IntegralLayout::Builder( CharLayout('7'), CharLayout('x'), CharLayout('4'), @@ -179,52 +185,52 @@ QUIZ_CASE(poincare_parse_layouts) { assert_parsed_layout_is(l, e); // 2^2 ! - l = HorizontalLayout( + l = HorizontalLayout::Builder( CharLayout('2'), - VerticalOffsetLayout( + VerticalOffsetLayout::Builder( CharLayout('2'), VerticalOffsetLayoutNode::Type::Superscript), CharLayout('!')); - e = Factorial( - Power( + e = Factorial::Builder( + Power::Builder( Rational(2), Rational(2))); assert_parsed_layout_is(l, e); // 5* 6/(7+5) *3 - l = HorizontalLayout( + l = HorizontalLayout::Builder( CharLayout('5'), - FractionLayout( + FractionLayout::Builder( CharLayout('6'), - HorizontalLayout( + HorizontalLayout::Builder( CharLayout('7'), CharLayout('+'), CharLayout('5'))), CharLayout('3')); - e = Multiplication( + e = Multiplication::Builder( Rational(5), - Division( + Division::Builder( Rational(6), - Addition( + Addition::Builder( Rational(7), Rational(5))), Rational(3)); assert_parsed_layout_is(l, e); // [[3^2!, 7][4,5] - l = MatrixLayout( - HorizontalLayout( + l = MatrixLayout::Builder( + HorizontalLayout::Builder( CharLayout('3'), - VerticalOffsetLayout( + VerticalOffsetLayout::Builder( CharLayout('2'), VerticalOffsetLayoutNode::Type::Superscript), CharLayout('!')), CharLayout('7'), CharLayout('4'), CharLayout('5')); - Matrix m = Matrix( - Factorial( - Power( + Matrix m = BuildOneChildMatrix( + Factorial::Builder( + Power::Builder( Rational(3), Rational(2)))); m.addChildAtIndexInPlace(Rational(7), 1, 1); @@ -235,35 +241,35 @@ QUIZ_CASE(poincare_parse_layouts) { assert_parsed_layout_is(l, e); // 2^det([[3!, 7][4,5]) - l = HorizontalLayout( + l = HorizontalLayout::Builder( CharLayout('2'), - VerticalOffsetLayout( - MatrixLayout( - HorizontalLayout( + VerticalOffsetLayout::Builder( + MatrixLayout::Builder( + HorizontalLayout::Builder( CharLayout('3'), CharLayout('!')), CharLayout('7'), CharLayout('4'), CharLayout('5')), VerticalOffsetLayoutNode::Type::Superscript)); - m = Matrix( - Factorial( + m = BuildOneChildMatrix( + Factorial::Builder( Rational(3))); m.addChildAtIndexInPlace(Rational(7), 1, 1); m.addChildAtIndexInPlace(Rational(4), 2, 2); m.addChildAtIndexInPlace(Rational(5), 3, 3); m.setDimensions(2,2); - e = Power(Rational(2), m); + e = Power::Builder(Rational(2), m); assert_parsed_layout_is(l, e); // 2e^3 - l = HorizontalLayout( + l = HorizontalLayout::Builder( CharLayout('2'), CharLayout(Ion::Charset::Exponential), - VerticalOffsetLayout( + VerticalOffsetLayout::Builder( CharLayout('3'), VerticalOffsetLayoutNode::Type::Superscript)); - e = Multiplication(Rational(2),Power(Constant(Ion::Charset::Exponential),Parenthesis(Rational(3)))); - assert_parsed_expression_is("2X^(3)", Multiplication(Rational(2),Power(Constant(Ion::Charset::Exponential),Parenthesis(Rational(3))))); + e = Multiplication::Builder(Rational(2),Power::Builder(Constant(Ion::Charset::Exponential),Parenthesis::Builder(Rational(3)))); + assert_parsed_expression_is("2X^(3)", Multiplication::Builder(Rational(2),Power::Builder(Constant(Ion::Charset::Exponential),Parenthesis::Builder(Rational(3))))); assert_parsed_layout_is(l, e); } diff --git a/poincare/test/parentheses_layout.cpp b/poincare/test/parentheses_layout.cpp index 2518d312a..31cb61069 100644 --- a/poincare/test/parentheses_layout.cpp +++ b/poincare/test/parentheses_layout.cpp @@ -12,18 +12,18 @@ QUIZ_CASE(poincare_parenthesis_layout_size) { * 4 * Assert that the first and last parentheses have the same size. */ - HorizontalLayout layout = HorizontalLayout(); - LeftParenthesisLayout leftPar = LeftParenthesisLayout(); - RightParenthesisLayout rightPar = RightParenthesisLayout(); + HorizontalLayout layout = HorizontalLayout::Builder(); + LeftParenthesisLayout leftPar = LeftParenthesisLayout::Builder(); + RightParenthesisLayout rightPar = RightParenthesisLayout::Builder(); layout.addChildAtIndex(leftPar, 0, 0, nullptr); layout.addChildAtIndex(CharLayout('2'), 1, 1, nullptr); layout.addChildAtIndex(CharLayout('+'), 2, 2, nullptr); - layout.addChildAtIndex(LeftParenthesisLayout(), 3, 3, nullptr); - layout.addChildAtIndex(FractionLayout( + layout.addChildAtIndex(LeftParenthesisLayout::Builder(), 3, 3, nullptr); + layout.addChildAtIndex(FractionLayout::Builder( CharLayout('3'), CharLayout('4')), 4, 4, nullptr); - layout.addChildAtIndex(RightParenthesisLayout(), 4, 4, nullptr); + layout.addChildAtIndex(RightParenthesisLayout::Builder(), 4, 4, nullptr); layout.addChildAtIndex(CharLayout('6'), 5, 5, nullptr); layout.addChildAtIndex(rightPar, 7, 7, nullptr); layout.addChildAtIndex(CharLayout('1'), 8, 8, nullptr); diff --git a/poincare/test/parser.cpp b/poincare/test/parser.cpp index c2f313e25..f8f9cff22 100644 --- a/poincare/test/parser.cpp +++ b/poincare/test/parser.cpp @@ -104,7 +104,7 @@ QUIZ_CASE(poincare_parser_memory_exhaustion) { { Poincare::ExceptionCheckpoint ecp; if (ExceptionRun(ecp)) { - Addition a = Addition(); + Addition a = Addition::Builder(); while (true) { Expression e = Expression::Parse("1+2+3+4+5+6+7+8+9+10"); a.addChildAtIndexInPlace(e, 0, a.numberOfChildren()); @@ -124,65 +124,65 @@ QUIZ_CASE(poincare_parser_memory_exhaustion) { QUIZ_CASE(poincare_parser_parse) { assert_parsed_expression_is("1", Rational(1)); - assert_parsed_expression_is("(1)", Parenthesis(Rational(1))); - assert_parsed_expression_is("((1))", Parenthesis((Expression)Parenthesis(Rational(1)))); - assert_parsed_expression_is("1+2", Addition(Rational(1),Rational(2))); - assert_parsed_expression_is("(1)+2", Addition(Parenthesis(Rational(1)),Rational(2))); - assert_parsed_expression_is("(1+2)", Parenthesis(Addition(Rational(1),Rational(2)))); - assert_parsed_expression_is("1+2+3", Addition(Addition(Rational(1),Rational(2)),Rational(3))); - assert_parsed_expression_is("1+2+(3+4)", Addition(Addition(Rational(1),Rational(2)),Parenthesis(Addition(Rational(3),Rational(4))))); - assert_parsed_expression_is("1*2", Multiplication(Rational(1),Rational(2))); - assert_parsed_expression_is("1*2*3", Multiplication(Multiplication(Rational(1),Rational(2)),Rational(3))); - assert_parsed_expression_is("1+2*3", Addition(Rational(1), Multiplication(Rational(2), Rational(3)))); - assert_parsed_expression_is("1/2", Division(Rational(1),Rational(2))); - assert_parsed_expression_is("(1/2)", Parenthesis(Division(Rational(1),Rational(2)))); - assert_parsed_expression_is("1/2/3", Division(Division(Rational(1),Rational(2)),Rational(3))); - assert_parsed_expression_is("1/2*3", Multiplication(Division(Rational(1),Rational(2)),Rational(3))); - assert_parsed_expression_is("(1/2*3)", Parenthesis(Multiplication(Division(Rational(1),Rational(2)),Rational(3)))); - assert_parsed_expression_is("1*2/3", Multiplication(Rational(1),Division(Rational(2),Rational(3)))); - assert_parsed_expression_is("(1*2/3)", Parenthesis(Multiplication(Rational(1),Division(Rational(2),Rational(3))))); - assert_parsed_expression_is("(1/2/3)", Parenthesis(Division(Division(Rational(1),Rational(2)),Rational(3)))); - assert_parsed_expression_is("1^2", Power(Rational(1),Rational(2))); - assert_parsed_expression_is("1^2^3", Power(Rational(1),Power(Rational(2),Rational(3)))); + assert_parsed_expression_is("(1)", Parenthesis::Builder(Rational(1))); + assert_parsed_expression_is("((1))", Parenthesis::Builder((Expression)Parenthesis::Builder(Rational(1)))); + assert_parsed_expression_is("1+2", Addition::Builder(Rational(1),Rational(2))); + assert_parsed_expression_is("(1)+2", Addition::Builder(Parenthesis::Builder(Rational(1)),Rational(2))); + assert_parsed_expression_is("(1+2)", Parenthesis::Builder(Addition::Builder(Rational(1),Rational(2)))); + assert_parsed_expression_is("1+2+3", Addition::Builder(Addition::Builder(Rational(1),Rational(2)),Rational(3))); + assert_parsed_expression_is("1+2+(3+4)", Addition::Builder(Addition::Builder(Rational(1),Rational(2)),Parenthesis::Builder(Addition::Builder(Rational(3),Rational(4))))); + assert_parsed_expression_is("1*2", Multiplication::Builder(Rational(1),Rational(2))); + assert_parsed_expression_is("1*2*3", Multiplication::Builder(Multiplication::Builder(Rational(1),Rational(2)),Rational(3))); + assert_parsed_expression_is("1+2*3", Addition::Builder(Rational(1), Multiplication::Builder(Rational(2), Rational(3)))); + assert_parsed_expression_is("1/2", Division::Builder(Rational(1),Rational(2))); + assert_parsed_expression_is("(1/2)", Parenthesis::Builder(Division::Builder(Rational(1),Rational(2)))); + assert_parsed_expression_is("1/2/3", Division::Builder(Division::Builder(Rational(1),Rational(2)),Rational(3))); + assert_parsed_expression_is("1/2*3", Multiplication::Builder(Division::Builder(Rational(1),Rational(2)),Rational(3))); + assert_parsed_expression_is("(1/2*3)", Parenthesis::Builder(Multiplication::Builder(Division::Builder(Rational(1),Rational(2)),Rational(3)))); + assert_parsed_expression_is("1*2/3", Multiplication::Builder(Rational(1),Division::Builder(Rational(2),Rational(3)))); + assert_parsed_expression_is("(1*2/3)", Parenthesis::Builder(Multiplication::Builder(Rational(1),Division::Builder(Rational(2),Rational(3))))); + assert_parsed_expression_is("(1/2/3)", Parenthesis::Builder(Division::Builder(Division::Builder(Rational(1),Rational(2)),Rational(3)))); + assert_parsed_expression_is("1^2", Power::Builder(Rational(1),Rational(2))); + assert_parsed_expression_is("1^2^3", Power::Builder(Rational(1),Power::Builder(Rational(2),Rational(3)))); assert_parsed_expression_is("1=2", Equal(Rational(1),Rational(2))); assert_raises_parsing_error("=5"); assert_raises_parsing_error("1=2=3"); - assert_parsed_expression_is("-1", Opposite(Rational(1))); - assert_parsed_expression_is("(-1)", Parenthesis(Opposite(Rational(1)))); - assert_parsed_expression_is("1-2", Subtraction(Rational(1),Rational(2))); - assert_parsed_expression_is("-1-2", Subtraction(Opposite(Rational(1)),Rational(2))); - assert_parsed_expression_is("1-2-3", Subtraction(Subtraction(Rational(1),Rational(2)),Rational(3))); - assert_parsed_expression_is("(1-2)", Parenthesis(Subtraction(Rational(1),Rational(2)))); - assert_parsed_expression_is("1+-2", Addition(Rational(1),Opposite(Rational(2)))); - assert_parsed_expression_is("--1", Opposite((Expression)Opposite(Rational(1)))); - assert_parsed_expression_is("(1+2)-3", Subtraction(Parenthesis(Addition(Rational(1),Rational(2))),Rational(3))); - assert_parsed_expression_is("(2*-3)", Parenthesis(Multiplication(Rational(2),Opposite(Rational(3))))); - assert_parsed_expression_is("1^(2)-3", Subtraction(Power(Rational(1),Parenthesis(Rational(2))),Rational(3))); - assert_parsed_expression_is("1^2-3", Subtraction(Power(Rational(1),Rational(2)),Rational(3))); - assert_parsed_expression_is("2^-3", Power(Rational(2),Opposite(Rational(3)))); - assert_parsed_expression_is("2--2+-1", Addition(Subtraction(Rational(2),Opposite(Rational(2))),Opposite(Rational(1)))); - assert_parsed_expression_is("2--2*-1", Subtraction(Rational(2),Opposite(Multiplication(Rational(2),Opposite(Rational(1)))))); - assert_parsed_expression_is("-1^2", Opposite(Power(Rational(1),Rational(2)))); - assert_parsed_expression_is("2/-3/-4", Division(Division(Rational(2),Opposite(Rational(3))),Opposite(Rational(4)))); - assert_parsed_expression_is("1*2-3*4", Subtraction(Multiplication(Rational(1),Rational(2)),Multiplication(Rational(3),Rational(4)))); - assert_parsed_expression_is("-1*2", Opposite(Multiplication(Rational(1), Rational(2)))); - assert_parsed_expression_is("1!", Factorial(Rational(1))); - assert_parsed_expression_is("1+2!", Addition(Rational(1),Factorial(Rational(2)))); - assert_parsed_expression_is("1!+2", Addition(Factorial(Rational(1)),Rational(2))); - assert_parsed_expression_is("1!+2!", Addition(Factorial(Rational(1)),Factorial(Rational(2)))); - assert_parsed_expression_is("1*2!", Multiplication(Rational(1),Factorial(Rational(2)))); - assert_parsed_expression_is("1!*2", Multiplication(Factorial(Rational(1)),Rational(2))); - assert_parsed_expression_is("1!*2!", Multiplication(Factorial(Rational(1)),Factorial(Rational(2)))); - assert_parsed_expression_is("1-2!", Subtraction(Rational(1),Factorial(Rational(2)))); - assert_parsed_expression_is("1!-2", Subtraction(Factorial(Rational(1)),Rational(2))); - assert_parsed_expression_is("1!-2!", Subtraction(Factorial(Rational(1)),Factorial(Rational(2)))); - assert_parsed_expression_is("1/2!", Division(Rational(1),Factorial(Rational(2)))); - assert_parsed_expression_is("1!/2", Division(Factorial(Rational(1)),Rational(2))); - assert_parsed_expression_is("1!/2!", Division(Factorial(Rational(1)),Factorial(Rational(2)))); - assert_parsed_expression_is("1^2!", Power(Rational(1),Factorial(Rational(2)))); - assert_parsed_expression_is("1!^2", Power(Factorial(Rational(1)),Rational(2))); - assert_parsed_expression_is("1!^2!", Power(Factorial(Rational(1)),Factorial(Rational(2)))); - assert_parsed_expression_is("(1)!", Factorial(Parenthesis(Rational(1)))); + assert_parsed_expression_is("-1", Opposite::Builder(Rational(1))); + assert_parsed_expression_is("(-1)", Parenthesis::Builder(Opposite::Builder(Rational(1)))); + assert_parsed_expression_is("1-2", Subtraction::Builder(Rational(1),Rational(2))); + assert_parsed_expression_is("-1-2", Subtraction::Builder(Opposite::Builder(Rational(1)),Rational(2))); + assert_parsed_expression_is("1-2-3", Subtraction::Builder(Subtraction::Builder(Rational(1),Rational(2)),Rational(3))); + assert_parsed_expression_is("(1-2)", Parenthesis::Builder(Subtraction::Builder(Rational(1),Rational(2)))); + assert_parsed_expression_is("1+-2", Addition::Builder(Rational(1),Opposite::Builder(Rational(2)))); + assert_parsed_expression_is("--1", Opposite::Builder((Expression)Opposite::Builder(Rational(1)))); + assert_parsed_expression_is("(1+2)-3", Subtraction::Builder(Parenthesis::Builder(Addition::Builder(Rational(1),Rational(2))),Rational(3))); + assert_parsed_expression_is("(2*-3)", Parenthesis::Builder(Multiplication::Builder(Rational(2),Opposite::Builder(Rational(3))))); + assert_parsed_expression_is("1^(2)-3", Subtraction::Builder(Power::Builder(Rational(1),Parenthesis::Builder(Rational(2))),Rational(3))); + assert_parsed_expression_is("1^2-3", Subtraction::Builder(Power::Builder(Rational(1),Rational(2)),Rational(3))); + assert_parsed_expression_is("2^-3", Power::Builder(Rational(2),Opposite::Builder(Rational(3)))); + assert_parsed_expression_is("2--2+-1", Addition::Builder(Subtraction::Builder(Rational(2),Opposite::Builder(Rational(2))),Opposite::Builder(Rational(1)))); + assert_parsed_expression_is("2--2*-1", Subtraction::Builder(Rational(2),Opposite::Builder(Multiplication::Builder(Rational(2),Opposite::Builder(Rational(1)))))); + assert_parsed_expression_is("-1^2", Opposite::Builder(Power::Builder(Rational(1),Rational(2)))); + assert_parsed_expression_is("2/-3/-4", Division::Builder(Division::Builder(Rational(2),Opposite::Builder(Rational(3))),Opposite::Builder(Rational(4)))); + assert_parsed_expression_is("1*2-3*4", Subtraction::Builder(Multiplication::Builder(Rational(1),Rational(2)),Multiplication::Builder(Rational(3),Rational(4)))); + assert_parsed_expression_is("-1*2", Opposite::Builder(Multiplication::Builder(Rational(1), Rational(2)))); + assert_parsed_expression_is("1!", Factorial::Builder(Rational(1))); + assert_parsed_expression_is("1+2!", Addition::Builder(Rational(1),Factorial::Builder(Rational(2)))); + assert_parsed_expression_is("1!+2", Addition::Builder(Factorial::Builder(Rational(1)),Rational(2))); + assert_parsed_expression_is("1!+2!", Addition::Builder(Factorial::Builder(Rational(1)),Factorial::Builder(Rational(2)))); + assert_parsed_expression_is("1*2!", Multiplication::Builder(Rational(1),Factorial::Builder(Rational(2)))); + assert_parsed_expression_is("1!*2", Multiplication::Builder(Factorial::Builder(Rational(1)),Rational(2))); + assert_parsed_expression_is("1!*2!", Multiplication::Builder(Factorial::Builder(Rational(1)),Factorial::Builder(Rational(2)))); + assert_parsed_expression_is("1-2!", Subtraction::Builder(Rational(1),Factorial::Builder(Rational(2)))); + assert_parsed_expression_is("1!-2", Subtraction::Builder(Factorial::Builder(Rational(1)),Rational(2))); + assert_parsed_expression_is("1!-2!", Subtraction::Builder(Factorial::Builder(Rational(1)),Factorial::Builder(Rational(2)))); + assert_parsed_expression_is("1/2!", Division::Builder(Rational(1),Factorial::Builder(Rational(2)))); + assert_parsed_expression_is("1!/2", Division::Builder(Factorial::Builder(Rational(1)),Rational(2))); + assert_parsed_expression_is("1!/2!", Division::Builder(Factorial::Builder(Rational(1)),Factorial::Builder(Rational(2)))); + assert_parsed_expression_is("1^2!", Power::Builder(Rational(1),Factorial::Builder(Rational(2)))); + assert_parsed_expression_is("1!^2", Power::Builder(Factorial::Builder(Rational(1)),Rational(2))); + assert_parsed_expression_is("1!^2!", Power::Builder(Factorial::Builder(Rational(1)),Factorial::Builder(Rational(2)))); + assert_parsed_expression_is("(1)!", Factorial::Builder(Parenthesis::Builder(Rational(1)))); assert_raises_parsing_error("1+"); assert_raises_parsing_error(")"); assert_raises_parsing_error(")("); @@ -202,7 +202,7 @@ QUIZ_CASE(poincare_parser_parse) { } Matrix BuildMatrix(int rows, int columns, Expression entries[]) { - Matrix m; + Matrix m = Matrix::Builder(); int position = 0; for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { @@ -259,7 +259,7 @@ QUIZ_CASE(poincare_parser_symbols_and_functions) { assert_parsed_expression_is("ab12AB_(1)", Function("ab12AB_", 7, Rational(1))); assert_parsed_expression_is("f(g(x))", Function("f", 1, Function("g", 1, Symbol("x",1)))); assert_parsed_expression_is("f(g(1))", Function("f", 1, Function("g", 1, Rational(1)))); - assert_parsed_expression_is("f((1))", Function("f", 1, Parenthesis(Rational(1)))); + assert_parsed_expression_is("f((1))", Function("f", 1, Parenthesis::Builder(Rational(1)))); assert_raises_parsing_error("f(1,2)"); assert_raises_parsing_error("f(f)"); assert_raises_parsing_error("abcdefgh(1)"); @@ -333,12 +333,13 @@ QUIZ_CASE(poincare_parser_symbols_and_functions) { } QUIZ_CASE(poincare_parser_parse_store) { - assert_parsed_expression_is("1>a", Store(Rational(1),Symbol("a",1))); - assert_parsed_expression_is("1>e", Store(Rational(1),Symbol("e",1))); - assert_parsed_expression_is("1>f(x)", Store(Rational(1),Function("f",1,Symbol("x",1)))); - assert_parsed_expression_is("x>f(x)", Store(Symbol("x",1),Function("f",1,Symbol("x",1)))); - assert_parsed_expression_is("n>f(x)", Store(Symbol("n",1),Function("f",1,Symbol("x",1)))); - assert_parsed_expression_is("[[x]]>f(x)", Store(Matrix(Symbol('x')), Function("f", 1, Symbol('x')))); + assert_parsed_expression_is("1>a", Store::Builder(Rational(1),Symbol("a",1))); + assert_parsed_expression_is("1>e", Store::Builder(Rational(1),Symbol("e",1))); + assert_parsed_expression_is("1>f(x)", Store::Builder(Rational(1),Function("f",1,Symbol("x",1)))); + assert_parsed_expression_is("x>f(x)", Store::Builder(Symbol("x",1),Function("f",1,Symbol("x",1)))); + assert_parsed_expression_is("n>f(x)", Store::Builder(Symbol("n",1),Function("f",1,Symbol("x",1)))); + Expression m0[] = {Symbol('x')}; + assert_parsed_expression_is("[[x]]>f(x)", Store::Builder(BuildMatrix(1,1,m0), Function("f", 1, Symbol('x')))); assert_raises_parsing_error("a>b>c"); assert_raises_parsing_error("1>2"); assert_raises_parsing_error("1>"); @@ -368,27 +369,27 @@ QUIZ_CASE(poincare_parser_parse_store) { QUIZ_CASE(poincare_parser_implicit_multiplication) { assert_raises_parsing_error(".1.2"); assert_raises_parsing_error("1 2"); - assert_parsed_expression_is("1x", Multiplication(Rational(1),Symbol("x", 1))); - assert_parsed_expression_is("1ans", Multiplication(Rational(1),Symbol("ans", 3))); + assert_parsed_expression_is("1x", Multiplication::Builder(Rational(1),Symbol("x", 1))); + assert_parsed_expression_is("1ans", Multiplication::Builder(Rational(1),Symbol("ans", 3))); assert_parsed_expression_is("x1", Symbol("x1", 2)); - assert_parsed_expression_is("1x+2", Addition(Multiplication(Rational(1),Symbol("x", 1)),Rational(2))); - assert_parsed_expression_is("1P", Multiplication(Rational(1),Constant(Ion::Charset::SmallPi))); - assert_parsed_expression_is("1x-2", Subtraction(Multiplication(Rational(1),Symbol("x", 1)),Rational(2))); - assert_parsed_expression_is("-1x", Opposite(Multiplication(Rational(1),Symbol("x", 1)))); - assert_parsed_expression_is("2*1x", Multiplication(Rational(2),Multiplication(Rational(1),Symbol("x", 1)))); - assert_parsed_expression_is("2^1x", Multiplication(Power(Rational(2),Rational(1)),Symbol("x", 1))); - assert_parsed_expression_is("1x^2", Multiplication(Rational(1),Power(Symbol("x", 1),Rational(2)))); - assert_parsed_expression_is("2/1x", Division(Rational(2),Multiplication(Rational(1),Symbol("x", 1)))); - assert_parsed_expression_is("1x/2", Division(Multiplication(Rational(1),Symbol("x", 1)),Rational(2))); - assert_parsed_expression_is("(1)2", Multiplication(Parenthesis(Rational(1)),Rational(2))); - assert_parsed_expression_is("1(2)", Multiplication(Rational(1),Parenthesis(Rational(2)))); - assert_parsed_expression_is("sin(1)2", Multiplication(Sine::Builder(Rational(1)),Rational(2))); - assert_parsed_expression_is("1cos(2)", Multiplication(Rational(1),Cosine::Builder(Rational(2)))); - assert_parsed_expression_is("1!2", Multiplication(Factorial(Rational(1)),Rational(2))); - assert_parsed_expression_is("2X^(3)", Multiplication(Rational(2),Power(Constant(Ion::Charset::Exponential),Parenthesis(Rational(3))))); + assert_parsed_expression_is("1x+2", Addition::Builder(Multiplication::Builder(Rational(1),Symbol("x", 1)),Rational(2))); + assert_parsed_expression_is("1P", Multiplication::Builder(Rational(1),Constant(Ion::Charset::SmallPi))); + assert_parsed_expression_is("1x-2", Subtraction::Builder(Multiplication::Builder(Rational(1),Symbol("x", 1)),Rational(2))); + assert_parsed_expression_is("-1x", Opposite::Builder(Multiplication::Builder(Rational(1),Symbol("x", 1)))); + assert_parsed_expression_is("2*1x", Multiplication::Builder(Rational(2),Multiplication::Builder(Rational(1),Symbol("x", 1)))); + assert_parsed_expression_is("2^1x", Multiplication::Builder(Power::Builder(Rational(2),Rational(1)),Symbol("x", 1))); + assert_parsed_expression_is("1x^2", Multiplication::Builder(Rational(1),Power::Builder(Symbol("x", 1),Rational(2)))); + assert_parsed_expression_is("2/1x", Division::Builder(Rational(2),Multiplication::Builder(Rational(1),Symbol("x", 1)))); + assert_parsed_expression_is("1x/2", Division::Builder(Multiplication::Builder(Rational(1),Symbol("x", 1)),Rational(2))); + assert_parsed_expression_is("(1)2", Multiplication::Builder(Parenthesis::Builder(Rational(1)),Rational(2))); + assert_parsed_expression_is("1(2)", Multiplication::Builder(Rational(1),Parenthesis::Builder(Rational(2)))); + assert_parsed_expression_is("sin(1)2", Multiplication::Builder(Sine::Builder(Rational(1)),Rational(2))); + assert_parsed_expression_is("1cos(2)", Multiplication::Builder(Rational(1),Cosine::Builder(Rational(2)))); + assert_parsed_expression_is("1!2", Multiplication::Builder(Factorial::Builder(Rational(1)),Rational(2))); + assert_parsed_expression_is("2X^(3)", Multiplication::Builder(Rational(2),Power::Builder(Constant(Ion::Charset::Exponential),Parenthesis::Builder(Rational(3))))); Expression m1[] = {Rational(1)}; Matrix M1 = BuildMatrix(1,1,m1); Expression m2[] = {Rational(2)}; Matrix M2 = BuildMatrix(1,1,m2); - assert_parsed_expression_is("[[1]][[2]]", Multiplication(M1,M2)); + assert_parsed_expression_is("[[1]][[2]]", Multiplication::Builder(M1,M2)); } QUIZ_CASE(poincare_parser_expression_evaluation) { diff --git a/poincare/test/properties.cpp b/poincare/test/properties.cpp index 843d2369a..685aea2b1 100644 --- a/poincare/test/properties.cpp +++ b/poincare/test/properties.cpp @@ -77,15 +77,15 @@ void assert_expression_has_characteristic_range(Expression e, float range, Prefe QUIZ_CASE(poincare_characteristic_range) { assert_expression_has_characteristic_range(Cosine::Builder(Symbol(Poincare::Symbol::SpecialSymbols::UnknownX)), 360.0f); - assert_expression_has_characteristic_range(Cosine::Builder(Opposite(Symbol(Poincare::Symbol::SpecialSymbols::UnknownX))), 360.0f); + assert_expression_has_characteristic_range(Cosine::Builder(Opposite::Builder(Symbol(Poincare::Symbol::SpecialSymbols::UnknownX))), 360.0f); assert_expression_has_characteristic_range(Cosine::Builder(Symbol(Poincare::Symbol::SpecialSymbols::UnknownX)), 2.0f*M_PI, Preferences::AngleUnit::Radian); - assert_expression_has_characteristic_range(Cosine::Builder(Opposite(Symbol(Poincare::Symbol::SpecialSymbols::UnknownX))), 2.0f*M_PI, Preferences::AngleUnit::Radian); - assert_expression_has_characteristic_range(Sine::Builder(Addition(Multiplication(Rational(9),Symbol(Poincare::Symbol::SpecialSymbols::UnknownX)),Rational(10))), 40.0f); - assert_expression_has_characteristic_range(Addition(Sine::Builder(Addition(Multiplication(Rational(9),Symbol(Poincare::Symbol::SpecialSymbols::UnknownX)),Rational(10))),Cosine::Builder(Division(Symbol(Poincare::Symbol::SpecialSymbols::UnknownX),Rational(2)))), 720.0f); - assert_expression_has_characteristic_range(Addition(Sine::Builder(Addition(Multiplication(Rational(9),Symbol(Poincare::Symbol::SpecialSymbols::UnknownX)),Rational(10))),Cosine::Builder(Division(Symbol(Poincare::Symbol::SpecialSymbols::UnknownX),Rational(2)))), 4.0f*M_PI, Preferences::AngleUnit::Radian); + assert_expression_has_characteristic_range(Cosine::Builder(Opposite::Builder(Symbol(Poincare::Symbol::SpecialSymbols::UnknownX))), 2.0f*M_PI, Preferences::AngleUnit::Radian); + assert_expression_has_characteristic_range(Sine::Builder(Addition::Builder(Multiplication::Builder(Rational(9),Symbol(Poincare::Symbol::SpecialSymbols::UnknownX)),Rational(10))), 40.0f); + assert_expression_has_characteristic_range(Addition::Builder(Sine::Builder(Addition::Builder(Multiplication::Builder(Rational(9),Symbol(Poincare::Symbol::SpecialSymbols::UnknownX)),Rational(10))),Cosine::Builder(Division::Builder(Symbol(Poincare::Symbol::SpecialSymbols::UnknownX),Rational(2)))), 720.0f); + assert_expression_has_characteristic_range(Addition::Builder(Sine::Builder(Addition::Builder(Multiplication::Builder(Rational(9),Symbol(Poincare::Symbol::SpecialSymbols::UnknownX)),Rational(10))),Cosine::Builder(Division::Builder(Symbol(Poincare::Symbol::SpecialSymbols::UnknownX),Rational(2)))), 4.0f*M_PI, Preferences::AngleUnit::Radian); assert_expression_has_characteristic_range(Symbol(Poincare::Symbol::SpecialSymbols::UnknownX), NAN); - assert_expression_has_characteristic_range(Addition(Cosine::Builder(Rational(3)),Rational(2)), 0.0f); - assert_expression_has_characteristic_range(CommonLogarithm::Builder(Cosine::Builder(Multiplication(Rational(40),Symbol(Poincare::Symbol::SpecialSymbols::UnknownX)))), 9.0f); + assert_expression_has_characteristic_range(Addition::Builder(Cosine::Builder(Rational(3)),Rational(2)), 0.0f); + assert_expression_has_characteristic_range(CommonLogarithm::Builder(Cosine::Builder(Multiplication::Builder(Rational(40),Symbol(Poincare::Symbol::SpecialSymbols::UnknownX)))), 9.0f); assert_expression_has_characteristic_range(Cosine::Builder((Expression)Cosine::Builder(Symbol(Poincare::Symbol::SpecialSymbols::UnknownX))), 360.0f); assert_simplify("cos(x)>f(x)"); assert_expression_has_characteristic_range(Function("f",1,Symbol(Poincare::Symbol::SpecialSymbols::UnknownX)), 360.0f); diff --git a/poincare/test/user_variable.cpp b/poincare/test/user_variable.cpp index 7e7ba4490..eb4290428 100644 --- a/poincare/test/user_variable.cpp +++ b/poincare/test/user_variable.cpp @@ -157,9 +157,9 @@ QUIZ_CASE(poincare_user_variable_functions_with_context) { assert_simplify("x^2>f(x)"); // Approximate f(?-2) with ? = 5 const char x[] = {Symbol::SpecialSymbols::UnknownX, 0}; - assert_parsed_expression_approximates_with_value_for_symbol(Function("f", 1, Subtraction(Symbol(Symbol::SpecialSymbols::UnknownX), Rational(2))), x, 5.0, 9.0); + assert_parsed_expression_approximates_with_value_for_symbol(Function("f", 1, Subtraction::Builder(Symbol(Symbol::SpecialSymbols::UnknownX), Rational(2))), x, 5.0, 9.0); // Approximate f(?-1)+f(?+1) with ? = 3 - assert_parsed_expression_approximates_with_value_for_symbol(Addition(Function("f", 1, Subtraction(Symbol(Symbol::SpecialSymbols::UnknownX), Rational(1))), Function("f", 1, Addition(Symbol(Symbol::SpecialSymbols::UnknownX), Rational(1)))), x, 3.0, 20.0); + assert_parsed_expression_approximates_with_value_for_symbol(Addition::Builder(Function("f", 1, Subtraction::Builder(Symbol(Symbol::SpecialSymbols::UnknownX), Rational(1))), Function("f", 1, Addition::Builder(Symbol(Symbol::SpecialSymbols::UnknownX), Rational(1)))), x, 3.0, 20.0); // Clean the storage for other tests Ion::Storage::sharedStorage()->recordNamed("f.func").destroy(); diff --git a/poincare/test/vertical_offset_layout.cpp b/poincare/test/vertical_offset_layout.cpp index 77c7385f3..7379abfa7 100644 --- a/poincare/test/vertical_offset_layout.cpp +++ b/poincare/test/vertical_offset_layout.cpp @@ -7,9 +7,9 @@ using namespace Poincare; QUIZ_CASE(poincare_vertical_offset_layout_serialize) { - HorizontalLayout layout = HorizontalLayout( + HorizontalLayout layout = HorizontalLayout::Builder( CharLayout('2'), - VerticalOffsetLayout( + VerticalOffsetLayout::Builder( LayoutHelper::String("x+5", 3), VerticalOffsetLayoutNode::Type::Superscript ) From 902dda34d6a6a10baa097c36e43fdabd5dc1b0ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 15 Feb 2019 16:40:57 +0100 Subject: [PATCH 337/373] [poincare] Add comment --- poincare/include/poincare/expression.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 12bd9af66..72c860f7a 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -187,11 +187,23 @@ public: int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const; /* Simplification */ + /* Simplification routines are divided in 2 groups: + * - ParseAndSimplify & simplify methods are used before approximating the + * expression. We simplify beforehand to avoid precision error but the + * simplified expression is never displayed. The ReductionTarget is + * therefore the System for these methods. + * - ParseAndSimplifyAndApproximate & simplifyAndApproximate methods are used + * to simplify and approximate the expression for the User. They take into + * account the complex format required in the expression they return. + * (For instance, in Polar mode, they return an expression of the form + * r*e^(i*th) reduced and approximated.) */ static Expression ParseAndSimplify(const char * text, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); - static void ParseAndSimplifyAndApproximate(const char * text, Expression * simplifiedExpression, Expression * approximateExpression, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); Expression simplify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + + static void ParseAndSimplifyAndApproximate(const char * text, Expression * simplifiedExpression, Expression * approximateExpression, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); void simplifyAndApproximate(Expression * simplifiedExpression, Expression * approximateExpression, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); Expression reduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + static Expression ExpressionWithoutSymbols(Expression expressionWithSymbols, Context & context); Expression radianToDegree(); Expression degreeToRadian(); From 7b5f3c570d45c848a1b13deacfd97c911b99ef9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 18 Feb 2019 11:37:22 +0100 Subject: [PATCH 338/373] [poincare] Change the way Expression are built --- apps/calculation/calculation.cpp | 4 +- apps/calculation/calculation_store.cpp | 2 +- apps/regression/calculation_controller.cpp | 2 +- apps/regression/model/cubic_model.cpp | 40 +-- apps/regression/model/exponential_model.cpp | 12 +- apps/regression/model/linear_model.cpp | 10 +- apps/regression/model/logarithmic_model.cpp | 18 +- apps/regression/model/logistic_model.cpp | 20 +- apps/regression/model/power_model.cpp | 8 +- apps/regression/model/quadratic_model.cpp | 26 +- apps/regression/model/quartic_model.cpp | 54 +-- apps/regression/model/trigonometric_model.cpp | 30 +- apps/regression/regression_context.cpp | 2 +- apps/sequence/cache_context.cpp | 2 +- apps/sequence/graph/term_sum_controller.cpp | 4 +- apps/sequence/list/sequence_toolbox.cpp | 6 +- .../list/type_parameter_controller.cpp | 2 +- apps/sequence/sequence.cpp | 22 +- .../sub_menu/preferences_controller.cpp | 2 +- apps/shared/global_context.cpp | 2 +- apps/shared/storage_cartesian_function.cpp | 4 +- apps/shared/storage_expression_model.cpp | 2 +- apps/shared/storage_sum_graph_controller.cpp | 2 +- apps/shared/sum_graph_controller.cpp | 2 +- apps/solver/equation.cpp | 6 +- apps/solver/equation_store.cpp | 50 +-- apps/solver/solutions_controller.cpp | 2 +- apps/statistics/statistics_context.cpp | 2 +- poincare/Makefile | 2 + poincare/include/poincare/absolute_value.h | 7 +- .../include/poincare/absolute_value_layout.h | 9 +- poincare/include/poincare/addition.h | 14 +- poincare/include/poincare/arc_cosine.h | 6 +- poincare/include/poincare/arc_sine.h | 6 +- poincare/include/poincare/arc_tangent.h | 6 +- .../include/poincare/binomial_coefficient.h | 6 +- .../poincare/binomial_coefficient_layout.h | 11 +- poincare/include/poincare/ceiling.h | 6 +- poincare/include/poincare/ceiling_layout.h | 7 +- poincare/include/poincare/char_layout.h | 4 +- poincare/include/poincare/complex.h | 11 +- poincare/include/poincare/complex_argument.h | 6 +- poincare/include/poincare/complex_cartesian.h | 8 +- .../include/poincare/condensed_sum_layout.h | 11 +- .../include/poincare/confidence_interval.h | 13 +- poincare/include/poincare/conjugate.h | 6 +- poincare/include/poincare/conjugate_layout.h | 7 +- poincare/include/poincare/constant.h | 4 +- poincare/include/poincare/cosine.h | 6 +- poincare/include/poincare/decimal.h | 23 +- poincare/include/poincare/derivative.h | 9 +- poincare/include/poincare/determinant.h | 6 +- poincare/include/poincare/division.h | 12 +- poincare/include/poincare/division_quotient.h | 7 +- .../include/poincare/division_remainder.h | 7 +- poincare/include/poincare/empty_expression.h | 2 +- poincare/include/poincare/empty_layout.h | 4 +- poincare/include/poincare/equal.h | 5 +- poincare/include/poincare/factor.h | 6 +- poincare/include/poincare/factorial.h | 9 +- poincare/include/poincare/float.h | 8 +- poincare/include/poincare/floor.h | 6 +- poincare/include/poincare/floor_layout.h | 7 +- poincare/include/poincare/frac_part.h | 6 +- poincare/include/poincare/fraction_layout.h | 10 +- poincare/include/poincare/function.h | 9 +- poincare/include/poincare/ghost.h | 9 +- .../include/poincare/great_common_divisor.h | 7 +- poincare/include/poincare/grid_layout.h | 3 +- poincare/include/poincare/horizontal_layout.h | 3 +- .../include/poincare/hyperbolic_arc_cosine.h | 6 +- .../include/poincare/hyperbolic_arc_sine.h | 6 +- .../include/poincare/hyperbolic_arc_tangent.h | 6 +- poincare/include/poincare/hyperbolic_cosine.h | 6 +- poincare/include/poincare/hyperbolic_sine.h | 6 +- .../include/poincare/hyperbolic_tangent.h | 6 +- poincare/include/poincare/imaginary_part.h | 8 +- poincare/include/poincare/infinity.h | 6 +- poincare/include/poincare/integer.h | 3 +- poincare/include/poincare/integral.h | 10 +- poincare/include/poincare/integral_layout.h | 12 +- .../include/poincare/least_common_multiple.h | 7 +- .../poincare/left_parenthesis_layout.h | 5 +- .../poincare/left_square_bracket_layout.h | 5 +- poincare/include/poincare/logarithm.h | 14 +- poincare/include/poincare/matrix.h | 3 +- poincare/include/poincare/matrix_complex.h | 4 +- poincare/include/poincare/matrix_dimension.h | 6 +- poincare/include/poincare/matrix_inverse.h | 6 +- poincare/include/poincare/matrix_layout.h | 3 +- poincare/include/poincare/matrix_trace.h | 6 +- poincare/include/poincare/matrix_transpose.h | 6 +- poincare/include/poincare/multiplication.h | 18 +- .../include/poincare/naperian_logarithm.h | 8 +- poincare/include/poincare/nth_root.h | 7 +- poincare/include/poincare/nth_root_layout.h | 26 +- poincare/include/poincare/opposite.h | 12 +- poincare/include/poincare/parenthesis.h | 7 +- .../include/poincare/permute_coefficient.h | 8 +- poincare/include/poincare/power.h | 8 +- .../include/poincare/prediction_interval.h | 7 +- poincare/include/poincare/product.h | 10 +- poincare/include/poincare/product_layout.h | 12 +- poincare/include/poincare/randint.h | 7 +- poincare/include/poincare/random.h | 3 +- poincare/include/poincare/rational.h | 24 +- poincare/include/poincare/real_part.h | 8 +- .../poincare/right_parenthesis_layout.h | 5 +- .../poincare/right_square_bracket_layout.h | 6 +- poincare/include/poincare/round.h | 7 +- poincare/include/poincare/sign_function.h | 6 +- poincare/include/poincare/sine.h | 6 +- poincare/include/poincare/square_root.h | 5 +- poincare/include/poincare/store.h | 8 +- poincare/include/poincare/subtraction.h | 13 +- poincare/include/poincare/sum.h | 10 +- poincare/include/poincare/sum_layout.h | 12 +- poincare/include/poincare/symbol.h | 10 +- poincare/include/poincare/symbol_abstract.h | 2 - poincare/include/poincare/tangent.h | 6 +- poincare/include/poincare/tree_handle.h | 3 + poincare/include/poincare/tree_node.h | 1 - poincare/include/poincare/tree_pool.h | 6 +- poincare/include/poincare/undefined.h | 2 +- poincare/include/poincare/unreal.h | 3 +- .../include/poincare/vertical_offset_layout.h | 12 +- poincare/src/absolute_value.cpp | 9 +- poincare/src/absolute_value_layout.cpp | 12 + poincare/src/addition.cpp | 25 +- poincare/src/approximation_helper.cpp | 6 +- poincare/src/arc_cosine.cpp | 9 +- poincare/src/arc_sine.cpp | 9 +- poincare/src/arc_tangent.cpp | 9 +- poincare/src/binomial_coefficient.cpp | 27 +- poincare/src/binomial_coefficient_layout.cpp | 8 + poincare/src/ceiling.cpp | 17 +- poincare/src/ceiling_layout.cpp | 7 + poincare/src/char_layout.cpp | 10 +- poincare/src/complex.cpp | 26 +- poincare/src/complex_argument.cpp | 15 +- poincare/src/complex_cartesian.cpp | 64 ++-- poincare/src/condensed_sum_layout.cpp | 9 +- poincare/src/confidence_interval.cpp | 26 +- poincare/src/conjugate.cpp | 11 +- poincare/src/conjugate_layout.cpp | 7 + poincare/src/constant.cpp | 21 +- poincare/src/cosine.cpp | 9 +- poincare/src/decimal.cpp | 44 ++- poincare/src/derivative.cpp | 13 +- poincare/src/determinant.cpp | 9 +- poincare/src/division.cpp | 18 +- poincare/src/division_quotient.cpp | 19 +- poincare/src/division_remainder.cpp | 19 +- poincare/src/empty_expression.cpp | 9 +- poincare/src/empty_layout.cpp | 13 +- poincare/src/equal.cpp | 11 +- poincare/src/expression.cpp | 38 +- poincare/src/factor.cpp | 19 +- poincare/src/factorial.cpp | 19 +- poincare/src/float.cpp | 13 +- poincare/src/floor.cpp | 15 +- poincare/src/floor_layout.cpp | 12 + poincare/src/frac_part.cpp | 11 +- poincare/src/fraction_layout.cpp | 11 +- poincare/src/function.cpp | 21 +- poincare/src/great_common_divisor.cpp | 18 +- poincare/src/grid_layout.cpp | 11 +- poincare/src/horizontal_layout.cpp | 9 +- poincare/src/hyperbolic_arc_cosine.cpp | 9 +- poincare/src/hyperbolic_arc_sine.cpp | 9 +- poincare/src/hyperbolic_arc_tangent.cpp | 9 +- poincare/src/hyperbolic_cosine.cpp | 9 +- poincare/src/hyperbolic_sine.cpp | 9 +- poincare/src/hyperbolic_tangent.cpp | 9 +- poincare/src/imaginary_part.cpp | 9 +- poincare/src/infinity.cpp | 11 +- poincare/src/integer.cpp | 33 +- poincare/src/integral.cpp | 12 +- poincare/src/integral_layout.cpp | 7 + poincare/src/layout.cpp | 2 +- poincare/src/layout_cursor.cpp | 38 +- poincare/src/layout_helper.cpp | 4 +- poincare/src/least_common_multiple.cpp | 19 +- poincare/src/left_parenthesis_layout.cpp | 7 + poincare/src/left_square_bracket_layout.cpp | 7 + poincare/src/logarithm.cpp | 55 +-- poincare/src/matrix.cpp | 25 +- poincare/src/matrix_complex.cpp | 31 +- poincare/src/matrix_dimension.cpp | 21 +- poincare/src/matrix_inverse.cpp | 15 +- poincare/src/matrix_layout.cpp | 7 + poincare/src/matrix_trace.cpp | 13 +- poincare/src/matrix_transpose.cpp | 7 + poincare/src/multiplication.cpp | 41 ++- poincare/src/naperian_logarithm.cpp | 9 +- poincare/src/nth_root.cpp | 13 +- poincare/src/nth_root_layout.cpp | 14 + poincare/src/number.cpp | 22 +- poincare/src/opposite.cpp | 17 +- poincare/src/parenthesis.cpp | 7 + poincare/src/parsing/parser.cpp | 24 +- poincare/src/permute_coefficient.cpp | 23 +- poincare/src/power.cpp | 131 +++---- poincare/src/prediction_interval.cpp | 25 +- poincare/src/product.cpp | 9 +- poincare/src/product_layout.cpp | 7 + poincare/src/randint.cpp | 9 +- poincare/src/random.cpp | 9 +- poincare/src/rational.cpp | 73 ++-- poincare/src/real_part.cpp | 7 + poincare/src/right_parenthesis_layout.cpp | 7 + poincare/src/right_square_bracket_layout.cpp | 7 + poincare/src/round.cpp | 19 +- poincare/src/sequence.cpp | 2 +- poincare/src/sign_function.cpp | 25 +- poincare/src/sine.cpp | 9 +- poincare/src/square_root.cpp | 11 +- poincare/src/store.cpp | 15 +- poincare/src/subtraction.cpp | 18 +- poincare/src/sum.cpp | 9 +- poincare/src/sum_layout.cpp | 7 + poincare/src/symbol.cpp | 33 +- poincare/src/symbol_abstract.cpp | 18 +- poincare/src/tangent.cpp | 9 +- poincare/src/tree_handle.cpp | 26 ++ poincare/src/tree_pool.cpp | 127 ------- poincare/src/trigonometry.cpp | 30 +- poincare/src/undefined.cpp | 7 + poincare/src/unreal.cpp | 6 + poincare/src/variable_context.cpp | 2 +- poincare/src/vertical_offset_layout.cpp | 7 + poincare/test/addition.cpp | 12 +- poincare/test/convert_expression_to_text.cpp | 112 +++--- poincare/test/decimal.cpp | 36 +- poincare/test/expression.cpp | 2 +- poincare/test/expression_order.cpp | 50 +-- poincare/test/float.cpp | 40 +-- poincare/test/fraction_layout.cpp | 10 +- poincare/test/layouts.cpp | 198 +++++----- poincare/test/number.cpp | 30 +- poincare/test/parentheses_layout.cpp | 12 +- poincare/test/parser.cpp | 338 +++++++++--------- poincare/test/properties.cpp | 24 +- poincare/test/rational.cpp | 78 ++-- poincare/test/tree/blob_node.h | 10 +- poincare/test/tree/pair_node.h | 11 +- poincare/test/tree/tree_handle.cpp | 24 +- poincare/test/user_variable.cpp | 16 +- poincare/test/vertical_offset_layout.cpp | 2 +- 249 files changed, 2076 insertions(+), 1908 deletions(-) create mode 100644 poincare/src/absolute_value_layout.cpp create mode 100644 poincare/src/floor_layout.cpp diff --git a/apps/calculation/calculation.cpp b/apps/calculation/calculation.cpp index e794cbf30..1bf479107 100644 --- a/apps/calculation/calculation.cpp +++ b/apps/calculation/calculation.cpp @@ -125,7 +125,7 @@ Expression Calculation::exactOutput() { * 'cos(pi/4) = 0.999906' (which is true in degree). */ Expression exactOutput = Expression::Parse(m_exactOutputText); if (exactOutput.isUninitialized()) { - return Undefined(); + return Undefined::Builder(); } return exactOutput; } @@ -178,7 +178,7 @@ Calculation::EqualSign Calculation::exactAndApproximateDisplayedOutputsAreEqual( Preferences * preferences = Preferences::sharedPreferences(); Expression exactOutputExpression = PoincareHelpers::ParseAndSimplify(m_exactOutputText, *context); if (exactOutputExpression.isUninitialized()) { - exactOutputExpression = Undefined(); + exactOutputExpression = Undefined::Builder(); } Preferences::ComplexFormat complexFormat = Expression::UpdatedComplexFormatWithTextInput(preferences->complexFormat(), m_inputText); m_equalSign = exactOutputExpression.isEqualToItsApproximationLayout(approximateOutput(context), buffer, bufferSize, complexFormat, preferences->angleUnit(), preferences->displayMode(), preferences->numberOfSignificantDigits(), *context) ? EqualSign::Equal : EqualSign::Approximation; diff --git a/apps/calculation/calculation_store.cpp b/apps/calculation/calculation_store.cpp index 64813e188..d235445d1 100644 --- a/apps/calculation/calculation_store.cpp +++ b/apps/calculation/calculation_store.cpp @@ -88,7 +88,7 @@ void CalculationStore::tidy() { Expression CalculationStore::ansExpression(Context * context) { if (numberOfCalculations() == 0) { - return Rational(0); + return Rational::Builder(0); } Calculation * lastCalculation = calculationAtIndex(numberOfCalculations()-1); /* Special case: the exact output is a Store/Equal expression. diff --git a/apps/regression/calculation_controller.cpp b/apps/regression/calculation_controller.cpp index 3b21ba53f..895256377 100644 --- a/apps/regression/calculation_controller.cpp +++ b/apps/regression/calculation_controller.cpp @@ -25,7 +25,7 @@ CalculationController::CalculationController(Responder * parentResponder, Button m_hideableCell(), m_store(store) { - m_r2Layout = HorizontalLayout::Builder(CharLayout('r', KDFont::SmallFont), VerticalOffsetLayout::Builder(CharLayout('2', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Superscript)); + m_r2Layout = HorizontalLayout::Builder(CharLayout::Builder('r', KDFont::SmallFont), VerticalOffsetLayout::Builder(CharLayout::Builder('2', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Superscript)); m_selectableTableView.setVerticalCellOverlap(0); m_selectableTableView.setBackgroundColor(Palette::WallScreenDark); m_selectableTableView.setMargins(k_margin, k_scrollBarMargin, k_scrollBarMargin, k_margin); diff --git a/apps/regression/model/cubic_model.cpp b/apps/regression/model/cubic_model.cpp index 1452ccf53..da7fc39c6 100644 --- a/apps/regression/model/cubic_model.cpp +++ b/apps/regression/model/cubic_model.cpp @@ -20,27 +20,27 @@ namespace Regression { Layout CubicModel::layout() { if (m_layout.isUninitialized()) { const Layout layoutChildren[] = { - CharLayout('a', KDFont::SmallFont), - CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), - CharLayout('X', KDFont::SmallFont), + CharLayout::Builder('a', KDFont::SmallFont), + CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), + CharLayout::Builder('X', KDFont::SmallFont), VerticalOffsetLayout::Builder( - CharLayout('3', KDFont::SmallFont), + CharLayout::Builder('3', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Superscript ), - CharLayout('+', KDFont::SmallFont), - CharLayout('b', KDFont::SmallFont), - CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), - CharLayout('X', KDFont::SmallFont), + CharLayout::Builder('+', KDFont::SmallFont), + CharLayout::Builder('b', KDFont::SmallFont), + CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), + CharLayout::Builder('X', KDFont::SmallFont), VerticalOffsetLayout::Builder( - CharLayout('2', KDFont::SmallFont), + CharLayout::Builder('2', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Superscript ), - CharLayout('+', KDFont::SmallFont), - CharLayout('c', KDFont::SmallFont), - CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), - CharLayout('X', KDFont::SmallFont), - CharLayout('+', KDFont::SmallFont), - CharLayout('d', KDFont::SmallFont), + CharLayout::Builder('+', KDFont::SmallFont), + CharLayout::Builder('c', KDFont::SmallFont), + CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), + CharLayout::Builder('X', KDFont::SmallFont), + CharLayout::Builder('+', KDFont::SmallFont), + CharLayout::Builder('d', KDFont::SmallFont), }; m_layout = HorizontalLayout::Builder(layoutChildren, 15); } @@ -56,16 +56,16 @@ Expression CubicModel::simplifiedExpression(double * modelCoefficients, Poincare Multiplication::Builder( Number::DecimalNumber(a), Power::Builder( - Symbol('x'), - Decimal(3.0))), + Symbol::Builder('x'), + Decimal::Builder(3.0))), Multiplication::Builder( Number::DecimalNumber(b), Power::Builder( - Symbol('x'), - Decimal(2.0))), + Symbol::Builder('x'), + Decimal::Builder(2.0))), Multiplication::Builder( Number::DecimalNumber(c), - Symbol('x')), + Symbol::Builder('x')), Number::DecimalNumber(d) }; // a*x^3+b*x^2+c*x+d diff --git a/apps/regression/model/exponential_model.cpp b/apps/regression/model/exponential_model.cpp index e7097bcf8..52492b4fe 100644 --- a/apps/regression/model/exponential_model.cpp +++ b/apps/regression/model/exponential_model.cpp @@ -12,14 +12,14 @@ namespace Regression { Layout ExponentialModel::layout() { if (m_layout.isUninitialized()) { const Layout layoutChildren[] = { - CharLayout('a', KDFont::SmallFont), - CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), - CharLayout('e', KDFont::SmallFont), + CharLayout::Builder('a', KDFont::SmallFont), + CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), + CharLayout::Builder('e', KDFont::SmallFont), VerticalOffsetLayout::Builder( HorizontalLayout::Builder( - CharLayout('b', KDFont::SmallFont), - CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), - CharLayout('X', KDFont::SmallFont) + CharLayout::Builder('b', KDFont::SmallFont), + CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), + CharLayout::Builder('X', KDFont::SmallFont) ), VerticalOffsetLayoutNode::Type::Superscript ) diff --git a/apps/regression/model/linear_model.cpp b/apps/regression/model/linear_model.cpp index 11992808c..272505f6c 100644 --- a/apps/regression/model/linear_model.cpp +++ b/apps/regression/model/linear_model.cpp @@ -12,11 +12,11 @@ namespace Regression { Layout LinearModel::layout() { if (m_layout.isUninitialized()) { const Layout layoutChildren[] = { - CharLayout('a', KDFont::SmallFont), - CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), - CharLayout('X', KDFont::SmallFont), - CharLayout('+', KDFont::SmallFont), - CharLayout('b', KDFont::SmallFont), + CharLayout::Builder('a', KDFont::SmallFont), + CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), + CharLayout::Builder('X', KDFont::SmallFont), + CharLayout::Builder('+', KDFont::SmallFont), + CharLayout::Builder('b', KDFont::SmallFont), }; m_layout = HorizontalLayout::Builder(layoutChildren, 5); } diff --git a/apps/regression/model/logarithmic_model.cpp b/apps/regression/model/logarithmic_model.cpp index 546f434ea..bb585ea59 100644 --- a/apps/regression/model/logarithmic_model.cpp +++ b/apps/regression/model/logarithmic_model.cpp @@ -12,15 +12,15 @@ namespace Regression { Layout LogarithmicModel::layout() { if (m_layout.isUninitialized()) { const Layout layoutChildren[] = { - CharLayout('a', KDFont::SmallFont), - CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), - CharLayout('l', KDFont::SmallFont), - CharLayout('n', KDFont::SmallFont), - CharLayout('(', KDFont::SmallFont), - CharLayout('X', KDFont::SmallFont), - CharLayout(')', KDFont::SmallFont), - CharLayout('+', KDFont::SmallFont), - CharLayout('b', KDFont::SmallFont) + CharLayout::Builder('a', KDFont::SmallFont), + CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), + CharLayout::Builder('l', KDFont::SmallFont), + CharLayout::Builder('n', KDFont::SmallFont), + CharLayout::Builder('(', KDFont::SmallFont), + CharLayout::Builder('X', KDFont::SmallFont), + CharLayout::Builder(')', KDFont::SmallFont), + CharLayout::Builder('+', KDFont::SmallFont), + CharLayout::Builder('b', KDFont::SmallFont) }; m_layout = HorizontalLayout::Builder(layoutChildren, 9); } diff --git a/apps/regression/model/logistic_model.cpp b/apps/regression/model/logistic_model.cpp index 79b8d3bdc..c3f91bf95 100644 --- a/apps/regression/model/logistic_model.cpp +++ b/apps/regression/model/logistic_model.cpp @@ -13,24 +13,24 @@ namespace Regression { Layout LogisticModel::layout() { if (m_layout.isUninitialized()) { const Layout exponentLayoutChildren[] = { - CharLayout('-', KDFont::SmallFont), - CharLayout('b', KDFont::SmallFont), - CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), - CharLayout('X', KDFont::SmallFont) + CharLayout::Builder('-', KDFont::SmallFont), + CharLayout::Builder('b', KDFont::SmallFont), + CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), + CharLayout::Builder('X', KDFont::SmallFont) }; const Layout layoutChildren[] = { - CharLayout('1', KDFont::SmallFont), - CharLayout('+', KDFont::SmallFont), - CharLayout('a', KDFont::SmallFont), - CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), - CharLayout('e', KDFont::SmallFont), + CharLayout::Builder('1', KDFont::SmallFont), + CharLayout::Builder('+', KDFont::SmallFont), + CharLayout::Builder('a', KDFont::SmallFont), + CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), + CharLayout::Builder('e', KDFont::SmallFont), VerticalOffsetLayout::Builder( HorizontalLayout::Builder(exponentLayoutChildren, 4), VerticalOffsetLayoutNode::Type::Superscript ) }; m_layout = FractionLayout::Builder( - CharLayout('c', KDFont::SmallFont), + CharLayout::Builder('c', KDFont::SmallFont), HorizontalLayout::Builder(layoutChildren, 6) ); } diff --git a/apps/regression/model/power_model.cpp b/apps/regression/model/power_model.cpp index 9825d0afa..4f341c4bf 100644 --- a/apps/regression/model/power_model.cpp +++ b/apps/regression/model/power_model.cpp @@ -13,11 +13,11 @@ namespace Regression { Layout PowerModel::layout() { if (m_layout.isUninitialized()) { const Layout layoutChildren[] = { - CharLayout('a', KDFont::SmallFont), - CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), - CharLayout('X', KDFont::SmallFont), + CharLayout::Builder('a', KDFont::SmallFont), + CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), + CharLayout::Builder('X', KDFont::SmallFont), VerticalOffsetLayout::Builder( - CharLayout('b', KDFont::SmallFont), + CharLayout::Builder('b', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Superscript ), }; diff --git a/apps/regression/model/quadratic_model.cpp b/apps/regression/model/quadratic_model.cpp index 698680ba6..0babfe9d6 100644 --- a/apps/regression/model/quadratic_model.cpp +++ b/apps/regression/model/quadratic_model.cpp @@ -20,19 +20,19 @@ namespace Regression { Layout QuadraticModel::layout() { if (m_layout.isUninitialized()) { const Layout layoutChildren[] = { - CharLayout('a', KDFont::SmallFont), - CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), - CharLayout('X', KDFont::SmallFont), + CharLayout::Builder('a', KDFont::SmallFont), + CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), + CharLayout::Builder('X', KDFont::SmallFont), VerticalOffsetLayout::Builder( - CharLayout('2', KDFont::SmallFont), + CharLayout::Builder('2', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Superscript ), - CharLayout('+', KDFont::SmallFont), - CharLayout('b', KDFont::SmallFont), - CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), - CharLayout('X', KDFont::SmallFont), - CharLayout('+', KDFont::SmallFont), - CharLayout('c', KDFont::SmallFont), + CharLayout::Builder('+', KDFont::SmallFont), + CharLayout::Builder('b', KDFont::SmallFont), + CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), + CharLayout::Builder('X', KDFont::SmallFont), + CharLayout::Builder('+', KDFont::SmallFont), + CharLayout::Builder('c', KDFont::SmallFont), }; m_layout = HorizontalLayout::Builder(layoutChildren, 10); } @@ -48,11 +48,11 @@ Expression QuadraticModel::simplifiedExpression(double * modelCoefficients, Poin Multiplication::Builder( Number::DecimalNumber(a), Power::Builder( - Symbol('x'), - Decimal(2.0))), + Symbol::Builder('x'), + Decimal::Builder(2.0))), Multiplication::Builder( Number::DecimalNumber(b), - Symbol('x')), + Symbol::Builder('x')), Number::DecimalNumber(c) }; Expression result = Addition::Builder(addChildren, 3); diff --git a/apps/regression/model/quartic_model.cpp b/apps/regression/model/quartic_model.cpp index 3c7382fa8..c1dbd87ca 100644 --- a/apps/regression/model/quartic_model.cpp +++ b/apps/regression/model/quartic_model.cpp @@ -20,35 +20,35 @@ namespace Regression { Layout QuarticModel::layout() { if (m_layout.isUninitialized()) { const Layout layoutChildren[] = { - CharLayout('a', KDFont::SmallFont), - CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), - CharLayout('X', KDFont::SmallFont), + CharLayout::Builder('a', KDFont::SmallFont), + CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), + CharLayout::Builder('X', KDFont::SmallFont), VerticalOffsetLayout::Builder( - CharLayout('4', KDFont::SmallFont), + CharLayout::Builder('4', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Superscript ), - CharLayout('+', KDFont::SmallFont), - CharLayout('b', KDFont::SmallFont), - CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), - CharLayout('X', KDFont::SmallFont), + CharLayout::Builder('+', KDFont::SmallFont), + CharLayout::Builder('b', KDFont::SmallFont), + CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), + CharLayout::Builder('X', KDFont::SmallFont), VerticalOffsetLayout::Builder( - CharLayout('3', KDFont::SmallFont), + CharLayout::Builder('3', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Superscript ), - CharLayout('+', KDFont::SmallFont), - CharLayout('c', KDFont::SmallFont), - CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), - CharLayout('X', KDFont::SmallFont), + CharLayout::Builder('+', KDFont::SmallFont), + CharLayout::Builder('c', KDFont::SmallFont), + CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), + CharLayout::Builder('X', KDFont::SmallFont), VerticalOffsetLayout::Builder( - CharLayout('2', KDFont::SmallFont), + CharLayout::Builder('2', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Superscript ), - CharLayout('+', KDFont::SmallFont), - CharLayout('d', KDFont::SmallFont), - CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), - CharLayout('X', KDFont::SmallFont), - CharLayout('+', KDFont::SmallFont), - CharLayout('e', KDFont::SmallFont), + CharLayout::Builder('+', KDFont::SmallFont), + CharLayout::Builder('d', KDFont::SmallFont), + CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), + CharLayout::Builder('X', KDFont::SmallFont), + CharLayout::Builder('+', KDFont::SmallFont), + CharLayout::Builder('e', KDFont::SmallFont), }; m_layout = HorizontalLayout::Builder(layoutChildren, 20); } @@ -66,24 +66,24 @@ Expression QuarticModel::simplifiedExpression(double * modelCoefficients, Poinca Multiplication::Builder( Number::DecimalNumber(a), Power::Builder( - Symbol('x'), - Decimal(4.0))), + Symbol::Builder('x'), + Decimal::Builder(4.0))), // b*x^3 Multiplication::Builder( Number::DecimalNumber(b), Power::Builder( - Symbol('x'), - Decimal(3.0))), + Symbol::Builder('x'), + Decimal::Builder(3.0))), // c*x^2 Multiplication::Builder( Number::DecimalNumber(c), Power::Builder( - Symbol('x'), - Decimal(2.0))), + Symbol::Builder('x'), + Decimal::Builder(2.0))), // d*x Multiplication::Builder( Number::DecimalNumber(d), - Symbol('x')), + Symbol::Builder('x')), // e Number::DecimalNumber(e) }; diff --git a/apps/regression/model/trigonometric_model.cpp b/apps/regression/model/trigonometric_model.cpp index f1151036a..ed919a59e 100644 --- a/apps/regression/model/trigonometric_model.cpp +++ b/apps/regression/model/trigonometric_model.cpp @@ -21,20 +21,20 @@ namespace Regression { Layout TrigonometricModel::layout() { if (m_layout.isUninitialized()) { const Layout layoutChildren[] = { - CharLayout('a', KDFont::SmallFont), - CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), - CharLayout('s', KDFont::SmallFont), - CharLayout('i', KDFont::SmallFont), - CharLayout('n', KDFont::SmallFont), - CharLayout('(', KDFont::SmallFont), - CharLayout('b', KDFont::SmallFont), - CharLayout(Ion::Charset::MiddleDot, KDFont::SmallFont), - CharLayout('X', KDFont::SmallFont), - CharLayout('+', KDFont::SmallFont), - CharLayout('c', KDFont::SmallFont), - CharLayout(')', KDFont::SmallFont), - CharLayout('+', KDFont::SmallFont), - CharLayout('d', KDFont::SmallFont) + CharLayout::Builder('a', KDFont::SmallFont), + CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), + CharLayout::Builder('s', KDFont::SmallFont), + CharLayout::Builder('i', KDFont::SmallFont), + CharLayout::Builder('n', KDFont::SmallFont), + CharLayout::Builder('(', KDFont::SmallFont), + CharLayout::Builder('b', KDFont::SmallFont), + CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), + CharLayout::Builder('X', KDFont::SmallFont), + CharLayout::Builder('+', KDFont::SmallFont), + CharLayout::Builder('c', KDFont::SmallFont), + CharLayout::Builder(')', KDFont::SmallFont), + CharLayout::Builder('+', KDFont::SmallFont), + CharLayout::Builder('d', KDFont::SmallFont) }; m_layout = HorizontalLayout::Builder(layoutChildren, 14); } @@ -55,7 +55,7 @@ Expression TrigonometricModel::simplifiedExpression(double * modelCoefficients, Addition::Builder( Multiplication::Builder( Number::DecimalNumber(b), - Symbol('x')), + Symbol::Builder('x')), Number::DecimalNumber(c)))), Number::DecimalNumber(d)); PoincareHelpers::Simplify(&result, *context); diff --git a/apps/regression/regression_context.cpp b/apps/regression/regression_context.cpp index b7d480743..1550cd2bc 100644 --- a/apps/regression/regression_context.cpp +++ b/apps/regression/regression_context.cpp @@ -22,7 +22,7 @@ const Expression RegressionContext::expressionForSymbol(const SymbolAbstract & s assert(m_seriesPairIndex >= 0); assert(m_seriesPairIndex < m_store->numberOfPairsOfSeries(series)); - return Float(m_store->get(series, storeI, m_seriesPairIndex)); + return Float::Builder(m_store->get(series, storeI, m_seriesPairIndex)); } else { return m_parentContext->expressionForSymbol(symbol, clone); } diff --git a/apps/sequence/cache_context.cpp b/apps/sequence/cache_context.cpp index b16a3d4f3..96fb44608 100644 --- a/apps/sequence/cache_context.cpp +++ b/apps/sequence/cache_context.cpp @@ -22,7 +22,7 @@ const Expression CacheContext::expressionForSymbol(const SymbolAbstract & sym && (strcmp(symbol.name()+1, "(n)") == 0 || strcmp(symbol.name()+1, "(n+1)") == 0)) { Symbol s = const_cast(static_cast(symbol)); - return Float(m_values[nameIndexForSymbol(s)][rankIndexForSymbol(s)]); + return Float::Builder(m_values[nameIndexForSymbol(s)][rankIndexForSymbol(s)]); } return VariableContext::expressionForSymbol(symbol, clone); } diff --git a/apps/sequence/graph/term_sum_controller.cpp b/apps/sequence/graph/term_sum_controller.cpp index 033a0ce65..35fcfb49f 100644 --- a/apps/sequence/graph/term_sum_controller.cpp +++ b/apps/sequence/graph/term_sum_controller.cpp @@ -51,9 +51,9 @@ double TermSumController::cursorNextStep(double x, int direction) { Layout TermSumController::createFunctionLayout(const char * functionName) { return HorizontalLayout::Builder( - CharLayout(functionName[0], KDFont::SmallFont), + CharLayout::Builder(functionName[0], KDFont::SmallFont), VerticalOffsetLayout::Builder( - CharLayout('n', KDFont::SmallFont), + CharLayout::Builder('n', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Subscript ) ); diff --git a/apps/sequence/list/sequence_toolbox.cpp b/apps/sequence/list/sequence_toolbox.cpp index ab0468c5c..5dbcd3380 100644 --- a/apps/sequence/list/sequence_toolbox.cpp +++ b/apps/sequence/list/sequence_toolbox.cpp @@ -77,18 +77,18 @@ void SequenceToolbox::buildExtraCellsLayouts(const char * sequenceName, int recu for (int j = 0; j < recurrenceDepth; j++) { const char * indice = j == 0 ? "n" : "n+1"; m_addedCellLayout[j] = HorizontalLayout::Builder( - CharLayout(sequenceName[0], KDFont::LargeFont), + CharLayout::Builder(sequenceName[0], KDFont::LargeFont), VerticalOffsetLayout::Builder(LayoutHelper::String(indice, strlen(indice), KDFont::LargeFont), VerticalOffsetLayoutNode::Type::Subscript) ); m_addedCellLayout[j+recurrenceDepth] = HorizontalLayout::Builder( - CharLayout(otherSequenceName[0], KDFont::LargeFont), + CharLayout::Builder(otherSequenceName[0], KDFont::LargeFont), VerticalOffsetLayout::Builder(LayoutHelper::String(indice, strlen(indice), KDFont::LargeFont), VerticalOffsetLayoutNode::Type::Subscript) ); } if (recurrenceDepth < 2) { const char * indice = recurrenceDepth == 0 ? "n" : (recurrenceDepth == 1 ? "n+1" : "n+2"); m_addedCellLayout[2*recurrenceDepth] = HorizontalLayout::Builder( - CharLayout(otherSequenceName[0], KDFont::LargeFont), + CharLayout::Builder(otherSequenceName[0], KDFont::LargeFont), VerticalOffsetLayout::Builder(LayoutHelper::String(indice, strlen(indice), KDFont::LargeFont), VerticalOffsetLayoutNode::Type::Subscript) ); } diff --git a/apps/sequence/list/type_parameter_controller.cpp b/apps/sequence/list/type_parameter_controller.cpp index 80ae5ec85..71bace67e 100644 --- a/apps/sequence/list/type_parameter_controller.cpp +++ b/apps/sequence/list/type_parameter_controller.cpp @@ -116,7 +116,7 @@ void TypeParameterController::willDisplayCellAtLocation(HighlightCell * cell, in } const char * subscripts[3] = {"n", "n+1", "n+2"}; m_layouts[j] = HorizontalLayout::Builder( - CharLayout(nextName[0], font), + CharLayout::Builder(nextName[0], font), VerticalOffsetLayout::Builder(LayoutHelper::String(subscripts[j], strlen(subscripts[j]), font), VerticalOffsetLayoutNode::Type::Subscript) ); ExpressionTableCellWithPointer * myCell = (ExpressionTableCellWithPointer *)cell; diff --git a/apps/sequence/sequence.cpp b/apps/sequence/sequence.cpp index ff7555ee2..d413343b0 100644 --- a/apps/sequence/sequence.cpp +++ b/apps/sequence/sequence.cpp @@ -147,8 +147,8 @@ int Sequence::numberOfElements() { Poincare::Layout Sequence::nameLayout() { if (m_nameLayout.isUninitialized()) { m_nameLayout = HorizontalLayout::Builder( - CharLayout(name()[0], KDFont::SmallFont), - VerticalOffsetLayout::Builder(CharLayout('n', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Subscript) + CharLayout::Builder(name()[0], KDFont::SmallFont), + VerticalOffsetLayout::Builder(CharLayout::Builder('n', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Subscript) ); } return m_nameLayout; @@ -158,16 +158,16 @@ Poincare::Layout Sequence::definitionName() { if (m_definitionName.isUninitialized()) { if (m_type == Type::Explicit) { m_definitionName = HorizontalLayout::Builder( - CharLayout(name()[0], k_layoutFont), + CharLayout::Builder(name()[0], k_layoutFont), VerticalOffsetLayout::Builder(LayoutHelper::String("n", 1, k_layoutFont), VerticalOffsetLayoutNode::Type::Subscript)); } else if (m_type == Type::SingleRecurrence) { m_definitionName = HorizontalLayout::Builder( - CharLayout(name()[0], k_layoutFont), + CharLayout::Builder(name()[0], k_layoutFont), VerticalOffsetLayout::Builder(LayoutHelper::String("n+1", 3, k_layoutFont), VerticalOffsetLayoutNode::Type::Subscript)); } else { assert(m_type == Type::DoubleRecurrence); m_definitionName = HorizontalLayout::Builder( - CharLayout(name()[0], k_layoutFont), + CharLayout::Builder(name()[0], k_layoutFont), VerticalOffsetLayout::Builder(LayoutHelper::String("n+2", 3, k_layoutFont), VerticalOffsetLayoutNode::Type::Subscript)); } } @@ -183,7 +183,7 @@ Poincare::Layout Sequence::firstInitialConditionName() { { Layout indexLayout = LayoutHelper::String(buffer, strlen(buffer), k_layoutFont); m_firstInitialConditionName = HorizontalLayout::Builder( - CharLayout(name()[0], k_layoutFont), + CharLayout::Builder(name()[0], k_layoutFont), VerticalOffsetLayout::Builder(indexLayout, VerticalOffsetLayoutNode::Type::Subscript)); } return m_firstInitialConditionName; @@ -196,7 +196,7 @@ Poincare::Layout Sequence::secondInitialConditionName() { if (m_type == Type::DoubleRecurrence) { Layout indexLayout = LayoutHelper::String(buffer, strlen(buffer), k_layoutFont); m_secondInitialConditionName = HorizontalLayout::Builder( - CharLayout(name()[0], k_layoutFont), + CharLayout::Builder(name()[0], k_layoutFont), VerticalOffsetLayout::Builder(indexLayout, VerticalOffsetLayoutNode::Type::Subscript)); } } @@ -247,10 +247,10 @@ T Sequence::approximateToNextRank(int n, SequenceContext * sqctx) const { T vn = sqctx->valueOfSequenceAtPreviousRank(1, 0); T vnm1 = sqctx->valueOfSequenceAtPreviousRank(1, 1); T vnm2 = sqctx->valueOfSequenceAtPreviousRank(1, 2); - Poincare::Symbol vnSymbol("v(n)", 4); - Poincare::Symbol vn1Symbol("v(n+1)", 6); - Poincare::Symbol unSymbol("u(n)", 4); - Poincare::Symbol un1Symbol("u(n+1)", 6); + Poincare::Symbol vnSymbol = Symbol::Builder("v(n)", 4); + Poincare::Symbol vn1Symbol = Symbol::Builder("v(n+1)", 6); + Poincare::Symbol unSymbol = Symbol::Builder("u(n)", 4); + Poincare::Symbol un1Symbol = Symbol::Builder("u(n+1)", 6); switch (m_type) { case Type::Explicit: { diff --git a/apps/settings/sub_menu/preferences_controller.cpp b/apps/settings/sub_menu/preferences_controller.cpp index ccc052317..bb96f02cf 100644 --- a/apps/settings/sub_menu/preferences_controller.cpp +++ b/apps/settings/sub_menu/preferences_controller.cpp @@ -84,7 +84,7 @@ Layout layoutForPreferences(I18n::Message message) { // Complex format case I18n::Message::Real: { - return CharLayout('x', KDFont::SmallFont); + return CharLayout::Builder('x', KDFont::SmallFont); } case I18n::Message::Cartesian: { diff --git a/apps/shared/global_context.cpp b/apps/shared/global_context.cpp index 83e4da400..336945f11 100644 --- a/apps/shared/global_context.cpp +++ b/apps/shared/global_context.cpp @@ -71,7 +71,7 @@ void GlobalContext::setExpressionForSymbol(const Expression & expression, const Ion::Storage::Record record = SymbolAbstractRecordWithBaseName(symbol.name()); Expression e = ExpressionFromRecord(record); if (e.isUninitialized()) { - e = Undefined(); + e = Undefined::Builder(); } Expression finalExpression = expression.clone().replaceSymbolWithExpression(symbol, e); diff --git a/apps/shared/storage_cartesian_function.cpp b/apps/shared/storage_cartesian_function.cpp index ff46ec7cb..d07eb935d 100644 --- a/apps/shared/storage_cartesian_function.cpp +++ b/apps/shared/storage_cartesian_function.cpp @@ -85,7 +85,7 @@ void StorageCartesianFunction::setDisplayDerivative(bool display) { } double StorageCartesianFunction::approximateDerivative(double x, Poincare::Context * context) const { - Poincare::Derivative derivative = Poincare::Derivative::Builder(expressionReduced(context).clone(), Symbol(Symbol::SpecialSymbols::UnknownX), Poincare::Float(x)); // derivative takes ownership of Poincare::Float(x) and the clone of expression + Poincare::Derivative derivative = Poincare::Derivative::Builder(expressionReduced(context).clone(), Symbol::Builder(Symbol::SpecialSymbols::UnknownX), Poincare::Float::Builder(x)); // derivative takes ownership of Poincare::Float::Builder(x) and the clone of expression /* TODO: when we approximate derivative, we might want to simplify the * derivative here. However, we might want to do it once for all x (to avoid * lagging in the derivative table. */ @@ -94,7 +94,7 @@ double StorageCartesianFunction::approximateDerivative(double x, Poincare::Conte double StorageCartesianFunction::sumBetweenBounds(double start, double end, Poincare::Context * context) const { // TODO: this does not work yet because integral does not understand UnknownX - Poincare::Integral integral = Poincare::Integral::Builder(expressionReduced(context).clone(), Symbol(Symbol::SpecialSymbols::UnknownX), Poincare::Float(start), Poincare::Float(end)); // Integral takes ownership of args + Poincare::Integral integral = Poincare::Integral::Builder(expressionReduced(context).clone(), Symbol::Builder(Symbol::SpecialSymbols::UnknownX), Poincare::Float::Builder(start), Poincare::Float::Builder(end)); // Integral takes ownership of args /* TODO: when we approximate integral, we might want to simplify the integral * here. However, we might want to do it once for all x (to avoid lagging in * the derivative table. */ diff --git a/apps/shared/storage_expression_model.cpp b/apps/shared/storage_expression_model.cpp index 1a6aabf17..bfb274c7b 100644 --- a/apps/shared/storage_expression_model.cpp +++ b/apps/shared/storage_expression_model.cpp @@ -87,7 +87,7 @@ Ion::Storage::Record::ErrorStatus StorageExpressionModel::setContent(const char // Compute the expression to store, without replacing symbols expressionToStore = Expression::Parse(c); if (!expressionToStore.isUninitialized()) { - expressionToStore = expressionToStore.replaceUnknown(Symbol('x')); //TODO Beware of non x unknowns! (for instance whe sequences are in the storage) + expressionToStore = expressionToStore.replaceUnknown(Symbol::Builder('x')); //TODO Beware of non x unknowns! (for instance whe sequences are in the storage) } } return setExpressionContent(expressionToStore); diff --git a/apps/shared/storage_sum_graph_controller.cpp b/apps/shared/storage_sum_graph_controller.cpp index 0e950cebb..bc164fb5a 100644 --- a/apps/shared/storage_sum_graph_controller.cpp +++ b/apps/shared/storage_sum_graph_controller.cpp @@ -243,7 +243,7 @@ void StorageSumGraphController::LegendView::setSumSymbol(Step step, double start m_sumLayout = CondensedSumLayout::Builder( LayoutHelper::String(sigma, sizeof(sigma)), LayoutHelper::String(buffer, strlen(buffer), k_font), - EmptyLayout(EmptyLayoutNode::Color::Yellow, false, k_font, false)); + EmptyLayout::Builder(EmptyLayoutNode::Color::Yellow, false, k_font, false)); } else { m_sumLayout = LayoutHelper::String(sigma, sizeof(sigma)); char buffer[2+PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; diff --git a/apps/shared/sum_graph_controller.cpp b/apps/shared/sum_graph_controller.cpp index 384279450..ee03dbc2b 100644 --- a/apps/shared/sum_graph_controller.cpp +++ b/apps/shared/sum_graph_controller.cpp @@ -242,7 +242,7 @@ void SumGraphController::LegendView::setSumSymbol(Step step, double start, doubl m_sumLayout = CondensedSumLayout::Builder( LayoutHelper::String(sigma, sizeof(sigma)), LayoutHelper::String(buffer, strlen(buffer), KDFont::SmallFont), - EmptyLayout(EmptyLayoutNode::Color::Yellow, false, KDFont::SmallFont, false)); + EmptyLayout::Builder(EmptyLayoutNode::Color::Yellow, false, KDFont::SmallFont, false)); } else { m_sumLayout = LayoutHelper::String(sigma, sizeof(sigma)); constexpr size_t bufferSize = 2+PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits); diff --git a/apps/solver/equation.cpp b/apps/solver/equation.cpp index faabddbf3..15c9e1578 100644 --- a/apps/solver/equation.cpp +++ b/apps/solver/equation.cpp @@ -30,11 +30,11 @@ Expression Equation::standardForm(Context * context) const { if (m_standardForm.isUninitialized()) { const Expression e = expression(context); if (e.type() == ExpressionNode::Type::Unreal) { - m_standardForm = Unreal(); + m_standardForm = Unreal::Builder(); return m_standardForm; } if (e.recursivelyMatches([](const Expression e, Context & context, bool replaceSymbols) { return e.type() == ExpressionNode::Type::Undefined || e.type() == ExpressionNode::Type::Infinity || Expression::IsMatrix(e, context, replaceSymbols); }, *context, true)) { - m_standardForm = Undefined(); + m_standardForm = Undefined::Builder(); return m_standardForm; } if (e.type() == ExpressionNode::Type::Equal) { @@ -43,7 +43,7 @@ Expression Equation::standardForm(Context * context) const { } else { assert(e.type() == ExpressionNode::Type::Rational && static_cast(e).isOne()); // The equality was reduced which means the equality was always true. - m_standardForm = Rational(0); + m_standardForm = Rational::Builder(0); } } return m_standardForm; diff --git a/apps/solver/equation_store.cpp b/apps/solver/equation_store.cpp index 8f9e841af..b81de3552 100644 --- a/apps/solver/equation_store.cpp +++ b/apps/solver/equation_store.cpp @@ -257,20 +257,20 @@ EquationStore::Error EquationStore::oneDimensialPolynomialSolve(Expression exact /* Equation ax^2+bx+c = 0 */ assert(degree == 2); // Compute delta = b*b-4ac - Expression delta = Subtraction::Builder(Power::Builder(coefficients[1].clone(), Rational(2)), Multiplication::Builder(Rational(4), coefficients[0].clone(), coefficients[2].clone())); + Expression delta = Subtraction::Builder(Power::Builder(coefficients[1].clone(), Rational::Builder(2)), Multiplication::Builder(Rational::Builder(4), coefficients[0].clone(), coefficients[2].clone())); delta = delta.simplify(*context, updatedComplexFormat(), Poincare::Preferences::sharedPreferences()->angleUnit()); if (delta.isUninitialized()) { - delta = Poincare::Undefined(); + delta = Poincare::Undefined::Builder(); } if (delta.isRationalZero()) { // if delta = 0, x0=x1= -b/(2a) - exactSolutions[0] = Division::Builder(Opposite::Builder(coefficients[1]), Multiplication::Builder(Rational(2), coefficients[2])); + exactSolutions[0] = Division::Builder(Opposite::Builder(coefficients[1]), Multiplication::Builder(Rational::Builder(2), coefficients[2])); m_numberOfSolutions = 2; } else { // x0 = (-b-sqrt(delta))/(2a) - exactSolutions[0] = Division::Builder(Subtraction::Builder(Opposite::Builder(coefficients[1].clone()), SquareRoot::Builder(delta.clone())), Multiplication::Builder(Rational(2), coefficients[2].clone())); + exactSolutions[0] = Division::Builder(Subtraction::Builder(Opposite::Builder(coefficients[1].clone()), SquareRoot::Builder(delta.clone())), Multiplication::Builder(Rational::Builder(2), coefficients[2].clone())); // x1 = (-b+sqrt(delta))/(2a) - exactSolutions[1] = Division::Builder(Addition::Builder(Opposite::Builder(coefficients[1]), SquareRoot::Builder(delta.clone())), Multiplication::Builder(Rational(2), coefficients[2])); + exactSolutions[1] = Division::Builder(Addition::Builder(Opposite::Builder(coefficients[1]), SquareRoot::Builder(delta.clone())), Multiplication::Builder(Rational::Builder(2), coefficients[2])); m_numberOfSolutions = 3; } exactSolutions[m_numberOfSolutions-1] = delta; @@ -285,47 +285,47 @@ EquationStore::Error EquationStore::oneDimensialPolynomialSolve(Expression exact Expression * c = coefficients[1]; Expression * d = coefficients[0]; // Delta = b^2*c^2+18abcd-27a^2*d^2-4ac^3-4db^3 - Expression * mult0Operands[2] = {new Power::Builder(b->clone(), new Rational(2), false), new Power::Builder(c->clone(), new Rational(2), false)}; - Expression * mult1Operands[5] = {new Rational(18), a->clone(), b->clone(), c->clone(), d->clone()}; - Expression * mult2Operands[3] = {new Rational(-27), new Power::Builder(a->clone(), new Rational(2), false), new Power::Builder(d->clone(), new Rational(2), false)}; - Expression * mult3Operands[3] = {new Rational(-4), a->clone(), new Power::Builder(c->clone(), new Rational(3), false)}; - Expression * mult4Operands[3] = {new Rational(-4), d->clone(), new Power::Builder(b->clone(), new Rational(3), false)}; + Expression * mult0Operands[2] = {new Power::Builder(b->clone(), new Rational::Builder(2), false), new Power::Builder(c->clone(), new Rational::Builder(2), false)}; + Expression * mult1Operands[5] = {new Rational::Builder(18), a->clone(), b->clone(), c->clone(), d->clone()}; + Expression * mult2Operands[3] = {new Rational::Builder(-27), new Power::Builder(a->clone(), new Rational::Builder(2), false), new Power::Builder(d->clone(), new Rational::Builder(2), false)}; + Expression * mult3Operands[3] = {new Rational::Builder(-4), a->clone(), new Power::Builder(c->clone(), new Rational::Builder(3), false)}; + Expression * mult4Operands[3] = {new Rational::Builder(-4), d->clone(), new Power::Builder(b->clone(), new Rational::Builder(3), false)}; Expression * add0Operands[5] = {new Multiplication::Builder(mult0Operands, 2, false), new Multiplication::Builder(mult1Operands, 5, false), new Multiplication::Builder(mult2Operands, 3, false), new Multiplication::Builder(mult3Operands, 3, false), new Multiplication::Builder(mult4Operands, 3, false)}; Expression * delta = new Addition(add0Operands, 5, false); PoincareHelpers::Simplify(&delta, *context); // Delta0 = b^2-3ac - Expression * mult5Operands[3] = {new Rational(3), a->clone(), c->clone()}; - Expression * delta0 = new Subtraction::Builder(new Power::Builder(b->clone(), new Rational(2), false), new Multiplication::Builder(mult5Operands, 3, false), false); + Expression * mult5Operands[3] = {new Rational::Builder(3), a->clone(), c->clone()}; + Expression * delta0 = new Subtraction::Builder(new Power::Builder(b->clone(), new Rational::Builder(2), false), new Multiplication::Builder(mult5Operands, 3, false), false); Reduce(&delta0, *context); if (delta->isRationalZero()) { if (delta0->isRationalZero()) { // delta0 = 0 && delta = 0 --> x0 = -b/(3a) delete delta0; - m_exactSolutions[0] = new Opposite::Builder(new Division::Builder(b, new Multiplication::Builder(new Rational(3), a, false), false), false); + m_exactSolutions[0] = new Opposite::Builder(new Division::Builder(b, new Multiplication::Builder(new Rational::Builder(3), a, false), false), false); m_numberOfSolutions = 1; delete c; delete d; } else { // delta = 0 --> x0 = (9ad-bc)/(2delta0) // --> x1 = (4abc-9a^2d-b^3)/(a*delta0) - Expression * mult6Operands[3] = {new Rational(9), a, d}; - m_exactSolutions[0] = new Division::Builder(new Subtraction::Builder(new Multiplication::Builder(mult6Operands, 3, false), new Multiplication::Builder(b, c, false), false), new Multiplication::Builder(new Rational(2), delta0, false), false); - Expression * mult7Operands[4] = {new Rational(4), a->clone(), b->clone(), c->clone()}; - Expression * mult8Operands[3] = {new Rational(-9), new Power::Builder(a->clone(), new Rational(2), false), d->clone()}; - Expression * add1Operands[3] = {new Multiplication::Builder(mult7Operands, 4, false), new Multiplication::Builder(mult8Operands,3, false), new Opposite::Builder(new Power::Builder(b->clone(), new Rational(3), false), false)}; + Expression * mult6Operands[3] = {new Rational::Builder(9), a, d}; + m_exactSolutions[0] = new Division::Builder(new Subtraction::Builder(new Multiplication::Builder(mult6Operands, 3, false), new Multiplication::Builder(b, c, false), false), new Multiplication::Builder(new Rational::Builder(2), delta0, false), false); + Expression * mult7Operands[4] = {new Rational::Builder(4), a->clone(), b->clone(), c->clone()}; + Expression * mult8Operands[3] = {new Rational::Builder(-9), new Power::Builder(a->clone(), new Rational::Builder(2), false), d->clone()}; + Expression * add1Operands[3] = {new Multiplication::Builder(mult7Operands, 4, false), new Multiplication::Builder(mult8Operands,3, false), new Opposite::Builder(new Power::Builder(b->clone(), new Rational::Builder(3), false), false)}; m_exactSolutions[1] = new Division::Builder(new Addition(add1Operands, 3, false), new Multiplication::Builder(a->clone(), delta0, false), false); m_numberOfSolutions = 2; } } else { // delta1 = 2b^3-9abc+27a^2*d - Expression * mult9Operands[4] = {new Rational(-9), a, b, c}; - Expression * mult10Operands[3] = {new Rational(27), new Power::Builder(a->clone(), new Rational(2), false), d}; - Expression * add2Operands[3] = {new Multiplication::Builder(new Rational(2), new Power::Builder(b->clone(), new Rational(3), false), false), new Multiplication::Builder(mult9Operands, 4, false), new Multiplication::Builder(mult10Operands, 3, false)}; + Expression * mult9Operands[4] = {new Rational::Builder(-9), a, b, c}; + Expression * mult10Operands[3] = {new Rational::Builder(27), new Power::Builder(a->clone(), new Rational::Builder(2), false), d}; + Expression * add2Operands[3] = {new Multiplication::Builder(new Rational::Builder(2), new Power::Builder(b->clone(), new Rational::Builder(3), false), false), new Multiplication::Builder(mult9Operands, 4, false), new Multiplication::Builder(mult10Operands, 3, false)}; Expression * delta1 = new Addition(add2Operands, 3, false); // C = Root((delta1+sqrt(-27a^2*delta))/2, 3) - Expression * mult11Operands[3] = {new Rational(-27), new Power::Builder(a->clone(), new Rational(2), false), (*delta)->clone()}; - Expression * c = new Power::Builder(new Division::Builder(new Addition(delta1, new SquareRoot(new Multiplication::Builder(mult11Operands, 3, false), false), false), new Rational(2), false), new Rational(1,3), false); - Expression * unary3roots[2] = {new Addition(new Rational(-1,2), new Division::Builder(new Multiplication::Builder(new SquareRoot(new Rational(3), false), new Constant(Ion::Charset::IComplex), false), new Rational(2), false), false), new Subtraction::Builder(new Rational(-1,2), new Division::Builder(new Multiplication::Builder(new SquareRoot(new Rational(3), false), new Constant(Ion::Charset::IComplex), false), new Rational(2), false), false)}; + Expression * mult11Operands[3] = {new Rational::Builder(-27), new Power::Builder(a->clone(), new Rational::Builder(2), false), (*delta)->clone()}; + Expression * c = new Power::Builder(new Division::Builder(new Addition(delta1, new SquareRoot(new Multiplication::Builder(mult11Operands, 3, false), false), false), new Rational::Builder(2), false), new Rational::Builder(1,3), false); + Expression * unary3roots[2] = {new Addition(new Rational::Builder(-1,2), new Division::Builder(new Multiplication::Builder(new SquareRoot(new Rational::Builder(3), false), new Constant::Builder(Ion::Charset::IComplex), false), new Rational::Builder(2), false), false), new Subtraction::Builder(new Rational::Builder(-1,2), new Division::Builder(new Multiplication::Builder(new SquareRoot(new Rational::Builder(3), false), new Constant::Builder(Ion::Charset::IComplex), false), new Rational::Builder(2), false), false)}; // x_k = -1/(3a)*(b+C*z+delta0/(zC)) with z = unary cube root for (int k = 0; k < 3; k++) { Expression * ccopy = c; @@ -335,7 +335,7 @@ EquationStore::Error EquationStore::oneDimensialPolynomialSolve(Expression exact delta0copy = delta0->clone(); } Expression * add3Operands[3] = {b->clone(), ccopy, new Division::Builder(delta0copy, ccopy->clone(), false)}; - m_exactSolutions[k] = new Multiplication::Builder(new Division::Builder(new Rational(-1), new Multiplication::Builder(new Rational(3), a->clone(), false), false), new Addition(add3Operands, 3, false), false); + m_exactSolutions[k] = new Multiplication::Builder(new Division::Builder(new Rational::Builder(-1), new Multiplication::Builder(new Rational::Builder(3), a->clone(), false), false), new Addition(add3Operands, 3, false), false); } m_numberOfSolutions = 3; } diff --git a/apps/solver/solutions_controller.cpp b/apps/solver/solutions_controller.cpp index 5783f4287..f9b97405b 100644 --- a/apps/solver/solutions_controller.cpp +++ b/apps/solver/solutions_controller.cpp @@ -75,7 +75,7 @@ SolutionsController::SolutionsController(Responder * parentResponder, EquationSt m_delta2Layout(), m_contentView(this) { - m_delta2Layout = HorizontalLayout::Builder(VerticalOffsetLayout::Builder(CharLayout('2', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Superscript), LayoutHelper::String("-4ac", 4, KDFont::SmallFont)); + m_delta2Layout = HorizontalLayout::Builder(VerticalOffsetLayout::Builder(CharLayout::Builder('2', KDFont::SmallFont), VerticalOffsetLayoutNode::Type::Superscript), LayoutHelper::String("-4ac", 4, KDFont::SmallFont)); char deltaB[] = {Ion::Charset::CapitalDelta, '=', 'b'}; static_cast(m_delta2Layout).addOrMergeChildAtIndex(LayoutHelper::String(deltaB, 3, KDFont::SmallFont), 0, false); for (int i = 0; i < EquationStore::k_maxNumberOfExactSolutions; i++) { diff --git a/apps/statistics/statistics_context.cpp b/apps/statistics/statistics_context.cpp index 1f5260ee9..23830d431 100644 --- a/apps/statistics/statistics_context.cpp +++ b/apps/statistics/statistics_context.cpp @@ -22,7 +22,7 @@ const Expression StatisticsContext::expressionForSymbol(const SymbolAbstract & s assert(m_seriesPairIndex >= 0); assert(m_seriesPairIndex < m_store->numberOfPairsOfSeries(series)); - return Float(m_store->get(series, storeI, m_seriesPairIndex)); + return Float::Builder(m_store->get(series, storeI, m_seriesPairIndex)); } else { return m_parentContext->expressionForSymbol(symbol, clone); } diff --git a/poincare/Makefile b/poincare/Makefile index 891a50338..7fbd144c1 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -3,6 +3,7 @@ SFLAGS += -Ipoincare/include #include poincare/src/simplify/Makefile #include poincare/src/simplification/Makefile objs += $(addprefix poincare/src/,\ + absolute_value_layout.o\ binomial_coefficient_layout.o\ bracket_layout.o\ bracket_pair_layout.o\ @@ -11,6 +12,7 @@ objs += $(addprefix poincare/src/,\ condensed_sum_layout.o\ conjugate_layout.o\ empty_layout.o\ + floor_layout.o\ fraction_layout.o\ grid_layout.o\ horizontal_layout.o\ diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 5a2b9ed98..d0eec68d2 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -28,7 +28,7 @@ public: // Approximation template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { - return Complex(std::abs(c)); + return Complex::Builder(std::abs(c)); } Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); @@ -49,15 +49,12 @@ class AbsoluteValue final : public Expression { friend class AbsoluteValueNode; public: AbsoluteValue(const AbsoluteValueNode * n) : Expression(n) {} - static AbsoluteValue Builder(Expression child) { return AbsoluteValue(child); } + static AbsoluteValue Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("abs", 1, &UntypedBuilder); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: - explicit AbsoluteValue(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); }; diff --git a/poincare/include/poincare/absolute_value_layout.h b/poincare/include/poincare/absolute_value_layout.h index a0dfde873..42510c6b0 100644 --- a/poincare/include/poincare/absolute_value_layout.h +++ b/poincare/include/poincare/absolute_value_layout.h @@ -33,13 +33,8 @@ private: class AbsoluteValueLayout final : public Layout { public: - static AbsoluteValueLayout Builder(Layout l) { return AbsoluteValueLayout(l); } -private: - explicit AbsoluteValueLayout(Layout l) : - Layout(TreePool::sharedPool()->createTreeNode()) - { - replaceChildAtIndexInPlace(0, l); - } + static AbsoluteValueLayout Builder(Layout l); + AbsoluteValueLayout() = delete; }; } diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 6c4348130..07d482e46 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -29,7 +29,7 @@ public: int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const override; // Evaluation - template static Complex compute(const std::complex c, const std::complex d, Preferences::ComplexFormat complexFormat) { return Complex(c+d); } + template static Complex compute(const std::complex c, const std::complex d, Preferences::ComplexFormat complexFormat) { return Complex::Builder(c+d); } template static MatrixComplex computeOnMatrices(const MatrixComplex m, const MatrixComplex n, Preferences::ComplexFormat complexFormat) { return ApproximationHelper::ElementWiseOnComplexMatrices(m, n, complexFormat, compute); } @@ -61,23 +61,15 @@ private: class Addition final : public NAryExpression { public: Addition(const AdditionNode * n) : NAryExpression(n) {} - static Addition Builder() { return Addition(); } + static Addition Builder(); static Addition Builder(Expression e1) { return Addition::Builder(&e1, 1); } static Addition Builder(Expression e1, Expression e2) { return Addition::Builder(ArrayBuilder(e1, e2).array(), 2); } - static Addition Builder(Expression * children, size_t numberOfChildren) { - Addition a = Addition::Builder(); - for (size_t i = 0; i < numberOfChildren; i++) { - a.addChildAtIndexInPlace(children[i], i, i); - } - return a; - } + static Addition Builder(Expression * children, size_t numberOfChildren); // Expression Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const; private: - Addition() : NAryExpression(TreePool::sharedPool()->createTreeNode()) {} - static const Number NumeralFactor(const Expression & e); static inline int NumberOfNonNumeralFactors(const Expression & e); static inline const Expression FirstNonNumeralFactor(const Expression & e); diff --git a/poincare/include/poincare/arc_cosine.h b/poincare/include/poincare/arc_cosine.h index 421bf8a9f..e15d9a685 100644 --- a/poincare/include/poincare/arc_cosine.h +++ b/poincare/include/poincare/arc_cosine.h @@ -41,15 +41,11 @@ private: class ArcCosine final : public Expression { public: ArcCosine(const ArcCosineNode * n) : Expression(n) {} - static ArcCosine Builder(Expression child) { return ArcCosine(child); } + static ArcCosine Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("acos", 1, &UntypedBuilder); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); -private: - explicit ArcCosine(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; diff --git a/poincare/include/poincare/arc_sine.h b/poincare/include/poincare/arc_sine.h index dd5f030cd..230e39475 100644 --- a/poincare/include/poincare/arc_sine.h +++ b/poincare/include/poincare/arc_sine.h @@ -40,15 +40,11 @@ private: class ArcSine final : public Expression { public: ArcSine(const ArcSineNode * n) : Expression(n) {} - static ArcSine Builder(Expression child) { return ArcSine(child); } + static ArcSine Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("asin", 1, &UntypedBuilder); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); -private: - explicit ArcSine(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/arc_tangent.h b/poincare/include/poincare/arc_tangent.h index 8569eed36..5262fc692 100644 --- a/poincare/include/poincare/arc_tangent.h +++ b/poincare/include/poincare/arc_tangent.h @@ -44,15 +44,11 @@ private: class ArcTangent final : public Expression { public: ArcTangent(const ArcTangentNode * n) : Expression(n) {} - static ArcTangent Builder(Expression child) { return ArcTangent(child); } + static ArcTangent Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("atan", 1, &UntypedBuilder); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); -private: - explicit ArcTangent(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/binomial_coefficient.h b/poincare/include/poincare/binomial_coefficient.h index 1edf2b6ba..f6102a879 100644 --- a/poincare/include/poincare/binomial_coefficient.h +++ b/poincare/include/poincare/binomial_coefficient.h @@ -39,17 +39,13 @@ private: class BinomialCoefficient final : public Expression { public: BinomialCoefficient(const BinomialCoefficientNode * n) : Expression(n) {} - static BinomialCoefficient Builder(Expression child0, Expression child1) { return BinomialCoefficient(child0, child1); } + static BinomialCoefficient Builder(Expression child0, Expression child1); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("binomial", 2, &UntypedBuilder); // Expression Expression shallowReduce(); private: - BinomialCoefficient(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child0); - replaceChildAtIndexInPlace(1, child1); - } constexpr static int k_maxNValue = 300; }; diff --git a/poincare/include/poincare/binomial_coefficient_layout.h b/poincare/include/poincare/binomial_coefficient_layout.h index 756f8862e..b094b5b53 100644 --- a/poincare/include/poincare/binomial_coefficient_layout.h +++ b/poincare/include/poincare/binomial_coefficient_layout.h @@ -43,15 +43,8 @@ private: class BinomialCoefficientLayout final : public Layout { public: - static BinomialCoefficientLayout Builder(Layout n, Layout k) { return BinomialCoefficientLayout(n, k); } - -private: - BinomialCoefficientLayout(Layout n, Layout k) : - Layout(TreePool::sharedPool()->createTreeNode()) - { - replaceChildAtIndexInPlace(0, n); - replaceChildAtIndexInPlace(1, k); - } + static BinomialCoefficientLayout Builder(Layout n, Layout k); + BinomialCoefficientLayout() = delete; }; } diff --git a/poincare/include/poincare/ceiling.h b/poincare/include/poincare/ceiling.h index a7880853b..0a202947c 100644 --- a/poincare/include/poincare/ceiling.h +++ b/poincare/include/poincare/ceiling.h @@ -42,15 +42,11 @@ private: class Ceiling final : public Expression { public: Ceiling(const CeilingNode * n) : Expression(n) {} - static Ceiling Builder(Expression child) { return Ceiling(child); } + static Ceiling Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("ceil", 1, &UntypedBuilder); Expression shallowReduce(); -private: - explicit Ceiling(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/ceiling_layout.h b/poincare/include/poincare/ceiling_layout.h index 72ce65484..8b06304e7 100644 --- a/poincare/include/poincare/ceiling_layout.h +++ b/poincare/include/poincare/ceiling_layout.h @@ -30,11 +30,8 @@ protected: class CeilingLayout final : public Layout { public: - static CeilingLayout Builder(Layout l) { return CeilingLayout(l); } -private: - explicit CeilingLayout(Layout l) : Layout(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, l); - } + static CeilingLayout Builder(Layout l); + CeilingLayout() = delete; }; } diff --git a/poincare/include/poincare/char_layout.h b/poincare/include/poincare/char_layout.h index aa183db36..c206d39b8 100644 --- a/poincare/include/poincare/char_layout.h +++ b/poincare/include/poincare/char_layout.h @@ -17,10 +17,8 @@ public: {} // CharLayout - virtual void setChar(char c) { m_char = c; } char character() const { return m_char; } const KDFont * font() const { return m_font; } - void setFont(const KDFont * font) { m_font = font; } // LayoutNode void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; @@ -62,7 +60,7 @@ private: class CharLayout final : public Layout { public: CharLayout(const CharLayoutNode * n) : Layout(n) {} - CharLayout(char c, const KDFont * font = KDFont::LargeFont); + static CharLayout Builder(char c, const KDFont * font = KDFont::LargeFont); const KDFont * font() const { return const_cast(this)->node()->font(); } char character() const {return const_cast(this)->node()->character();} private: diff --git a/poincare/include/poincare/complex.h b/poincare/include/poincare/complex.h index 9d443ea65..1f9e82652 100644 --- a/poincare/include/poincare/complex.h +++ b/poincare/include/poincare/complex.h @@ -9,9 +9,9 @@ template class Complex; template -class ComplexNode final : public std::complex, public EvaluationNode { +class ComplexNode final : public EvaluationNode, public std::complex { public: - ComplexNode() : std::complex(NAN, NAN) {} + ComplexNode(std::complex c); // TreeNode size_t size() const override { return sizeof(ComplexNode); } @@ -26,7 +26,6 @@ public: } #endif - virtual void setComplex(std::complex c); typename Poincare::EvaluationNode::Type type() const override { return Poincare::EvaluationNode::Type::Complex; } bool isUndefined() const override { return (std::isnan(this->real()) && std::isnan(this->imag())); @@ -41,10 +40,10 @@ template class Complex final : public Evaluation { public: Complex(ComplexNode * n) : Evaluation(n) {} - explicit Complex(T a, T b = 0.0) : Complex(std::complex(a, b)) {} - explicit Complex(std::complex c); + static Complex Builder(std::complex c); + static Complex Builder(T a, T b = 0.0) { return Complex::Builder(std::complex(a, b)); } static Complex Undefined() { - return Complex(NAN, NAN); + return Complex::Builder(NAN, NAN); } std::complex stdComplex() { return *node(); } T real() { return node()->real(); } diff --git a/poincare/include/poincare/complex_argument.h b/poincare/include/poincare/complex_argument.h index c770ed433..9ec2bec09 100644 --- a/poincare/include/poincare/complex_argument.h +++ b/poincare/include/poincare/complex_argument.h @@ -41,15 +41,11 @@ private: class ComplexArgument final : public Expression { public: ComplexArgument(const ComplexArgumentNode * n) : Expression(n) {} - static ComplexArgument Builder(Expression child) { return ComplexArgument(child); } + static ComplexArgument Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("arg", 1, &UntypedBuilder); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); -private: - explicit ComplexArgument(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/complex_cartesian.h b/poincare/include/poincare/complex_cartesian.h index e86835e64..4a6db764f 100644 --- a/poincare/include/poincare/complex_cartesian.h +++ b/poincare/include/poincare/complex_cartesian.h @@ -38,8 +38,8 @@ class ComplexCartesian final : public Expression { public: ComplexCartesian() : Expression() {} ComplexCartesian(const ComplexCartesianNode * node) : Expression(node) {} - static ComplexCartesian Builder() { ComplexCartesianNode * node = TreePool::sharedPool()->createTreeNode(); return ComplexCartesian(node); } - static ComplexCartesian Builder(Expression child0, Expression child1) { return ComplexCartesian(child0, child1); } + static ComplexCartesian Builder(); + static ComplexCartesian Builder(Expression child0, Expression child1); // Getters Expression real() { return childAtIndex(0); } @@ -60,10 +60,6 @@ public: ComplexCartesian power(ComplexCartesian & other, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: static constexpr int k_maxNumberOfNodesBeforeInterrupting = 50; - ComplexCartesian(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child0); - replaceChildAtIndexInPlace(1, child1); - } void factorAndArgumentOfFunction(Expression e, ExpressionNode::Type searchedType, Expression * factor, Expression * argument, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); ComplexCartesian interruptComputationIfManyNodes(); static Multiplication squareRootHelper(Expression e, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); diff --git a/poincare/include/poincare/condensed_sum_layout.h b/poincare/include/poincare/condensed_sum_layout.h index 59d2f6a7c..9c95a20d9 100644 --- a/poincare/include/poincare/condensed_sum_layout.h +++ b/poincare/include/poincare/condensed_sum_layout.h @@ -51,15 +51,8 @@ private: class CondensedSumLayout final : public Layout { public: - static CondensedSumLayout Builder(Layout base, Layout subscript, Layout superscript) { return CondensedSumLayout(base, subscript, superscript); } -private: - CondensedSumLayout(Layout base, Layout subscript, Layout superscript) : - Layout(TreePool::sharedPool()->createTreeNode()) - { - replaceChildAtIndexInPlace(0, base); - replaceChildAtIndexInPlace(1, subscript); - replaceChildAtIndexInPlace(2, superscript); - } + static CondensedSumLayout Builder(Layout base, Layout subscript, Layout superscript); + CondensedSumLayout() = delete; }; } diff --git a/poincare/include/poincare/confidence_interval.h b/poincare/include/poincare/confidence_interval.h index 30eda3893..88c82fc79 100644 --- a/poincare/include/poincare/confidence_interval.h +++ b/poincare/include/poincare/confidence_interval.h @@ -45,31 +45,22 @@ class ConfidenceInterval : public Expression { friend class SimplePredictionInterval; public: ConfidenceInterval(const ConfidenceIntervalNode * n) : Expression(n) {} - static ConfidenceInterval Builder(Expression child0, Expression child1) { return ConfidenceInterval(child0, child1); } + static ConfidenceInterval Builder(Expression child0, Expression child1); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("confidence", 2, &UntypedBuilder); // Expression Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: - ConfidenceInterval(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child0); - replaceChildAtIndexInPlace(1, child1); - } constexpr static int k_maxNValue = 300; }; class SimplePredictionInterval final : public ConfidenceInterval { public: SimplePredictionInterval(const SimplePredictionIntervalNode * n) : ConfidenceInterval(n) {} - static SimplePredictionInterval Builder(Expression child0, Expression child1) { return SimplePredictionInterval(child0, child1); } + static SimplePredictionInterval Builder(Expression child0, Expression child1); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("prediction", 2, &UntypedBuilder); -private: - SimplePredictionInterval(Expression child0, Expression child1) : ConfidenceInterval(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child0); - replaceChildAtIndexInPlace(1, child1); - } }; } diff --git a/poincare/include/poincare/conjugate.h b/poincare/include/poincare/conjugate.h index ac465b4cc..f6a0a1cb4 100644 --- a/poincare/include/poincare/conjugate.h +++ b/poincare/include/poincare/conjugate.h @@ -41,15 +41,11 @@ private: class Conjugate final : public Expression { public: Conjugate(const ConjugateNode * n) : Expression(n) {} - static Conjugate Builder(Expression child) { return Conjugate(child); } + static Conjugate Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("conj", 1, &UntypedBuilder);; Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); -private: - explicit Conjugate(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/conjugate_layout.h b/poincare/include/poincare/conjugate_layout.h index d95dde4f7..fe0bf5ea9 100644 --- a/poincare/include/poincare/conjugate_layout.h +++ b/poincare/include/poincare/conjugate_layout.h @@ -40,11 +40,8 @@ private: class ConjugateLayout final : public Layout { public: - static ConjugateLayout Builder(Layout l) { return ConjugateLayout(l); } -private: - explicit ConjugateLayout(Layout l) : Layout(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, l); - } + static ConjugateLayout Builder(Layout child); + ConjugateLayout() = delete; }; } diff --git a/poincare/include/poincare/constant.h b/poincare/include/poincare/constant.h index c5c529b87..c0754357c 100644 --- a/poincare/include/poincare/constant.h +++ b/poincare/include/poincare/constant.h @@ -7,6 +7,8 @@ namespace Poincare { class ConstantNode final : public SymbolAbstractNode { public: + ConstantNode(const char * newName, int length); + const char * name() const override { return m_name; } // TreeNode @@ -52,8 +54,8 @@ private: class Constant final : public SymbolAbstract { public: - Constant(char name); Constant(const ConstantNode * node) : SymbolAbstract(node) {} + static Constant Builder(char name); // Constant properties bool isPi() const { return node()->isPi(); } diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index 060384a0b..3e0524a65 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -46,15 +46,11 @@ private: class Cosine final : public Expression { public: Cosine(const CosineNode * n) : Expression(n) {} - static Cosine Builder(Expression child) { return Cosine(child); } + static Cosine Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("cos", 1, &UntypedBuilder); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); -private: - explicit Cosine(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index 22971bb8c..e55904fc7 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -18,19 +18,13 @@ class Decimal; class DecimalNode final : public NumberNode { friend class Decimal; public: - DecimalNode() : - m_negative(false), - m_exponent(0), - m_numberOfDigitsInMantissa(0) {} - - virtual void setValue(const native_uint_t * mantissaDigits, uint8_t mantissaSize, int exponent, bool negative); + DecimalNode(const native_uint_t * mantissaDigits, uint8_t mantissaSize, int exponent, bool negative); Integer signedMantissa() const; Integer unsignedMantissa() const; int exponent() const { return m_exponent; } // TreeNode - void initToMatchSize(size_t size) override; size_t size() const override; #if POINCARE_TREE_LOG virtual void logNodeName(std::ostream & stream) const override { @@ -52,10 +46,10 @@ public: // Approximation Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { - return Complex(templatedApproximate()); + return Complex::Builder(templatedApproximate()); } Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { - return Complex(templatedApproximate()); + return Complex::Builder(templatedApproximate()); } // Comparison @@ -88,11 +82,12 @@ friend class DecimalNode; template friend class ComplexNode; public: - static int Exponent(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, const char * exponent, int exponentLength, bool exponentIsNegative = false); - Decimal(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, int exponent); Decimal(DecimalNode * node) : Number(node) {} - Decimal(Integer m, int e); - template Decimal(T f); + static Decimal Builder(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, int exponent); + static Decimal Builder(Integer m, int e); + template static Decimal Builder(T f); + static int Exponent(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, const char * exponent, int exponentLength, bool exponentIsNegative = false); + /* k_maxExponentLength caps the string length we parse to create the exponent. * It prevents m_exponent (int32_t) from overflowing and giving wrong results. */ constexpr static int k_maxExponentLength = 8; @@ -101,7 +96,7 @@ public: private: constexpr static int k_maxMantissaLength = 20; DecimalNode * node() const { return static_cast(Number::node()); } - Decimal(size_t size, const Integer & m, int e); + static Decimal Builder(size_t size, const Integer & m, int e); Expression setSign(ExpressionNode::Sign s); // Simplification Expression shallowReduce(); diff --git a/poincare/include/poincare/derivative.h b/poincare/include/poincare/derivative.h index 4bb534b37..70dc0973a 100644 --- a/poincare/include/poincare/derivative.h +++ b/poincare/include/poincare/derivative.h @@ -51,7 +51,7 @@ private: class Derivative final : public Expression { public: Derivative(const DerivativeNode * n) : Expression(n) {} - static Derivative Builder(Expression child0, Symbol child1, Expression child2) { return Derivative(child0, child1, child2); } + static Derivative Builder(Expression child0, Symbol child1, Expression child2); static Expression UntypedBuilder(Expression children) { if (children.childAtIndex(1).type() != ExpressionNode::Type::Symbol) { // Second parameter must be a Symbol. @@ -62,13 +62,6 @@ public: static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("diff", 3, &UntypedBuilder); Expression shallowReduce(); -private: - Derivative(Expression child0, Expression child1, Expression child2) : Expression(TreePool::sharedPool()->createTreeNode()) { - assert(child1.type() == ExpressionNode::Type::Symbol); - replaceChildAtIndexInPlace(0, child0); - replaceChildAtIndexInPlace(1, child1); - replaceChildAtIndexInPlace(2, child2); - } }; } diff --git a/poincare/include/poincare/determinant.h b/poincare/include/poincare/determinant.h index 8909acca7..ff350e1fd 100644 --- a/poincare/include/poincare/determinant.h +++ b/poincare/include/poincare/determinant.h @@ -35,15 +35,11 @@ private: class Determinant final : public Expression { public: Determinant(const DeterminantNode * n) : Expression(n) {} - static Determinant Builder(Expression child) { return Determinant(child); } + static Determinant Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("det", 1, &UntypedBuilder); Expression shallowReduce(Context & context); -private: - explicit Determinant(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/division.h b/poincare/include/poincare/division.h index b620eba3d..c1bf207b5 100644 --- a/poincare/include/poincare/division.h +++ b/poincare/include/poincare/division.h @@ -61,18 +61,10 @@ private: class Division final : public Expression { public: Division(const DivisionNode * n) : Expression(n) {} - static Division Builder() { return Division(); } - static Division Builder(Expression numerator, Expression denominator) { - Division d; - d.replaceChildAtIndexInPlace(0, numerator); - d.replaceChildAtIndexInPlace(1, denominator); - return d; - } + static Division Builder(); + static Division Builder(Expression numerator, Expression denominator); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - -private: - Division() : Expression(TreePool::sharedPool()->createTreeNode()) {} }; } diff --git a/poincare/include/poincare/division_quotient.h b/poincare/include/poincare/division_quotient.h index 170eaf74a..d6f358a73 100644 --- a/poincare/include/poincare/division_quotient.h +++ b/poincare/include/poincare/division_quotient.h @@ -38,17 +38,12 @@ private: class DivisionQuotient final : public Expression { public: DivisionQuotient(const DivisionQuotientNode * n) : Expression(n) {} - static DivisionQuotient Builder(Expression child0, Expression child1) { return DivisionQuotient(child0, child1); } + static DivisionQuotient Builder(Expression child0, Expression child1); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("quo", 2, &UntypedBuilder); // Expression Expression shallowReduce(); -private: - DivisionQuotient(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child0); - replaceChildAtIndexInPlace(1, child1); - } }; } diff --git a/poincare/include/poincare/division_remainder.h b/poincare/include/poincare/division_remainder.h index 07443c5d2..b7a3e1273 100644 --- a/poincare/include/poincare/division_remainder.h +++ b/poincare/include/poincare/division_remainder.h @@ -39,17 +39,12 @@ private: class DivisionRemainder final : public Expression { public: DivisionRemainder(const DivisionRemainderNode * n) : Expression(n) {} - static DivisionRemainder Builder(Expression child0, Expression child1) { return DivisionRemainder(child0, child1); } + static DivisionRemainder Builder(Expression child0, Expression child1); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("rem", 2, &UntypedBuilder); // Expression Expression shallowReduce(); -private: - DivisionRemainder(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child0); - replaceChildAtIndexInPlace(1, child1); - } }; } diff --git a/poincare/include/poincare/empty_expression.h b/poincare/include/poincare/empty_expression.h index 0f67887b6..332430992 100644 --- a/poincare/include/poincare/empty_expression.h +++ b/poincare/include/poincare/empty_expression.h @@ -33,7 +33,7 @@ private: class EmptyExpression final : public Expression { public: - EmptyExpression(); + static EmptyExpression Builder(); EmptyExpression(const EmptyExpressionNode * n) : Expression(n) {} }; diff --git a/poincare/include/poincare/empty_layout.h b/poincare/include/poincare/empty_layout.h index 9cb5ea312..cc07406bb 100644 --- a/poincare/include/poincare/empty_layout.h +++ b/poincare/include/poincare/empty_layout.h @@ -26,8 +26,6 @@ public: void setColor(Color color) { m_color = color; } bool isVisible() const { return m_isVisible; } void setVisible(bool visible) { m_isVisible = visible; } - void setMargins(bool margins) { m_margins = margins; } - void setFont(const KDFont * font) { m_font = font; } // LayoutNode void deleteBeforeCursor(LayoutCursor * cursor) override; @@ -75,7 +73,7 @@ private: class EmptyLayout final : public Layout { public: EmptyLayout(const EmptyLayoutNode * n); - EmptyLayout(EmptyLayoutNode::Color color = EmptyLayoutNode::Color::Yellow, bool visible = true, const KDFont * font = KDFont::LargeFont, bool margins = true); + static EmptyLayout Builder(EmptyLayoutNode::Color color = EmptyLayoutNode::Color::Yellow, bool visible = true, const KDFont * font = KDFont::LargeFont, bool margins = true); void setVisible(bool visible) { node()->setVisible(visible); } diff --git a/poincare/include/poincare/equal.h b/poincare/include/poincare/equal.h index 6b91f2d62..e191b12ba 100644 --- a/poincare/include/poincare/equal.h +++ b/poincare/include/poincare/equal.h @@ -35,10 +35,7 @@ private: class Equal final : public Expression { public: Equal(const EqualNode * n) : Expression(n) {} - Equal(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child0); - replaceChildAtIndexInPlace(1, child1); - } + static Equal Builder(Expression child0, Expression child1); // For the equation A = B, create the reduced expression A-B Expression standardEquation(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; diff --git a/poincare/include/poincare/factor.h b/poincare/include/poincare/factor.h index 401a90126..09ebcbf6a 100644 --- a/poincare/include/poincare/factor.h +++ b/poincare/include/poincare/factor.h @@ -37,16 +37,12 @@ private: class Factor final : public Expression { public: Factor(const FactorNode * n) : Expression(n) {} - static Factor Builder(Expression child) { return Factor(child); } + static Factor Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("factor", 1, &UntypedBuilder); Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); Multiplication createMultiplicationOfIntegerPrimeDecomposition(Integer i, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; -private: - explicit Factor(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index 2a1f2774d..c76129c69 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -52,18 +52,13 @@ private: class Factorial final : public Expression { public: Factorial(const FactorialNode * n) : Expression(n) {} - static Factorial Builder() { return Factorial(); } - static Factorial Builder(Expression child) { - Factorial f; - f.replaceChildAtIndexInPlace(0, child); - return f; - } + static Factorial Builder(); + static Factorial Builder(Expression child); Expression shallowReduce(); Expression shallowBeautify(); private: constexpr static int k_maxOperandValue = 100; - Factorial() : Expression(TreePool::sharedPool()->createTreeNode()) {} }; } diff --git a/poincare/include/poincare/float.h b/poincare/include/poincare/float.h index 039a967ad..9ecdaab70 100644 --- a/poincare/include/poincare/float.h +++ b/poincare/include/poincare/float.h @@ -20,10 +20,8 @@ namespace Poincare { template class FloatNode final : public NumberNode { public: - FloatNode() : m_value(0.0) {} + FloatNode(T value = 0.0) : m_value(value) {} - - void setFloat(T a) { m_value = a; } T value() const { return m_value; } // TreeNode @@ -52,7 +50,7 @@ public: Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } private: template Evaluation templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { - return Complex((U)m_value); + return Complex::Builder((U)m_value); } T m_value; }; @@ -60,7 +58,7 @@ private: template class Float final : public Number { public: - Float(T value); + static Float Builder(T value); private: FloatNode * node() const { return static_cast *>(Number::node()); } }; diff --git a/poincare/include/poincare/floor.h b/poincare/include/poincare/floor.h index 7a823747f..507ecb541 100644 --- a/poincare/include/poincare/floor.h +++ b/poincare/include/poincare/floor.h @@ -44,15 +44,11 @@ private: class Floor final : public Expression { public: Floor(const FloorNode * n) : Expression(n) {} - static Floor Builder(Expression child) { return Floor(child); } + static Floor Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("floor", 1, &UntypedBuilder); Expression shallowReduce(); -private: - explicit Floor(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/floor_layout.h b/poincare/include/poincare/floor_layout.h index 7caf67ed0..77ee2b986 100644 --- a/poincare/include/poincare/floor_layout.h +++ b/poincare/include/poincare/floor_layout.h @@ -29,11 +29,8 @@ protected: class FloorLayout final : public Layout { public: - static FloorLayout Builder(Layout l) { return FloorLayout(l); } -private: - explicit FloorLayout(Layout l) : Layout(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, l); - } + static FloorLayout Builder(Layout child); + FloorLayout() = delete; }; } diff --git a/poincare/include/poincare/frac_part.h b/poincare/include/poincare/frac_part.h index 9988621c1..f6551e063 100644 --- a/poincare/include/poincare/frac_part.h +++ b/poincare/include/poincare/frac_part.h @@ -44,15 +44,11 @@ private: class FracPart final : public Expression { public: FracPart(const FracPartNode * n) : Expression(n) {} - static FracPart Builder(Expression child) { return FracPart(child); } + static FracPart Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("frac", 1, &UntypedBuilder); Expression shallowReduce(); -private: - explicit FracPart(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/fraction_layout.h b/poincare/include/poincare/fraction_layout.h index 23ee39f8f..17df46c28 100644 --- a/poincare/include/poincare/fraction_layout.h +++ b/poincare/include/poincare/fraction_layout.h @@ -58,14 +58,8 @@ private: class FractionLayout final : public Layout { public: - static FractionLayout Builder(Layout numerator, Layout denominator) { return FractionLayout(numerator, denominator); } -private: - FractionLayout(Layout numerator, Layout denominator) : - Layout(TreePool::sharedPool()->createTreeNode()) - { - replaceChildAtIndexInPlace(0, numerator); - replaceChildAtIndexInPlace(1, denominator); - } + static FractionLayout Builder(Layout numerator, Layout denominator); + FractionLayout() = delete; }; } diff --git a/poincare/include/poincare/function.h b/poincare/include/poincare/function.h index c12bc6896..781324826 100644 --- a/poincare/include/poincare/function.h +++ b/poincare/include/poincare/function.h @@ -8,6 +8,8 @@ namespace Poincare { class FunctionNode : public SymbolAbstractNode { public: + FunctionNode(const char * newName, int length); + // SymbolAbstractNode const char * name() const override { return m_name; } @@ -49,15 +51,12 @@ private: class Function : public SymbolAbstract { friend class FunctionNode; public: - Function(const char * name, size_t length); Function(const FunctionNode * n) : SymbolAbstract(n) {} - Function(const char * name, size_t length, Expression child) : Function(name, length) { - replaceChildAtIndexInPlace(0, child); - } + static Function Builder(const char * name, size_t length, Expression child = Expression()); static Expression UntypedBuilder(const char * name, size_t length, Expression child, Context * context) { /* Create an expression only if it is not in the context or defined as a * function */ - Function f(name, length, child); + Function f = Function::Builder(name, length, child); if (SymbolAbstract::ValidInContext(f, context)) { return f; } diff --git a/poincare/include/poincare/ghost.h b/poincare/include/poincare/ghost.h index d27eff5e9..da30640df 100644 --- a/poincare/include/poincare/ghost.h +++ b/poincare/include/poincare/ghost.h @@ -12,9 +12,12 @@ namespace Poincare { class Ghost final : public TreeHandle { public: - static Ghost Builder() { return Ghost(); } -private: - Ghost() : TreeHandle(TreePool::sharedPool()->createTreeNode()) {} + static Ghost Builder() { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(GhostNode)); + GhostNode * node = new (bufferNode) GhostNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); + } }; } diff --git a/poincare/include/poincare/great_common_divisor.h b/poincare/include/poincare/great_common_divisor.h index b392fede9..019867025 100644 --- a/poincare/include/poincare/great_common_divisor.h +++ b/poincare/include/poincare/great_common_divisor.h @@ -37,17 +37,12 @@ private: class GreatCommonDivisor final : public Expression { public: GreatCommonDivisor(const GreatCommonDivisorNode * n) : Expression(n) {} - static GreatCommonDivisor Builder(Expression child0, Expression child1) { return GreatCommonDivisor(child0, child1); } + static GreatCommonDivisor Builder(Expression child0, Expression child1); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("gcd", 2, &UntypedBuilder); // Expression Expression shallowReduce(); -private: - GreatCommonDivisor(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child0); - replaceChildAtIndexInPlace(1, child1); - } }; } diff --git a/poincare/include/poincare/grid_layout.h b/poincare/include/poincare/grid_layout.h index 46e0b8e2e..9510c75f9 100644 --- a/poincare/include/poincare/grid_layout.h +++ b/poincare/include/poincare/grid_layout.h @@ -89,7 +89,7 @@ private: class GridLayout : public Layout { public: GridLayout(const GridLayoutNode * n) : Layout(n) {} - static GridLayout Builder() { return GridLayout(); } + static GridLayout Builder(); void setDimensions(int rows, int columns); void addChildAtIndex(Layout l, int index, int currentNumberOfChildren, LayoutCursor * cursor) { Layout::addChildAtIndex(l, index, currentNumberOfChildren, cursor); @@ -97,7 +97,6 @@ public: int numberOfRows() const { return node()->numberOfRows(); } int numberOfColumns() const { return node()->numberOfColumns(); } private: - GridLayout() : Layout(TreePool::sharedPool()->createTreeNode()) {} virtual GridLayoutNode * node() const { return static_cast(Layout::node()); } void setNumberOfRows(int rows) { assert(rows >= 0); diff --git a/poincare/include/poincare/horizontal_layout.h b/poincare/include/poincare/horizontal_layout.h index 5cb32b211..2b39ecd29 100644 --- a/poincare/include/poincare/horizontal_layout.h +++ b/poincare/include/poincare/horizontal_layout.h @@ -68,7 +68,7 @@ class HorizontalLayout final : public Layout { public: // Constructors HorizontalLayout(HorizontalLayoutNode * n) : Layout(n) {} - static HorizontalLayout Builder() { return HorizontalLayout(); } + static HorizontalLayout Builder(); static HorizontalLayout Builder(Layout l) { return HorizontalLayout::Builder(&l, 1); } static HorizontalLayout Builder(Layout l1, Layout l2) { return HorizontalLayout::Builder(ArrayBuilder(l1, l2).array(), 2); } static HorizontalLayout Builder(Layout l1, Layout l2, Layout l3) { return HorizontalLayout::Builder(ArrayBuilder(l1, l2, l3).array(), 3); } @@ -93,7 +93,6 @@ public: void mergeChildrenAtIndex(HorizontalLayout h, int index, bool removeEmptyChildren, LayoutCursor * cursor = nullptr); private: - HorizontalLayout() : Layout(TreePool::sharedPool()->createTreeNode()) {} void removeEmptyChildBeforeInsertionAtIndex(int * index, int * currentNumberOfChildren, bool shouldRemoveOnLeft, LayoutCursor * cursor = nullptr); }; diff --git a/poincare/include/poincare/hyperbolic_arc_cosine.h b/poincare/include/poincare/hyperbolic_arc_cosine.h index aebd357ef..8f8a8272f 100644 --- a/poincare/include/poincare/hyperbolic_arc_cosine.h +++ b/poincare/include/poincare/hyperbolic_arc_cosine.h @@ -36,13 +36,9 @@ private: class HyperbolicArcCosine final : public HyperbolicTrigonometricFunction { public: HyperbolicArcCosine(const HyperbolicArcCosineNode * n) : HyperbolicTrigonometricFunction(n) {} - static HyperbolicArcCosine Builder(Expression child) { return HyperbolicArcCosine(child); } + static HyperbolicArcCosine Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("acosh", 1, &UntypedBuilder); -private: - explicit HyperbolicArcCosine(Expression child) : HyperbolicTrigonometricFunction(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/hyperbolic_arc_sine.h b/poincare/include/poincare/hyperbolic_arc_sine.h index fd7ec2644..0569275c2 100644 --- a/poincare/include/poincare/hyperbolic_arc_sine.h +++ b/poincare/include/poincare/hyperbolic_arc_sine.h @@ -36,13 +36,9 @@ private: class HyperbolicArcSine final : public HyperbolicTrigonometricFunction { public: HyperbolicArcSine(const HyperbolicArcSineNode * n) : HyperbolicTrigonometricFunction(n) {} - static HyperbolicArcSine Builder(Expression child) { return HyperbolicArcSine(child); } + static HyperbolicArcSine Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("asinh", 1, &UntypedBuilder); -private: - explicit HyperbolicArcSine(Expression child) : HyperbolicTrigonometricFunction(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/hyperbolic_arc_tangent.h b/poincare/include/poincare/hyperbolic_arc_tangent.h index 01bfe38ab..565fcb42f 100644 --- a/poincare/include/poincare/hyperbolic_arc_tangent.h +++ b/poincare/include/poincare/hyperbolic_arc_tangent.h @@ -36,13 +36,9 @@ private: class HyperbolicArcTangent final : public HyperbolicTrigonometricFunction { public: HyperbolicArcTangent(const HyperbolicArcTangentNode * n) : HyperbolicTrigonometricFunction(n) {} - static HyperbolicArcTangent Builder(Expression child) { return HyperbolicArcTangent(child); } + static HyperbolicArcTangent Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("atanh", 1, &UntypedBuilder); -private: - explicit HyperbolicArcTangent(Expression child) : HyperbolicTrigonometricFunction(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/hyperbolic_cosine.h b/poincare/include/poincare/hyperbolic_cosine.h index 6764d1948..cbe78f7ba 100644 --- a/poincare/include/poincare/hyperbolic_cosine.h +++ b/poincare/include/poincare/hyperbolic_cosine.h @@ -36,13 +36,9 @@ private: class HyperbolicCosine final : public HyperbolicTrigonometricFunction { public: HyperbolicCosine(const HyperbolicCosineNode * n) : HyperbolicTrigonometricFunction(n) {} - static HyperbolicCosine Builder(Expression child) { return HyperbolicCosine(child); } + static HyperbolicCosine Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("cosh", 1, &UntypedBuilder); -private: - explicit HyperbolicCosine(Expression child) : HyperbolicTrigonometricFunction(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/hyperbolic_sine.h b/poincare/include/poincare/hyperbolic_sine.h index 2acdc7dd7..53cf3eb85 100644 --- a/poincare/include/poincare/hyperbolic_sine.h +++ b/poincare/include/poincare/hyperbolic_sine.h @@ -36,13 +36,9 @@ private: class HyperbolicSine final : public HyperbolicTrigonometricFunction { public: HyperbolicSine(const HyperbolicSineNode * n) : HyperbolicTrigonometricFunction(n) {} - static HyperbolicSine Builder(Expression child) { return HyperbolicSine(child); } + static HyperbolicSine Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("sinh", 1, &UntypedBuilder); -private: - explicit HyperbolicSine(Expression child) : HyperbolicTrigonometricFunction(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/hyperbolic_tangent.h b/poincare/include/poincare/hyperbolic_tangent.h index d6d887c2e..cc43e572b 100644 --- a/poincare/include/poincare/hyperbolic_tangent.h +++ b/poincare/include/poincare/hyperbolic_tangent.h @@ -36,13 +36,9 @@ private: class HyperbolicTangent final : public HyperbolicTrigonometricFunction { public: HyperbolicTangent(const HyperbolicTangentNode * n) : HyperbolicTrigonometricFunction(n) {} - static HyperbolicTangent Builder(Expression child) { return HyperbolicTangent(child); } + static HyperbolicTangent Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("tanh", 1, &UntypedBuilder); -private: - explicit HyperbolicTangent(Expression child) : HyperbolicTrigonometricFunction(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/imaginary_part.h b/poincare/include/poincare/imaginary_part.h index 06956b66d..3fda87d4e 100644 --- a/poincare/include/poincare/imaginary_part.h +++ b/poincare/include/poincare/imaginary_part.h @@ -32,7 +32,7 @@ private: Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { - return Complex(std::imag(c)); + return Complex::Builder(std::imag(c)); } Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return ApproximationHelper::Map(this, context, complexFormat, angleUnit,computeOnComplex); @@ -45,15 +45,11 @@ private: class ImaginaryPart final : public Expression { public: ImaginaryPart(const ImaginaryPartNode * n) : Expression(n) {} - static ImaginaryPart Builder(Expression child) { return ImaginaryPart(child); } + static ImaginaryPart Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("im", 1, &UntypedBuilder); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); -private: - explicit ImaginaryPart(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/infinity.h b/poincare/include/poincare/infinity.h index a88ecee04..b1b552394 100644 --- a/poincare/include/poincare/infinity.h +++ b/poincare/include/poincare/infinity.h @@ -7,8 +7,8 @@ namespace Poincare { class InfinityNode final : public NumberNode { public: + InfinityNode(bool negative) : NumberNode(), m_negative(negative) {} - void setNegative(bool negative) { m_negative = negative; } Expression setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // TreeNode @@ -45,9 +45,7 @@ private: class Infinity final : public Number { public: Infinity(InfinityNode * n) : Number(n) {} - Infinity(bool negative) : Number(TreePool::sharedPool()->createTreeNode()) { - node()->setNegative(negative); - } + static Infinity Builder(bool negative); Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); static const char * Name() { return "inf"; diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 61ebcf47e..11aea50db 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -31,8 +31,8 @@ struct IntegerDivision; class IntegerNode final : public TreeNode { public: + IntegerNode(const native_uint_t * digits, uint8_t numberOfDigits); // TreeNode - void initToMatchSize(size_t goalSize) override; size_t size() const override; int numberOfChildren() const override { return 0; } #if POINCARE_TREE_LOG @@ -43,7 +43,6 @@ public: virtual void logAttributes(std::ostream & stream) const override; #endif - virtual void setDigits(const native_uint_t * digits, uint8_t numberOfDigits); const native_uint_t * digits() const { return m_digits; } uint8_t numberOfDigits() const { return m_numberOfDigits; } private: diff --git a/poincare/include/poincare/integral.h b/poincare/include/poincare/integral.h index 195b7647a..403a41b13 100644 --- a/poincare/include/poincare/integral.h +++ b/poincare/include/poincare/integral.h @@ -55,7 +55,7 @@ private: class Integral final : public Expression { public: Integral(const IntegralNode * n) : Expression(n) {} - static Integral Builder(Expression child0, Symbol child1, Expression child2, Expression child3) { return Integral(child0, child1, child2, child3); } + static Integral Builder(Expression child0, Symbol child1, Expression child2, Expression child3); static Expression UntypedBuilder(Expression children) { if (children.childAtIndex(1).type() != ExpressionNode::Type::Symbol) { // Second parameter must be a Symbol. @@ -67,14 +67,6 @@ public: // Expression Expression shallowReduce(); -private: - Integral(Expression child0, Expression child1, Expression child2, Expression child3) : Expression(TreePool::sharedPool()->createTreeNode()) { - assert(child1.type() == ExpressionNode::Type::Symbol); - replaceChildAtIndexInPlace(0, child0); - replaceChildAtIndexInPlace(1, child1); - replaceChildAtIndexInPlace(2, child2); - replaceChildAtIndexInPlace(3, child3); - } }; } diff --git a/poincare/include/poincare/integral_layout.h b/poincare/include/poincare/integral_layout.h index 26fc711a0..79f6e8a73 100644 --- a/poincare/include/poincare/integral_layout.h +++ b/poincare/include/poincare/integral_layout.h @@ -56,16 +56,8 @@ private: class IntegralLayout final : public Layout { public: - static IntegralLayout Builder(Layout integrand, Layout differential, Layout lowerBound, Layout upperBound) { return IntegralLayout(integrand, differential, lowerBound, upperBound); } -private: - IntegralLayout(Layout integrand, Layout differential, Layout lowerBound, Layout upperBound) : - Layout(TreePool::sharedPool()->createTreeNode()) - { - replaceChildAtIndexInPlace(0, integrand); - replaceChildAtIndexInPlace(1, differential); - replaceChildAtIndexInPlace(2, lowerBound); - replaceChildAtIndexInPlace(3, upperBound); - } + static IntegralLayout Builder(Layout integrand, Layout differential, Layout lowerBound, Layout upperBound); + IntegralLayout() = delete; }; } diff --git a/poincare/include/poincare/least_common_multiple.h b/poincare/include/poincare/least_common_multiple.h index 9dcd9e114..4f2fcbe4f 100644 --- a/poincare/include/poincare/least_common_multiple.h +++ b/poincare/include/poincare/least_common_multiple.h @@ -37,17 +37,12 @@ private: class LeastCommonMultiple final : public Expression { public: LeastCommonMultiple(const LeastCommonMultipleNode * n) : Expression(n) {} - static LeastCommonMultiple Builder(Expression child0, Expression child1) { return LeastCommonMultiple(child0, child1); } + static LeastCommonMultiple Builder(Expression child0, Expression child1); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("lcm", 2, &UntypedBuilder); // Expression Expression shallowReduce(); -private: - LeastCommonMultiple(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child0); - replaceChildAtIndexInPlace(1, child1); - } }; } diff --git a/poincare/include/poincare/left_parenthesis_layout.h b/poincare/include/poincare/left_parenthesis_layout.h index 5bf6d25e0..66f52047b 100644 --- a/poincare/include/poincare/left_parenthesis_layout.h +++ b/poincare/include/poincare/left_parenthesis_layout.h @@ -35,9 +35,8 @@ protected: class LeftParenthesisLayout final : public Layout { public: - static LeftParenthesisLayout Builder() { return LeftParenthesisLayout(); } -private: - LeftParenthesisLayout() : Layout(TreePool::sharedPool()->createTreeNode()) {} + static LeftParenthesisLayout Builder(); + LeftParenthesisLayout() = delete; }; } diff --git a/poincare/include/poincare/left_square_bracket_layout.h b/poincare/include/poincare/left_square_bracket_layout.h index c0dfed6cd..558e69e3b 100644 --- a/poincare/include/poincare/left_square_bracket_layout.h +++ b/poincare/include/poincare/left_square_bracket_layout.h @@ -29,9 +29,8 @@ protected: class LeftSquareBracketLayout final : public Layout { public: - static LeftSquareBracketLayout Builder() { return LeftSquareBracketLayout(); } -private: - LeftSquareBracketLayout() : Layout(TreePool::sharedPool()->createTreeNode()) {} + static LeftSquareBracketLayout Builder(); + LeftSquareBracketLayout() = delete; }; } diff --git a/poincare/include/poincare/logarithm.h b/poincare/include/poincare/logarithm.h index 9bc82b5dd..c7c5e5902 100644 --- a/poincare/include/poincare/logarithm.h +++ b/poincare/include/poincare/logarithm.h @@ -34,7 +34,7 @@ public: /* log has a branch cut on ]-inf, 0]: it is then multivalued on this cut. We * followed the convention chosen by the lib c++ of llvm on ]-inf+0i, 0+0i] * (warning: log takes the other side of the cut values on ]-inf-0i, 0-0i]). */ - return Complex(std::log10(c)); + return Complex::Builder(std::log10(c)); } Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } @@ -44,7 +44,7 @@ public: class Logarithm final : public Expression { public: Logarithm(const LogarithmNode<2> * n) : Expression(n) {} - static Logarithm Builder(Expression child0, Expression child1) { return Logarithm(child0, child1); } + static Logarithm Builder(Expression child0, Expression child1); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("log", 2, &UntypedBuilder); @@ -52,10 +52,6 @@ public: Expression shallowBeautify(); private: - Logarithm(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode >()) { - replaceChildAtIndexInPlace(0, child0); - replaceChildAtIndexInPlace(1, child1); - } Expression simpleShallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); Integer simplifyLogarithmIntegerBaseInteger(Integer i, Integer & base, Addition & a, bool isDenominator); Expression splitLogarithmInteger(Integer i, bool isDenominator, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); @@ -65,15 +61,11 @@ private: class CommonLogarithm : public Expression { public: CommonLogarithm(const LogarithmNode<1> * n) : Expression(n) {} - static CommonLogarithm Builder(Expression child) { return CommonLogarithm(child); } + static CommonLogarithm Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("log", 1, &UntypedBuilder); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); -private: - explicit CommonLogarithm(Expression child) : Expression(TreePool::sharedPool()->createTreeNode >()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/matrix.h b/poincare/include/poincare/matrix.h index 1c07e0708..790d7b556 100644 --- a/poincare/include/poincare/matrix.h +++ b/poincare/include/poincare/matrix.h @@ -63,7 +63,7 @@ class Matrix final : public Expression { friend class GlobalContext; public: Matrix(const MatrixNode * node) : Expression(node) {} - static Matrix Builder() { return Matrix(); } + static Matrix Builder(); void setDimensions(int rows, int columns); int numberOfRows() const { return node()->numberOfRows(); } @@ -85,7 +85,6 @@ public: Expression inverse(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; #endif private: - Matrix() : Matrix(TreePool::sharedPool()->createTreeNode()) {} // TODO: find another solution for inverse and determinant (avoid capping the matrix) static constexpr int k_maxNumberOfCoefficients = 100; diff --git a/poincare/include/poincare/matrix_complex.h b/poincare/include/poincare/matrix_complex.h index 83ddd941e..73a750a88 100644 --- a/poincare/include/poincare/matrix_complex.h +++ b/poincare/include/poincare/matrix_complex.h @@ -57,8 +57,8 @@ class MatrixComplex final : public Evaluation { friend class MatrixComplexNode; public: MatrixComplex(MatrixComplexNode * node) : Evaluation(node) {} - MatrixComplex(); - MatrixComplex(std::complex * operands, int numberOfRows, int numberOfColumns); + static MatrixComplex Builder(); + static MatrixComplex Builder(std::complex * operands, int numberOfRows, int numberOfColumns); static MatrixComplex Undefined(); static MatrixComplex createIdentity(int dim); MatrixComplex inverse() const { return node()->inverse(); } diff --git a/poincare/include/poincare/matrix_dimension.h b/poincare/include/poincare/matrix_dimension.h index 412072edd..5fc51803f 100644 --- a/poincare/include/poincare/matrix_dimension.h +++ b/poincare/include/poincare/matrix_dimension.h @@ -35,15 +35,11 @@ private: class MatrixDimension final : public Expression { public: MatrixDimension(const MatrixDimensionNode * n) : Expression(n) {} - static MatrixDimension Builder(Expression child) { return MatrixDimension(child); } + static MatrixDimension Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("dim", 1, &UntypedBuilder); Expression shallowReduce(); -private: - explicit MatrixDimension(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/matrix_inverse.h b/poincare/include/poincare/matrix_inverse.h index b4488c8c3..b03976fb4 100644 --- a/poincare/include/poincare/matrix_inverse.h +++ b/poincare/include/poincare/matrix_inverse.h @@ -34,15 +34,11 @@ private: class MatrixInverse final : public Expression { public: MatrixInverse(const MatrixInverseNode * n) : Expression(n) {} - static MatrixInverse Builder(Expression child) { return MatrixInverse(child); } + static MatrixInverse Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("inverse", 1, &UntypedBuilder); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); -private: - explicit MatrixInverse(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/matrix_layout.h b/poincare/include/poincare/matrix_layout.h index 9f3420136..519c6c585 100644 --- a/poincare/include/poincare/matrix_layout.h +++ b/poincare/include/poincare/matrix_layout.h @@ -57,8 +57,8 @@ private: class MatrixLayout /*final*/ : public GridLayout { friend class MatrixLayoutNode; public: - static MatrixLayout Builder() { return MatrixLayout(); } MatrixLayout(const MatrixLayoutNode * n) : GridLayout(n) {} + static MatrixLayout Builder(); static MatrixLayout Builder(Layout l1, Layout l2, Layout l3, Layout l4) { MatrixLayout m = MatrixLayout::Builder(); m.addChildAtIndexInPlace(l1, 0, 0); @@ -73,7 +73,6 @@ public: void addGreySquares() { node()->addGreySquares(); } void removeGreySquares() { node()->removeGreySquares(); } private: - MatrixLayout() : GridLayout(TreePool::sharedPool()->createTreeNode()) {} MatrixLayoutNode * node() const { return static_cast(Layout::node()); } }; diff --git a/poincare/include/poincare/matrix_trace.h b/poincare/include/poincare/matrix_trace.h index 3590ae444..ac281b937 100644 --- a/poincare/include/poincare/matrix_trace.h +++ b/poincare/include/poincare/matrix_trace.h @@ -34,15 +34,11 @@ private: class MatrixTrace final : public Expression { public: MatrixTrace(const MatrixTraceNode * n) : Expression(n) {} - static MatrixTrace Builder(Expression child) { return MatrixTrace(child); } + static MatrixTrace Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("trace", 1, &UntypedBuilder); Expression shallowReduce(); -private: - explicit MatrixTrace(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/matrix_transpose.h b/poincare/include/poincare/matrix_transpose.h index fe7e98ce1..bf6c1d7ec 100644 --- a/poincare/include/poincare/matrix_transpose.h +++ b/poincare/include/poincare/matrix_transpose.h @@ -34,15 +34,11 @@ private: class MatrixTranspose final : public Expression { public: MatrixTranspose(const MatrixTransposeNode * n) : Expression(n) {} - static MatrixTranspose Builder(Expression child) { return MatrixTranspose(child); } + static MatrixTranspose Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("transpose", 1, &UntypedBuilder); Expression shallowReduce(); -private: - explicit MatrixTranspose(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index b41bde2ce..9b4dba610 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -27,7 +27,7 @@ public: int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const override; // Approximation - template static Complex compute(const std::complex c, const std::complex d, Preferences::ComplexFormat complexFormat) { return Complex(c*d); } + template static Complex compute(const std::complex c, const std::complex d, Preferences::ComplexFormat complexFormat) { return Complex::Builder(c*d); } template static MatrixComplex computeOnComplexAndMatrix(const std::complex c, const MatrixComplex m, Preferences::ComplexFormat complexFormat) { return ApproximationHelper::ElementWiseOnMatrixComplexAndComplex(m, c, complexFormat, compute); } @@ -67,10 +67,10 @@ class Multiplication final : public NAryExpression { friend class Power; public: Multiplication(const MultiplicationNode * n) : NAryExpression(n) {} - static Multiplication Builder() { return Multiplication(); } - static Multiplication Builder(Expression e1) { return Multiplication(&e1, 1); } - static Multiplication Builder(Expression e1, Expression e2) { return Multiplication(ArrayBuilder(e1, e2).array(), 2); } - static Multiplication Builder(Expression e1, Expression e2, Expression e3) { return Multiplication(ArrayBuilder(e1, e2, e3).array(), 3); } + static Multiplication Builder(); + static Multiplication Builder(Expression e1) { return Multiplication::Builder(&e1, 1); } + static Multiplication Builder(Expression e1, Expression e2) { return Multiplication::Builder(ArrayBuilder(e1, e2).array(), 2); } + static Multiplication Builder(Expression e1, Expression e2, Expression e3) { return Multiplication::Builder(ArrayBuilder(e1, e2, e3).array(), 3); } template static void computeOnArrays(T * m, T * n, T * result, int mNumberOfColumns, int mNumberOfRows, int nNumberOfColumns); // Expression @@ -81,12 +81,8 @@ public: Expression denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; private: // Constructors - Multiplication() : NAryExpression(TreePool::sharedPool()->createTreeNode()) {} - explicit Multiplication(Expression * children, size_t numberOfChildren) : Multiplication() { - for (size_t i = 0; i < numberOfChildren; i++) { - addChildAtIndexInPlace(children[i], i, i); - } - } + static Multiplication Builder(Expression * children, size_t numberOfChildren); + // Simplification Expression privateShallowReduce(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target, bool expand, bool canBeInterrupted); void mergeMultiplicationChildrenInPlace(); diff --git a/poincare/include/poincare/naperian_logarithm.h b/poincare/include/poincare/naperian_logarithm.h index 8e2409729..c880afe5a 100644 --- a/poincare/include/poincare/naperian_logarithm.h +++ b/poincare/include/poincare/naperian_logarithm.h @@ -31,7 +31,7 @@ private: /* ln has a branch cut on ]-inf, 0]: it is then multivalued on this cut. We * followed the convention chosen by the lib c++ of llvm on ]-inf+0i, 0+0i] * (warning: ln takes the other side of the cut values on ]-inf-0i, 0-0i]). */ - return Complex(std::log(c)); + return Complex::Builder(std::log(c)); } Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return ApproximationHelper::Map(this, context, complexFormat, angleUnit,computeOnComplex); @@ -44,15 +44,11 @@ private: class NaperianLogarithm final : public Expression { public: NaperianLogarithm(const NaperianLogarithmNode * n) : Expression(n) {} - static NaperianLogarithm Builder(Expression child) { return NaperianLogarithm(child); } + static NaperianLogarithm Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("ln", 1, &UntypedBuilder); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); -private: - explicit NaperianLogarithm(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/nth_root.h b/poincare/include/poincare/nth_root.h index 2e68e7466..9612cf8a2 100644 --- a/poincare/include/poincare/nth_root.h +++ b/poincare/include/poincare/nth_root.h @@ -35,16 +35,11 @@ private: class NthRoot final : public Expression { public: NthRoot(const NthRootNode * n) : Expression(n) {} - static NthRoot Builder(Expression child0, Expression child1) { return NthRoot(child0, child1); } + static NthRoot Builder(Expression child0, Expression child1); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("root", 2, &UntypedBuilder); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); -private: - NthRoot(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child0); - replaceChildAtIndexInPlace(1, child1); - } }; } diff --git a/poincare/include/poincare/nth_root_layout.h b/poincare/include/poincare/nth_root_layout.h index 5cb5d51e3..1b2e27fc9 100644 --- a/poincare/include/poincare/nth_root_layout.h +++ b/poincare/include/poincare/nth_root_layout.h @@ -14,9 +14,9 @@ public: constexpr static KDCoordinate k_leftRadixHeight = 8; constexpr static KDCoordinate k_leftRadixWidth = 5; - NthRootLayoutNode() : + NthRootLayoutNode(bool hasIndex) : LayoutNode(), - m_hasIndex(false) + m_hasIndex(hasIndex) {} // LayoutNode @@ -50,14 +50,6 @@ private: constexpr static KDCoordinate k_heightMargin = 2; constexpr static KDCoordinate k_widthMargin = 2; constexpr static KDCoordinate k_radixLineThickness = 1; - void setNumberOfChildren(int number) { - assert(number == 1 || number == 2); - if (number == 1) { - m_hasIndex = false; - } else { - m_hasIndex = true; - } - } KDSize adjustedIndexSize(); void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; LayoutNode * radicandLayout() { return childAtIndex(0); } @@ -67,17 +59,9 @@ private: class NthRootLayout final : public Layout { public: - static NthRootLayout Builder(Layout radicand) { return NthRootLayout(radicand); } - static NthRootLayout Builder(Layout radicand, Layout index) { - NthRootLayout n(radicand); - n.addChildAtIndexInPlace(index, 1, 1); - static_cast(n.node())->setNumberOfChildren(2); - return n; - } -private: - NthRootLayout(Layout radicand) : Layout(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, radicand); - } + NthRootLayout() = delete; + static NthRootLayout Builder(Layout child); + static NthRootLayout Builder(Layout radicand, Layout index); }; } diff --git a/poincare/include/poincare/opposite.h b/poincare/include/poincare/opposite.h index 23f1f19df..424486585 100644 --- a/poincare/include/poincare/opposite.h +++ b/poincare/include/poincare/opposite.h @@ -10,7 +10,7 @@ class Opposite; class OppositeNode /*final*/ : public ExpressionNode { public: - template static Complex compute(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Degree) { return Complex(-c); } + template static Complex compute(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Degree) { return Complex::Builder(-c); } // TreeNode @@ -47,16 +47,10 @@ public: class Opposite final : public Expression { public: Opposite(const OppositeNode * n) : Expression(n) {} - static Opposite Builder() { return Opposite(); } - static Opposite Builder(Expression child) { return Opposite(child); } + static Opposite Builder(); + static Opposite Builder(Expression child); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); - -private: - Opposite() : Expression(TreePool::sharedPool()->createTreeNode()) {} - explicit Opposite(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index d4b940bea..ba8b2197e 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -38,14 +38,9 @@ private: class Parenthesis final : public Expression { public: Parenthesis(const ParenthesisNode * n) : Expression(n) {} - static Parenthesis Builder(Expression child) { return Parenthesis(child); } + static Parenthesis Builder(Expression child); // Expression Expression shallowReduce(); - -private: - Parenthesis(Expression exp) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, exp); - } }; } diff --git a/poincare/include/poincare/permute_coefficient.h b/poincare/include/poincare/permute_coefficient.h index 4c241bcf5..45cd8f8ee 100644 --- a/poincare/include/poincare/permute_coefficient.h +++ b/poincare/include/poincare/permute_coefficient.h @@ -41,17 +41,13 @@ private: class PermuteCoefficient final : public Expression { public: PermuteCoefficient(const PermuteCoefficientNode * n) : Expression(n) {} - static PermuteCoefficient Builder(Expression child0, Expression child1) { return PermuteCoefficient(child0, child1); } + static PermuteCoefficient Builder(Expression child0, Expression child1); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("permute", 2, &UntypedBuilder); // Expression Expression shallowReduce(); -private: - PermuteCoefficient(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child0); - replaceChildAtIndexInPlace(1, child1); - } + constexpr static int k_maxNValue = 100; }; diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 8ddc1d6b0..2c30a77ff 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -67,7 +67,7 @@ class Power final : public Expression { friend class Round; public: Power(const PowerNode * n) : Expression(n) {} - static Power Builder(Expression base, Expression exponent) { return Power(base, exponent); } + static Power Builder(Expression base, Expression exponent); Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const; @@ -78,12 +78,6 @@ private: constexpr static int k_maxExactPowerMatrix = 100; constexpr static int k_maxNumberOfTermsInExpandedMultinome = 25; - // Constructors - Power(Expression base, Expression exponent) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, base); - replaceChildAtIndexInPlace(1, exponent); - } - // Simplification Expression denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; diff --git a/poincare/include/poincare/prediction_interval.h b/poincare/include/poincare/prediction_interval.h index 8ff5633f0..f21dc03e8 100644 --- a/poincare/include/poincare/prediction_interval.h +++ b/poincare/include/poincare/prediction_interval.h @@ -37,17 +37,12 @@ private: class PredictionInterval final : public Expression { public: PredictionInterval(const PredictionIntervalNode * n) : Expression(n) {} - static PredictionInterval Builder(Expression child0, Expression child1) { return PredictionInterval(child0, child1); } + static PredictionInterval Builder(Expression child0, Expression child1); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("prediction95", 2, &UntypedBuilder); // Expression Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); -private: - PredictionInterval(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child0); - replaceChildAtIndexInPlace(1, child1); - } }; } diff --git a/poincare/include/poincare/product.h b/poincare/include/poincare/product.h index 02701a19d..e57525551 100644 --- a/poincare/include/poincare/product.h +++ b/poincare/include/poincare/product.h @@ -35,7 +35,7 @@ class Product final : public Expression { friend class ProductNode; public: Product(const ProductNode * n) : Expression(n) {} - static Product Builder(Expression child0, Symbol child1, Expression child2, Expression child3) { return Product(child0, child1, child2, child3); } + static Product Builder(Expression child0, Symbol child1, Expression child2, Expression child3); static Expression UntypedBuilder(Expression children) { if (children.childAtIndex(1).type() != ExpressionNode::Type::Symbol) { // Second parameter must be a Symbol. @@ -44,14 +44,6 @@ public: return Builder(children.childAtIndex(0), children.childAtIndex(1).convert(), children.childAtIndex(2), children.childAtIndex(3)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("product", 4, &UntypedBuilder); -private: - Product(Expression child0, Expression child1, Expression child2, Expression child3) : Expression(TreePool::sharedPool()->createTreeNode()) { - assert(child1.type() == ExpressionNode::Type::Symbol); - replaceChildAtIndexInPlace(0, child0); - replaceChildAtIndexInPlace(1, child1); - replaceChildAtIndexInPlace(2, child2); - replaceChildAtIndexInPlace(3, child3); - } }; } diff --git a/poincare/include/poincare/product_layout.h b/poincare/include/poincare/product_layout.h index 7c2298d95..eeb28ec79 100644 --- a/poincare/include/poincare/product_layout.h +++ b/poincare/include/poincare/product_layout.h @@ -25,16 +25,8 @@ private: class ProductLayout final : public Layout { public: - static ProductLayout Builder(Layout argument, Layout variable, Layout lowerB, Layout upperB) { return ProductLayout(argument, variable, lowerB, upperB); } -private: - ProductLayout(Layout argument, Layout variable, Layout lowerB, Layout upperB) : - Layout(TreePool::sharedPool()->createTreeNode()) - { - replaceChildAtIndexInPlace(0, argument); - replaceChildAtIndexInPlace(1, variable); - replaceChildAtIndexInPlace(2, lowerB); - replaceChildAtIndexInPlace(3, upperB); - } + static ProductLayout Builder(Layout argument, Layout variable, Layout lowerB, Layout upperB); + ProductLayout() = delete; }; } diff --git a/poincare/include/poincare/randint.h b/poincare/include/poincare/randint.h index 5f549a75d..469dc209a 100644 --- a/poincare/include/poincare/randint.h +++ b/poincare/include/poincare/randint.h @@ -41,14 +41,9 @@ class Randint final : public Expression { friend class RandintNode; public: Randint(const RandintNode * n) : Expression(n) {} - static Randint Builder(Expression child0, Expression child1) { return Randint(child0, child1); } + static Randint Builder(Expression child0, Expression child1); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("randint", 2, &UntypedBuilder); -private: - Randint(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child0); - replaceChildAtIndexInPlace(1, child1); - } }; } diff --git a/poincare/include/poincare/random.h b/poincare/include/poincare/random.h index 30cc8dbb9..8b74c5b56 100644 --- a/poincare/include/poincare/random.h +++ b/poincare/include/poincare/random.h @@ -43,13 +43,12 @@ class Random final : public Expression { friend class RandomNode; public: Random(const RandomNode * n) : Expression(n) {} - static Random Builder() { return Random(); } + static Random Builder(); static Expression UntypedBuilder(Expression children) { return Builder(); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("random", 0, &UntypedBuilder); template static T random(); private: - Random() : Expression(TreePool::sharedPool()->createTreeNode()) {} Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); }; diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index d9c3c8612..03e241a28 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -9,11 +9,7 @@ namespace Poincare { class RationalNode final : public NumberNode { public: - RationalNode() : - m_negative(false), - m_numberOfDigitsNumerator(0), - m_numberOfDigitsDenominator(0) {} - virtual void setDigits(const native_uint_t * i, uint8_t numeratorSize, const native_uint_t * j, uint8_t denominatorSize, bool negative); + RationalNode(const native_uint_t * i, uint8_t numeratorSize, const native_uint_t * j, uint8_t denominatorSize, bool negative); Integer signedNumerator() const; Integer unsignedNumerator() const; @@ -22,7 +18,6 @@ public: void setNegative(bool negative) { m_negative = negative; } // TreeNode - void initToMatchSize(size_t goalSize) override; size_t size() const override; #if POINCARE_TREE_LOG virtual void logNodeName(std::ostream & stream) const override { @@ -42,8 +37,8 @@ public: Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Approximation - Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return Complex(templatedApproximate()); } - Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return Complex(templatedApproximate()); } + Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return Complex::Builder(templatedApproximate()); } + Evaluation approximate(DoublePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return Complex::Builder(templatedApproximate()); } template T templatedApproximate() const; // Basic test @@ -74,11 +69,11 @@ class Rational final : public Number { public: /* The constructor build a irreductible fraction */ Rational(const RationalNode * node) : Number(node) {} - Rational(Integer & num, Integer & den); - Rational(const Integer & numerator); - Rational(native_int_t i); - Rational(native_int_t i, native_int_t j); - Rational(const char * iString, const char * jString); + static Rational Builder(Integer & num, Integer & den); + static Rational Builder(const Integer & numerator); + static Rational Builder(native_int_t i); + static Rational Builder(native_int_t i, native_int_t j); + static Rational Builder(const char * iString, const char * jString); // TreeNode RationalNode * node() const { return static_cast(Number::node()); } @@ -111,7 +106,8 @@ public: Expression shallowReduce(); private: - Rational(const native_uint_t * i, uint8_t numeratorSize, const native_uint_t * j, uint8_t denominatorSize, bool negative); + static Rational Builder(const native_uint_t * i, uint8_t numeratorSize, const native_uint_t * j, uint8_t denominatorSize, bool negative); + RationalNode * node() { return static_cast(Number::node()); } /* Simplification */ diff --git a/poincare/include/poincare/real_part.h b/poincare/include/poincare/real_part.h index e9107a486..ad7fba108 100644 --- a/poincare/include/poincare/real_part.h +++ b/poincare/include/poincare/real_part.h @@ -32,7 +32,7 @@ private: Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) override; // Evaluation template static Complex computeOnComplex(const std::complex c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { - return Complex(std::real(c)); + return Complex::Builder(std::real(c)); } Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return ApproximationHelper::Map(this, context, complexFormat, angleUnit,computeOnComplex); @@ -45,15 +45,11 @@ private: class RealPart final : public Expression { public: RealPart(const RealPartNode * n) : Expression(n) {} - static RealPart Builder(Expression child) { return RealPart(child); } + static RealPart Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("re", 1, &UntypedBuilder); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); -private: - explicit RealPart(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/right_parenthesis_layout.h b/poincare/include/poincare/right_parenthesis_layout.h index 342634b7f..779039803 100644 --- a/poincare/include/poincare/right_parenthesis_layout.h +++ b/poincare/include/poincare/right_parenthesis_layout.h @@ -36,9 +36,8 @@ protected: class RightParenthesisLayout final : public Layout { public: - static RightParenthesisLayout Builder() { return RightParenthesisLayout(); } -private: - RightParenthesisLayout() : Layout(TreePool::sharedPool()->createTreeNode()) {} + static RightParenthesisLayout Builder(); + RightParenthesisLayout() = delete; }; } diff --git a/poincare/include/poincare/right_square_bracket_layout.h b/poincare/include/poincare/right_square_bracket_layout.h index 860c15e20..8c7ff1332 100644 --- a/poincare/include/poincare/right_square_bracket_layout.h +++ b/poincare/include/poincare/right_square_bracket_layout.h @@ -29,10 +29,8 @@ protected: class RightSquareBracketLayout final : public Layout { public: - static RightSquareBracketLayout Builder() { return RightSquareBracketLayout(); } - -private: - RightSquareBracketLayout() : Layout(TreePool::sharedPool()->createTreeNode()) {} + static RightSquareBracketLayout Builder(); + RightSquareBracketLayout() = delete; }; } diff --git a/poincare/include/poincare/round.h b/poincare/include/poincare/round.h index a219cc775..d397217cc 100644 --- a/poincare/include/poincare/round.h +++ b/poincare/include/poincare/round.h @@ -38,16 +38,11 @@ private: class Round final : public Expression { public: Round(const RoundNode * n) : Expression(n) {} - static Round Builder(Expression child0, Expression child1) { return Round(child0, child1); } + static Round Builder(Expression child0, Expression child1); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("round", 2, &UntypedBuilder); Expression shallowReduce(); -private: - Round(Expression child0, Expression child1) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child0); - replaceChildAtIndexInPlace(1, child1); - } }; } diff --git a/poincare/include/poincare/sign_function.h b/poincare/include/poincare/sign_function.h index 9bb83d47e..3205d8d7b 100644 --- a/poincare/include/poincare/sign_function.h +++ b/poincare/include/poincare/sign_function.h @@ -45,15 +45,11 @@ private: class SignFunction final : public Expression { public: SignFunction(const SignFunctionNode * n) : Expression(n) {} - static SignFunction Builder(Expression child) { return SignFunction(child); } + static SignFunction Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("sign", 1, &UntypedBuilder); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); -private: - explicit SignFunction(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index 393ae365c..f53614b9e 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -48,15 +48,11 @@ private: class Sine final : public Expression { public: Sine(const SineNode * n) : Expression(n) {} - static Sine Builder(Expression child) { return Sine(child); } + static Sine Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("sin", 1, &UntypedBuilder); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); -private: - explicit Sine(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/square_root.h b/poincare/include/poincare/square_root.h index 4a1401c69..a47c17adb 100644 --- a/poincare/include/poincare/square_root.h +++ b/poincare/include/poincare/square_root.h @@ -41,16 +41,13 @@ private: class SquareRoot final : public Expression { public: SquareRoot(const SquareRootNode * n) : Expression(n) {} - static SquareRoot Builder(Expression child) { return SquareRoot(child); } + static SquareRoot Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static_assert('\x91' == Ion::Charset::Root, "Charset error"); static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("\x91", 1, &UntypedBuilder); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: - explicit SquareRoot(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } static const char k_name[2]; }; diff --git a/poincare/include/poincare/store.h b/poincare/include/poincare/store.h index 0d780cd75..e9db5570b 100644 --- a/poincare/include/poincare/store.h +++ b/poincare/include/poincare/store.h @@ -40,7 +40,7 @@ class Store final : public Expression { friend class StoreNode; public: Store(const StoreNode * n) : Expression(n) {} - static Store Builder(Expression value, SymbolAbstract symbol) { return Store(value, symbol); } + static Store Builder(Expression value, SymbolAbstract symbol); // Store const SymbolAbstract symbol() const { @@ -54,12 +54,8 @@ public: // Expression Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); -private: - Store(Expression value, SymbolAbstract symbol) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, value); - replaceChildAtIndexInPlace(1, symbol); - } +private: Expression storeValueForSymbol(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; StoreNode * node() const { return static_cast(Expression::node()); } }; diff --git a/poincare/include/poincare/subtraction.h b/poincare/include/poincare/subtraction.h index faae9c66b..3fd149bcc 100644 --- a/poincare/include/poincare/subtraction.h +++ b/poincare/include/poincare/subtraction.h @@ -25,7 +25,7 @@ public: int polynomialDegree(Context & context, const char * symbolName) const override; // Approximation - template static Complex compute(const std::complex c, const std::complex d, Preferences::ComplexFormat complexFormat) { return Complex(c - d); } + template static Complex compute(const std::complex c, const std::complex d, Preferences::ComplexFormat complexFormat) { return Complex::Builder(c - d); } Evaluation approximate(SinglePrecision p, Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return ApproximationHelper::MapReduce(this, context, complexFormat, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } @@ -55,19 +55,12 @@ private: class Subtraction final : public Expression { public: Subtraction(const SubtractionNode * n) : Expression(n) {} - static Subtraction Builder() { return Subtraction(); } - static Subtraction Builder(Expression child0, Expression child1) { - Subtraction s = Subtraction::Builder(); - s.replaceChildAtIndexInPlace(0, child0); - s.replaceChildAtIndexInPlace(1, child1); - return s; - } + static Subtraction Builder(); + static Subtraction Builder(Expression child0, Expression child1); // Expression Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); -private: - Subtraction() : Expression(TreePool::sharedPool()->createTreeNode()) {} }; } diff --git a/poincare/include/poincare/sum.h b/poincare/include/poincare/sum.h index 515290d56..0d9cc6da2 100644 --- a/poincare/include/poincare/sum.h +++ b/poincare/include/poincare/sum.h @@ -35,7 +35,7 @@ class Sum final : public Expression { friend class SumNode; public: Sum(const SumNode * n) : Expression(n) {} - static Sum Builder(Expression child0, Symbol child1, Expression child2, Expression child3) { return Sum(child0, child1, child2, child3); } + static Sum Builder(Expression child0, Symbol child1, Expression child2, Expression child3); static Expression UntypedBuilder(Expression children) { if (children.childAtIndex(1).type() != ExpressionNode::Type::Symbol) { // Second parameter must be a Symbol. @@ -44,14 +44,6 @@ public: return Builder(children.childAtIndex(0), children.childAtIndex(1).convert(), children.childAtIndex(2), children.childAtIndex(3)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("sum", 4, &UntypedBuilder); -private: - Sum(Expression child0, Expression child1, Expression child2, Expression child3) : Expression(TreePool::sharedPool()->createTreeNode()) { - assert(child1.type() == ExpressionNode::Type::Symbol); - replaceChildAtIndexInPlace(0, child0); - replaceChildAtIndexInPlace(1, child1); - replaceChildAtIndexInPlace(2, child2); - replaceChildAtIndexInPlace(3, child3); - } }; } diff --git a/poincare/include/poincare/sum_layout.h b/poincare/include/poincare/sum_layout.h index a21b6fd38..b7999571e 100644 --- a/poincare/include/poincare/sum_layout.h +++ b/poincare/include/poincare/sum_layout.h @@ -23,16 +23,8 @@ private: class SumLayout final : public Layout { public: - static SumLayout Builder(Layout argument, Layout variable, Layout lowerB, Layout upperB) { return SumLayout(argument, variable, lowerB, upperB); } -private: - SumLayout(Layout argument, Layout variable, Layout lowerB, Layout upperB) : - Layout(TreePool::sharedPool()->createTreeNode()) - { - replaceChildAtIndexInPlace(0, argument); - replaceChildAtIndexInPlace(1, variable); - replaceChildAtIndexInPlace(2, lowerB); - replaceChildAtIndexInPlace(3, upperB); - } + static SumLayout Builder(Layout argument, Layout variable, Layout lowerB, Layout upperB); + SumLayout() = delete; }; } diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index e1fc8bf19..776498cac 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -7,6 +7,8 @@ namespace Poincare { class SymbolNode final : public SymbolAbstractNode { public: + SymbolNode(const char * newName, int length); + const char * name() const override { return m_name; } // TreeNode @@ -61,13 +63,13 @@ public: * characters but events as 'end of text', 'backspace'... */ UnknownX = 1, }; - Symbol(const char * name, int length); - Symbol(char name); Symbol(const SymbolNode * node) : SymbolAbstract(node) {} - static Symbol Ans() { return Symbol(k_ans, k_ansLength); } + static Symbol Builder(const char * name, int length); + static Symbol Builder(char name); + static Symbol Ans() { return Symbol::Builder(k_ans, k_ansLength); } static Expression UntypedBuilder(const char * name, size_t length, Context * context) { // create an expression only if it is not in the context or defined as a symbol - Symbol s(name, length); + Symbol s = Symbol::Builder(name, length); if (SymbolAbstract::ValidInContext(s, context)) { return s; } diff --git a/poincare/include/poincare/symbol_abstract.h b/poincare/include/poincare/symbol_abstract.h index 3de47c6c5..c993ef2ad 100644 --- a/poincare/include/poincare/symbol_abstract.h +++ b/poincare/include/poincare/symbol_abstract.h @@ -27,9 +27,7 @@ class SymbolAbstractNode : public ExpressionNode { friend class Store; public: virtual const char * name() const = 0; - void setName(const char * newName, int length); size_t size() const override; - void initToMatchSize(size_t goalSize) override; // ExpressionNode int simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const override; diff --git a/poincare/include/poincare/tangent.h b/poincare/include/poincare/tangent.h index dc271379a..b37a99d35 100644 --- a/poincare/include/poincare/tangent.h +++ b/poincare/include/poincare/tangent.h @@ -46,15 +46,11 @@ private: class Tangent final : public Expression { public: Tangent(const TangentNode * n) : Expression(n) {} - static Tangent Builder(Expression child) { return Tangent(child); } + static Tangent Builder(Expression child); static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("tan", 1, &UntypedBuilder); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); -private: - explicit Tangent(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, child); - } }; } diff --git a/poincare/include/poincare/tree_handle.h b/poincare/include/poincare/tree_handle.h index 87b6ade6d..abd3008d6 100644 --- a/poincare/include/poincare/tree_handle.h +++ b/poincare/include/poincare/tree_handle.h @@ -104,6 +104,9 @@ protected: /* Constructor */ TreeHandle(const TreeNode * node); TreeHandle(int nodeIndentifier = TreeNode::NoNodeIdentifier) : m_identifier(nodeIndentifier) {} + // WARNING: if the children table is the result of a cast, the object downcasted has to be the same size as a TreeHandle. + static TreeHandle BuildWithBasicChildren(TreeNode * node, TreeHandle * children = nullptr, int numberOfChildren = 0); + void setIdentifierAndRetain(int newId); void setTo(const TreeHandle & tr); diff --git a/poincare/include/poincare/tree_node.h b/poincare/include/poincare/tree_node.h index 4a5393b4f..26b9efb57 100644 --- a/poincare/include/poincare/tree_node.h +++ b/poincare/include/poincare/tree_node.h @@ -42,7 +42,6 @@ public: static constexpr int NoNodeIdentifier = -1; // Constructor and destructor - virtual void initToMatchSize(size_t goalSize) { assert(false); } virtual ~TreeNode() {} // Attributes diff --git a/poincare/include/poincare/tree_pool.h b/poincare/include/poincare/tree_pool.h index 3399f2f18..78c8a7342 100644 --- a/poincare/include/poincare/tree_pool.h +++ b/poincare/include/poincare/tree_pool.h @@ -31,8 +31,8 @@ public: return m_nodeForIdentifier[identifier]; } - template - T * createTreeNode(size_t size = sizeof(T)); + // Pool memory + void * alloc(size_t size); void move(TreeNode * destination, TreeNode * source, int realNumberOfSourceChildren); void moveChildren(TreeNode * destination, TreeNode * sourceParent); void removeChildren(TreeNode * node, int nodeNumberOfChildren); @@ -54,7 +54,6 @@ private: static TreePool * SharedStaticPool; // TreeNode - void addGhostChildrenAndRename(TreeNode * node); void discardTreeNode(TreeNode * node); void registerNode(TreeNode * node); void unregisterNode(TreeNode * node) { @@ -106,7 +105,6 @@ private: RootNodes roots() { return RootNodes(first()); } // Pool memory - void * alloc(size_t size); void dealloc(TreeNode * ptr, size_t size); void moveNodes(TreeNode * destination, TreeNode * source, size_t moveLength); diff --git a/poincare/include/poincare/undefined.h b/poincare/include/poincare/undefined.h index 1d76553bb..8891fe236 100644 --- a/poincare/include/poincare/undefined.h +++ b/poincare/include/poincare/undefined.h @@ -41,8 +41,8 @@ protected: class Undefined final : public Number { public: - Undefined() : Number(TreePool::sharedPool()->createTreeNode()) {} Undefined(const UndefinedNode * n) : Number(n) {} + static Undefined Builder(); static const char * Name() { return "undef"; } diff --git a/poincare/include/poincare/unreal.h b/poincare/include/poincare/unreal.h index 23e0f78b2..232f3607d 100644 --- a/poincare/include/poincare/unreal.h +++ b/poincare/include/poincare/unreal.h @@ -39,7 +39,8 @@ private: class Unreal final : public Number { public: - Unreal() : Number(TreePool::sharedPool()->createTreeNode()) {} + static Unreal Builder(); + Unreal() = delete; static const char * Name() { return "unreal"; } diff --git a/poincare/include/poincare/vertical_offset_layout.h b/poincare/include/poincare/vertical_offset_layout.h index 8ac17b24f..94162aa44 100644 --- a/poincare/include/poincare/vertical_offset_layout.h +++ b/poincare/include/poincare/vertical_offset_layout.h @@ -20,7 +20,6 @@ public: // VerticalOffsetLayoutNode Type type() const { return m_type; } - void setType(Type type) { m_type = type; } // LayoutNode void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; @@ -59,15 +58,8 @@ private: class VerticalOffsetLayout final : public Layout { public: - static VerticalOffsetLayout Builder(Layout l, VerticalOffsetLayoutNode::Type type) { return VerticalOffsetLayout(l, type); } - -private: - VerticalOffsetLayout(Layout l, VerticalOffsetLayoutNode::Type type) : - Layout(TreePool::sharedPool()->createTreeNode()) - { - static_cast(node())->setType(type); - replaceChildAtIndexInPlace(0,l); - } + static VerticalOffsetLayout Builder(Layout l, VerticalOffsetLayoutNode::Type type); + VerticalOffsetLayout() = delete; }; } diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index a057ae5f0..2999aef0f 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -31,6 +31,13 @@ Expression AbsoluteValueNode::shallowReduce(Context & context, Preferences::Comp return AbsoluteValue(this).shallowReduce(context, complexFormat, angleUnit, target); } +AbsoluteValue AbsoluteValue::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(AbsoluteValueNode)); + AbsoluteValueNode * node = new (bufferNode) AbsoluteValueNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); +} + Expression AbsoluteValue::setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { assert(s == ExpressionNode::Sign::Positive); return *this; @@ -62,7 +69,7 @@ Expression AbsoluteValue::shallowReduce(Context & context, Preferences::ComplexF } else if (!std::isnan(app) && ((c.isNumber() && app < 0.0f) || app <= -Expression::Epsilon())) { // abs(a) = -a with a < 0 (same comment as above to check that a < 0) - Multiplication m = Multiplication::Builder(Rational(-1), c); + Multiplication m = Multiplication::Builder(Rational::Builder(-1), c); replaceWithInPlace(m); return m.shallowReduce(context, complexFormat, angleUnit, target); } diff --git a/poincare/src/absolute_value_layout.cpp b/poincare/src/absolute_value_layout.cpp new file mode 100644 index 000000000..0d445c654 --- /dev/null +++ b/poincare/src/absolute_value_layout.cpp @@ -0,0 +1,12 @@ +#include + +namespace Poincare { + +AbsoluteValueLayout AbsoluteValueLayout::Builder(Layout child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(AbsoluteValueLayoutNode)); + AbsoluteValueLayoutNode * node = new (bufferNode) AbsoluteValueLayoutNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); +} + +} diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 73814db1e..80361ed50 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -65,7 +65,7 @@ const Number Addition::NumeralFactor(const Expression & e) { Number result = e.childAtIndex(0).convert(); return result; } - return Rational(1); + return Rational::Builder(1); } int Addition::getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const { @@ -74,7 +74,7 @@ int Addition::getPolynomialCoefficients(Context & context, const char * symbolNa return -1; } for (int k = 0; k < deg+1; k++) { - coefficients[k] = Addition(); + coefficients[k] = Addition::Builder(); } Expression intermediateCoefficients[Expression::k_maxNumberOfPolynomialCoefficients]; for (int i = 0; i < numberOfChildren(); i++) { @@ -87,6 +87,21 @@ int Addition::getPolynomialCoefficients(Context & context, const char * symbolNa return deg; } +Addition Addition::Builder() { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(AdditionNode)); + AdditionNode * node = new (bufferNode) AdditionNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); +} + +Addition Addition::Builder(Expression * children, size_t numberOfChildren) { + Addition a = Addition::Builder(); + for (int i = 0; i < numberOfChildren; i++) { + a.addChildAtIndexInPlace(children[i], i, i); + } + return a; +} + Expression Addition::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { /* Beautifying AdditionNode essentially consists in adding Subtractions if * needed. @@ -182,7 +197,7 @@ Expression Addition::shallowReduce(Context & context, Preferences::ComplexFormat int on = currentMatrix->numberOfRows(); int om = currentMatrix->numberOfColumns(); if (on != n || om != m) { - return replaceWith(new Undefined(), true); + return replaceWith(new Undefined::Builder(), true); } // Dispatch the current matrix children in the created additions matrix for (int j = 0; j < n*m; j++) { @@ -340,7 +355,7 @@ Expression Addition::factorizeOnCommonDenominator(Context & context, Preferences // We want to turn (a/b+c/d+e/b) into (a*d+b*c+e*d)/(b*d) // Step 1: We want to compute the common denominator, b*d - Multiplication commonDenominator; + Multiplication commonDenominator = Multiplication::Builder(); for (int i = 0; i < numberOfChildren(); i++) { Expression currentDenominator = childAtIndex(i).denominator(context, complexFormat, angleUnit); if (!currentDenominator.isUninitialized()) { @@ -363,7 +378,7 @@ Expression Addition::factorizeOnCommonDenominator(Context & context, Preferences } // Step 3: Add the denominator - Power inverseDenominator = Power::Builder(commonDenominator, Rational(-1)); + Power inverseDenominator = Power::Builder(commonDenominator, Rational::Builder(-1)); Multiplication result = Multiplication::Builder(numerator, inverseDenominator); // Step 4: Simplify the numerator diff --git a/poincare/src/approximation_helper.cpp b/poincare/src/approximation_helper.cpp index e77e39c27..bb4935d00 100644 --- a/poincare/src/approximation_helper.cpp +++ b/poincare/src/approximation_helper.cpp @@ -34,7 +34,7 @@ template Evaluation ApproximationHelper::Map(const ExpressionNode } else { assert(input.type() == EvaluationNode::Type::MatrixComplex); MatrixComplex m = static_cast &>(input); - MatrixComplex result; + MatrixComplex result = MatrixComplex::Builder(); for (int i = 0; i < m.numberOfChildren(); i++) { result.addChildAtIndexInPlace(compute(m.complexAtIndex(i), complexFormat, angleUnit), i, i); } @@ -71,7 +71,7 @@ template Evaluation ApproximationHelper::MapReduce(const Expressi } template MatrixComplex ApproximationHelper::ElementWiseOnMatrixComplexAndComplex(const MatrixComplex m, const std::complex c, Poincare::Preferences::ComplexFormat complexFormat, ComplexAndComplexReduction computeOnComplexes) { - MatrixComplex matrix; + MatrixComplex matrix = MatrixComplex::Builder(); for (int i = 0; i < m.numberOfChildren(); i++) { matrix.addChildAtIndexInPlace(computeOnComplexes(m.complexAtIndex(i), c, complexFormat), i, i); } @@ -83,7 +83,7 @@ template MatrixComplex ApproximationHelper::ElementWiseOnComplexM if (m.numberOfRows() != n.numberOfRows() || m.numberOfColumns() != n.numberOfColumns()) { return MatrixComplex::Undefined(); } - MatrixComplex matrix; + MatrixComplex matrix = MatrixComplex::Builder(); for (int i = 0; i < m.numberOfChildren(); i++) { matrix.addChildAtIndexInPlace(computeOnComplexes(m.complexAtIndex(i), n.complexAtIndex(i), complexFormat), i, i); } diff --git a/poincare/src/arc_cosine.cpp b/poincare/src/arc_cosine.cpp index 100e52963..f32d5f6c5 100644 --- a/poincare/src/arc_cosine.cpp +++ b/poincare/src/arc_cosine.cpp @@ -45,7 +45,14 @@ Complex ArcCosineNode::computeOnComplex(const std::complex c, Preferences: } } result = Trigonometry::RoundToMeaningfulDigits(result, c); - return Complex(Trigonometry::ConvertRadianToAngleUnit(result, angleUnit)); + return Complex::Builder(Trigonometry::ConvertRadianToAngleUnit(result, angleUnit)); +} + +ArcCosine ArcCosine::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(ArcCosineNode)); + ArcCosineNode * node = new (bufferNode) ArcCosineNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); } Expression ArcCosine::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { diff --git a/poincare/src/arc_sine.cpp b/poincare/src/arc_sine.cpp index 4493f0e2b..450c8df5f 100644 --- a/poincare/src/arc_sine.cpp +++ b/poincare/src/arc_sine.cpp @@ -45,7 +45,14 @@ Complex ArcSineNode::computeOnComplex(const std::complex c, Preferences::C } } result = Trigonometry::RoundToMeaningfulDigits(result, c); - return Complex(Trigonometry::ConvertRadianToAngleUnit(result, angleUnit)); + return Complex::Builder(Trigonometry::ConvertRadianToAngleUnit(result, angleUnit)); +} + +ArcSine ArcSine::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(ArcSineNode)); + ArcSineNode * node = new (bufferNode) ArcSineNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); } Expression ArcSine::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { diff --git a/poincare/src/arc_tangent.cpp b/poincare/src/arc_tangent.cpp index 917b2bc55..71fae7d4c 100644 --- a/poincare/src/arc_tangent.cpp +++ b/poincare/src/arc_tangent.cpp @@ -41,13 +41,20 @@ Complex ArcTangentNode::computeOnComplex(const std::complex c, Preferences } } result = Trigonometry::RoundToMeaningfulDigits(result, c); - return Complex(Trigonometry::ConvertRadianToAngleUnit(result, angleUnit)); + return Complex::Builder(Trigonometry::ConvertRadianToAngleUnit(result, angleUnit)); } Expression ArcTangentNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { return ArcTangent(this).shallowReduce(context, complexFormat, angleUnit, target); } +ArcTangent ArcTangent::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(ArcTangentNode)); + ArcTangentNode * node = new (bufferNode) ArcTangentNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); +} + Expression ArcTangent::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { Expression e = Expression::defaultShallowReduce(); diff --git a/poincare/src/binomial_coefficient.cpp b/poincare/src/binomial_coefficient.cpp index 72661df33..5a039966d 100644 --- a/poincare/src/binomial_coefficient.cpp +++ b/poincare/src/binomial_coefficient.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -34,7 +35,7 @@ Complex BinomialCoefficientNode::templatedApproximate(Context& context, Prefe Evaluation kInput = childAtIndex(1)->approximate(T(), context, complexFormat, angleUnit); T n = nInput.toScalar(); T k = kInput.toScalar(); - return Complex(compute(k, n)); + return Complex::Builder(compute(k, n)); } template @@ -53,6 +54,13 @@ T BinomialCoefficientNode::compute(T k, T n) { return std::round(result); } +BinomialCoefficient BinomialCoefficient::Builder(Expression child0, Expression child1) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(BinomialCoefficientNode)); + BinomialCoefficientNode * node = new (bufferNode) BinomialCoefficientNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); + return static_cast(h); +} + Expression BinomialCoefficient::shallowReduce() { { Expression e = Expression::defaultShallowReduce(); @@ -64,13 +72,13 @@ Expression BinomialCoefficient::shallowReduce() { Expression c1 = childAtIndex(1); #if MATRIX_EXACT_REDUCING if (c0.type() == ExpressionNode::Type::Matrix || c1.type() == ExpressionNode::Type::Matrix) { - return Undefined(); + return Undefined::Builder(); } #endif if (c0.type() == ExpressionNode::Type::Rational) { Rational r0 = static_cast(c0); if (!r0.integerDenominator().isOne() || r0.isNegative()) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } @@ -78,7 +86,7 @@ Expression BinomialCoefficient::shallowReduce() { if (c1.type() == ExpressionNode::Type::Rational) { Rational r1 = static_cast(c1); if (!r1.integerDenominator().isOne() || r1.isNegative()) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } @@ -92,7 +100,7 @@ Expression BinomialCoefficient::shallowReduce() { Integer n = r0.signedIntegerNumerator(); Integer k = r1.signedIntegerNumerator(); if (n.isLowerThan(k)) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } @@ -101,21 +109,20 @@ Expression BinomialCoefficient::shallowReduce() { if (Integer(k_maxNValue).isLowerThan(n)) { return *this; } - Rational result(1); + Rational result = Rational::Builder(1); Integer kBis = Integer::Subtraction(n, k); k = kBis.isLowerThan(k) ? kBis : k; int clippedK = k.extractedInt(); // Authorized because k < n < k_maxNValue for (int i = 0; i < clippedK; i++) { Integer nMinusI = Integer::Subtraction(n, Integer(i)); Integer kMinusI = Integer::Subtraction(k, Integer(i)); - Rational factor = Rational(nMinusI, kMinusI); + Rational factor = Rational::Builder(nMinusI, kMinusI); result = Rational::Multiplication(result, factor); } // As we cap the n < k_maxNValue = 300, result < binomial(300, 150) ~2^89 assert(!result.numeratorOrDenominatorIsInfinity()); - Expression rationalResult = Rational(result); - replaceWithInPlace(rationalResult); - return rationalResult; + replaceWithInPlace(result); + return result; } template double BinomialCoefficientNode::compute(double k, double n); diff --git a/poincare/src/binomial_coefficient_layout.cpp b/poincare/src/binomial_coefficient_layout.cpp index 97872cc55..dc7b95788 100644 --- a/poincare/src/binomial_coefficient_layout.cpp +++ b/poincare/src/binomial_coefficient_layout.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -106,4 +107,11 @@ void BinomialCoefficientLayoutNode::render(KDContext * ctx, KDPoint p, KDColor e RightParenthesisLayoutNode::RenderWithChildHeight(childHeight, ctx, p.translatedBy(KDPoint(rightParenthesisPointX, 0)), expressionColor, backgroundColor); } +BinomialCoefficientLayout BinomialCoefficientLayout::Builder(Layout n, Layout k) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(BinomialCoefficientLayoutNode)); + BinomialCoefficientLayoutNode * node = new (bufferNode) BinomialCoefficientLayoutNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(n,k).array(), 2); + return static_cast(h); +} + } diff --git a/poincare/src/ceiling.cpp b/poincare/src/ceiling.cpp index cd8ddf05c..9742abffe 100644 --- a/poincare/src/ceiling.cpp +++ b/poincare/src/ceiling.cpp @@ -28,13 +28,20 @@ Complex CeilingNode::computeOnComplex(const std::complex c, Preferences::C if (c.imag() != 0) { return Complex::Undefined(); } - return Complex(std::ceil(c.real())); + return Complex::Builder(std::ceil(c.real())); } Expression CeilingNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { return Ceiling(this).shallowReduce(); } +Ceiling Ceiling::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(CeilingNode)); + CeilingNode * node = new (bufferNode) CeilingNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); +} + Expression Ceiling::shallowReduce() { { Expression e = Expression::defaultShallowReduce(); @@ -52,10 +59,10 @@ Expression Ceiling::shallowReduce() { Constant s = static_cast(c); Expression result; if (s.isPi()) { - result = Rational(4); + result = Rational::Builder(4); } if (s.isExponential()) { - result = Rational(3); + result = Rational::Builder(3); } if (!result.isUninitialized()) { replaceWithInPlace(result); @@ -70,7 +77,7 @@ Expression Ceiling::shallowReduce() { IntegerDivision div = Integer::Division(r.signedIntegerNumerator(), r.integerDenominator()); assert(!div.remainder.isOverflow()); if (div.remainder.isZero()) { - Expression result = Rational(div.quotient); + Expression result = Rational::Builder(div.quotient); replaceWithInPlace(result); return result; } @@ -78,7 +85,7 @@ Expression Ceiling::shallowReduce() { if (result.isOverflow()) { return *this; } - Expression rationalResult = Rational(result); + Expression rationalResult = Rational::Builder(result); replaceWithInPlace(rationalResult); return rationalResult; } diff --git a/poincare/src/ceiling_layout.cpp b/poincare/src/ceiling_layout.cpp index 3a7c5aff3..0c2c679f7 100644 --- a/poincare/src/ceiling_layout.cpp +++ b/poincare/src/ceiling_layout.cpp @@ -2,4 +2,11 @@ namespace Poincare { +CeilingLayout CeilingLayout::Builder(Layout child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(CeilingLayoutNode)); + CeilingLayoutNode * node = new (bufferNode) CeilingLayoutNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); +} + } diff --git a/poincare/src/char_layout.cpp b/poincare/src/char_layout.cpp index b49a0d0b9..d303a5b89 100644 --- a/poincare/src/char_layout.cpp +++ b/poincare/src/char_layout.cpp @@ -96,11 +96,11 @@ bool CharLayoutNode::isMultiplicationChar() const { || m_char == Ion::Charset::MiddleDot; } -CharLayout::CharLayout(char c, const KDFont * font) : - Layout(TreePool::sharedPool()->createTreeNode()) -{ - node()->setChar(c); - node()->setFont(font); +CharLayout CharLayout::Builder(char c, const KDFont * font) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(CharLayoutNode)); + CharLayoutNode * node = new (bufferNode) CharLayoutNode(c, font); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); } } diff --git a/poincare/src/complex.cpp b/poincare/src/complex.cpp index 5935fddce..7ea64fee8 100644 --- a/poincare/src/complex.cpp +++ b/poincare/src/complex.cpp @@ -22,12 +22,13 @@ extern "C" { namespace Poincare { template -void ComplexNode::setComplex(std::complex c) { +ComplexNode::ComplexNode(std::complex c) : + EvaluationNode(), + std::complex(c.real(), c.imag()) +{ if (!std::isnan(c.imag()) && c.imag() != 0.0) { Expression::SetEncounteredComplex(true); } - this->real(c.real()); - this->imag(c.imag()); if (this->real() == -0) { this->real(0); } @@ -47,7 +48,7 @@ T ComplexNode::toScalar() const { template Expression ComplexNode::complexToExpression(Preferences::ComplexFormat complexFormat) const { if (complexFormat == Preferences::ComplexFormat::Real && Expression::EncounteredComplex()) { - return Unreal(); + return Unreal::Builder(); } T ra, tb; if (complexFormat == Preferences::ComplexFormat::Polar) { @@ -67,17 +68,18 @@ Expression ComplexNode::complexToExpression(Preferences::ComplexFormat comple } template -Complex::Complex(std::complex c) : - Evaluation(TreePool::sharedPool()->createTreeNode>()) -{ - node()->setComplex(c); +Complex Complex::Builder(std::complex c) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(ComplexNode)); + ComplexNode * node = new (bufferNode) ComplexNode(c); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast &>(h); } template class ComplexNode; template class ComplexNode; -template Complex::Complex(float a, float b); -template Complex::Complex(double a, double b); -template Complex::Complex(std::complex c); -template Complex::Complex(std::complex c); +template Complex Complex::Builder(float a, float b); +template Complex Complex::Builder(double a, double b); +template Complex Complex::Builder(std::complex c); +template Complex Complex::Builder(std::complex c); } diff --git a/poincare/src/complex_argument.cpp b/poincare/src/complex_argument.cpp index 679ec064b..9ac1de038 100644 --- a/poincare/src/complex_argument.cpp +++ b/poincare/src/complex_argument.cpp @@ -30,7 +30,14 @@ Expression ComplexArgumentNode::shallowReduce(Context & context, Preferences::Co template Complex ComplexArgumentNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { - return Complex(std::arg(c)); + return Complex::Builder(std::arg(c)); +} + +ComplexArgument ComplexArgument::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(ComplexArgumentNode)); + ComplexArgumentNode * node = new (bufferNode) ComplexArgumentNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); } Expression ComplexArgument::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { @@ -51,18 +58,18 @@ Expression ComplexArgument::shallowReduce(Context & context, Preferences::Comple float app = c.node()->approximate(float(), context, complexFormat, angleUnit).toScalar(); if (!std::isnan(app) && app >= Expression::Epsilon()) { // arg(x) = 0 if x > 0 - Expression result = Rational(0); + Expression result = Rational::Builder(0); replaceWithInPlace(result); return result; } else if (!std::isnan(app) && app <= -Expression::Epsilon()) { // arg(x) = Pi if x < 0 - Expression result = Constant(Ion::Charset::SmallPi); + Expression result = Constant::Builder(Ion::Charset::SmallPi); replaceWithInPlace(result); return result; } } if (real || c.type() == ExpressionNode::Type::ComplexCartesian) { - ComplexCartesian complexChild = real ? ComplexCartesian::Builder(c, Rational(0)) : static_cast(c); + ComplexCartesian complexChild = real ? ComplexCartesian::Builder(c, Rational::Builder(0)) : static_cast(c); Expression childArg = complexChild.argument(context, complexFormat, angleUnit, target); replaceWithInPlace(childArg); return childArg.shallowReduce(context, complexFormat, angleUnit, target); diff --git a/poincare/src/complex_cartesian.cpp b/poincare/src/complex_cartesian.cpp index 65ea33af3..ccf3d88f1 100644 --- a/poincare/src/complex_cartesian.cpp +++ b/poincare/src/complex_cartesian.cpp @@ -49,7 +49,21 @@ Complex ComplexCartesianNode::templatedApproximate(Context& context, Preferen } assert(a.imag() == 0.0 || std::isnan(a.imag())); assert(b.imag() == 0.0 || std::isnan(b.imag())); - return Complex(a.real(), b.real()); + return Complex::Builder(a.real(), b.real()); +} + +ComplexCartesian ComplexCartesian::Builder() { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(ComplexCartesianNode)); + ComplexCartesianNode * node = new (bufferNode) ComplexCartesianNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); +} + +ComplexCartesian ComplexCartesian::Builder(Expression real, Expression imag) { + ComplexCartesian c = ComplexCartesian::Builder(); + c.replaceChildAtIndexInPlace(0, real); + c.replaceChildAtIndexInPlace(1, imag); + return c; } Expression ComplexCartesian::shallowReduce() { @@ -80,7 +94,7 @@ Expression ComplexCartesian::shallowBeautify(Context & context, Preferences::Com void ComplexCartesian::factorAndArgumentOfFunction(Expression e, ExpressionNode::Type searchedType, Expression * factor, Expression * argument, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { if (e.type() == searchedType) { - *factor = Rational(1); + *factor = Rational::Builder(1); *argument = e.childAtIndex(0); return; } @@ -106,12 +120,12 @@ Expression ComplexCartesian::squareNorm(Context & context, Preferences::ComplexF factorAndArgumentOfFunction(a, ExpressionNode::Type::Cosine, &aFactor, &aArgument, context, complexFormat, angleUnit, target); factorAndArgumentOfFunction(b, ExpressionNode::Type::Sine, &bFactor, &bArgument, context, complexFormat, angleUnit, target); if (!aFactor.isUninitialized() && !aArgument.isUninitialized() && !bFactor.isUninitialized() && !bArgument.isUninitialized() && aFactor.isIdenticalTo(bFactor) && aArgument.isIdenticalTo(bArgument)) { - Power result = Power::Builder(aFactor, Rational(2)); + Power result = Power::Builder(aFactor, Rational::Builder(2)); aFactor.shallowReduce(context, complexFormat, angleUnit, target); return result; } - Expression a2 = Power::Builder(a, Rational(2)); - Expression b2 = Power::Builder(b, Rational(2)); + Expression a2 = Power::Builder(a, Rational::Builder(2)); + Expression b2 = Power::Builder(b, Rational::Builder(2)); Addition add = Addition::Builder(a2, b2); a2.shallowReduce(context, complexFormat, angleUnit, target); b2.shallowReduce(context, complexFormat, angleUnit, target); @@ -152,7 +166,7 @@ Expression ComplexCartesian::argument(Context & context, Preferences::ComplexFor } // Then, compute sign(b) * Pi/2 - arctan(a/b) Expression signb = SignFunction::Builder(b); - Expression signbPi2 = Multiplication::Builder(Rational(1,2), signb, Constant(Ion::Charset::SmallPi)); + Expression signbPi2 = Multiplication::Builder(Rational::Builder(1,2), signb, Constant::Builder(Ion::Charset::SmallPi)); signb.shallowReduce(context, complexFormat, angleUnit, target); Expression sub = Subtraction::Builder(signbPi2, arcTangent); signbPi2.shallowReduce(context, complexFormat, angleUnit, target); @@ -161,9 +175,9 @@ Expression ComplexCartesian::argument(Context & context, Preferences::ComplexFor } else { // if b == 0, argument = (1-sign(a))*Pi/2 Expression signa = SignFunction::Builder(a).shallowReduce(context, complexFormat, angleUnit, target); - Subtraction sub = Subtraction::Builder(Rational(1), signa); + Subtraction sub = Subtraction::Builder(Rational::Builder(1), signa); signa.shallowReduce(context, complexFormat, angleUnit, target); - Multiplication mul = Multiplication::Builder(Rational(1,2), Constant(Ion::Charset::SmallPi), sub); + Multiplication mul = Multiplication::Builder(Rational::Builder(1,2), Constant::Builder(Ion::Charset::SmallPi), sub); sub.shallowReduce(context, complexFormat, angleUnit, target); return mul; } @@ -175,17 +189,17 @@ ComplexCartesian ComplexCartesian::inverse(Context & context, Preferences::Compl // 1/(a+ib) = a/(a^2+b^2)+i*(-b/(a^2+b^2)) Expression denominatorReal = clone().convert().squareNorm(context, complexFormat, angleUnit, target); Expression denominatorImag = denominatorReal.clone(); - Expression denominatorRealInv = Power::Builder(denominatorReal, Rational(-1)); + Expression denominatorRealInv = Power::Builder(denominatorReal, Rational::Builder(-1)); denominatorReal.shallowReduce(context, complexFormat, angleUnit, target); - Expression denominatorImagInv = Power::Builder(denominatorImag, Rational(-1)); + Expression denominatorImagInv = Power::Builder(denominatorImag, Rational::Builder(-1)); denominatorImag.shallowReduce(context, complexFormat, angleUnit, target); Multiplication A = Multiplication::Builder(a, denominatorRealInv); denominatorRealInv.shallowReduce(context, complexFormat, angleUnit, target); - Expression numeratorImag = Multiplication::Builder(Rational(-1), b); + Expression numeratorImag = Multiplication::Builder(Rational::Builder(-1), b); Multiplication B = Multiplication::Builder(numeratorImag, denominatorImagInv); numeratorImag.shallowReduce(context, complexFormat, angleUnit, target); denominatorImagInv.shallowReduce(context, complexFormat, angleUnit, target); - ComplexCartesian result(A,B); + ComplexCartesian result = ComplexCartesian::Builder(A,B); A.shallowReduce(context, complexFormat, angleUnit, target); B.shallowReduce(context, complexFormat, angleUnit, target); return result.interruptComputationIfManyNodes(); @@ -193,11 +207,11 @@ ComplexCartesian ComplexCartesian::inverse(Context & context, Preferences::Compl Multiplication ComplexCartesian::squareRootHelper(Expression e, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { //(1/2)*sqrt(2*e) - Multiplication doubleE = Multiplication::Builder(Rational(2), e); + Multiplication doubleE = Multiplication::Builder(Rational::Builder(2), e); e.shallowReduce(context, complexFormat, angleUnit, target); Expression sqrt = SquareRoot::Builder(doubleE); doubleE.shallowReduce(context, complexFormat, angleUnit, target); - Multiplication result = Multiplication::Builder(Rational(1,2), sqrt); + Multiplication result = Multiplication::Builder(Rational::Builder(1,2), sqrt); sqrt.shallowReduce(context, complexFormat, angleUnit, target); return result; } @@ -238,16 +252,16 @@ ComplexCartesian ComplexCartesian::powerInteger(int n, Context & context, Prefer // (b*i)^n = b^n*i^n with i^n == i, -i, 1 or -1 if (a.isRationalZero()) { ComplexCartesian result; - Expression bpow = Power::Builder(b, Rational(n)); + Expression bpow = Power::Builder(b, Rational::Builder(n)); if (n/2%2 == 1) { - Expression temp = Multiplication::Builder(Rational(-1), bpow); + Expression temp = Multiplication::Builder(Rational::Builder(-1), bpow); bpow.shallowReduce(context, complexFormat, angleUnit, target); bpow = temp; } if (n%2 == 0) { - result = ComplexCartesian(bpow, Rational(0)); + result = ComplexCartesian::Builder(bpow, Rational::Builder(0)); } else { - result = ComplexCartesian(Rational(0), bpow); + result = ComplexCartesian::Builder(Rational::Builder(0), bpow); } bpow.shallowReduce(context, complexFormat, angleUnit, target); return result; @@ -259,17 +273,17 @@ ComplexCartesian ComplexCartesian::powerInteger(int n, Context & context, Prefer Addition B = Addition::Builder(); ComplexCartesian result = ComplexCartesian::Builder(A, B); for (int i = 0; i <= n; i++) { - BinomialCoefficient binom = BinomialCoefficient::Builder(Rational(n), Rational(i)); + BinomialCoefficient binom = BinomialCoefficient::Builder(Rational::Builder(n), Rational::Builder(i)); Expression aclone = i == n ? a : a.clone(); Expression bclone = i == n ? b : b.clone(); - Power apow = Power::Builder(aclone, Rational(n-i)); - Power bpow = Power::Builder(bclone, Rational(i)); + Power apow = Power::Builder(aclone, Rational::Builder(n-i)); + Power bpow = Power::Builder(bclone, Rational::Builder(i)); Multiplication m = Multiplication::Builder(binom, apow, bpow); binom.shallowReduce(); apow.shallowReduce(context, complexFormat, angleUnit, target); bpow.shallowReduce(context, complexFormat, angleUnit, target); if (i/2%2 == 1) { - m.addChildAtIndexInPlace(Rational(-1), 0, m.numberOfChildren()); + m.addChildAtIndexInPlace(Rational::Builder(-1), 0, m.numberOfChildren()); } if (i%2 == 0) { A.addChildAtIndexInPlace(m, A.numberOfChildren(), A.numberOfChildren()); @@ -328,9 +342,9 @@ ComplexCartesian ComplexCartesian::power(ComplexCartesian & other, Context & con // R = r^c*e^(-th*d) Expression rpowc = Power::Builder(rclone, c.clone()); rclone.shallowReduce(context, complexFormat, angleUnit, target); - Expression thmuld = Multiplication::Builder(Rational(-1), thclone, d.clone()); + Expression thmuld = Multiplication::Builder(Rational::Builder(-1), thclone, d.clone()); thclone.shallowReduce(context, complexFormat, angleUnit, target); - Expression exp = Power::Builder(Constant(Ion::Charset::Exponential), thmuld); + Expression exp = Power::Builder(Constant::Builder(Ion::Charset::Exponential), thmuld); thmuld.shallowReduce(context, complexFormat, angleUnit, target); Multiplication norm = Multiplication::Builder(rpowc, exp); rpowc.shallowReduce(context, complexFormat, angleUnit, target); @@ -370,7 +384,7 @@ ComplexCartesian ComplexCartesian::power(ComplexCartesian & other, Context & con ComplexCartesian ComplexCartesian::interruptComputationIfManyNodes() { if (numberOfDescendants(true) > k_maxNumberOfNodesBeforeInterrupting) { Expression::SetInterruption(true); - return ComplexCartesian(Undefined(), Undefined()); + return ComplexCartesian::Builder(Undefined::Builder(), Undefined::Builder()); } return *this; } diff --git a/poincare/src/condensed_sum_layout.cpp b/poincare/src/condensed_sum_layout.cpp index 3204fe357..a658e5d5d 100644 --- a/poincare/src/condensed_sum_layout.cpp +++ b/poincare/src/condensed_sum_layout.cpp @@ -37,4 +37,11 @@ KDPoint CondensedSumLayoutNode::positionOfChild(LayoutNode * child) { return KDPoint(x,y); } -} \ No newline at end of file +CondensedSumLayout CondensedSumLayout::Builder(Layout base, Layout subscript, Layout superscript) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(CondensedSumLayoutNode)); + CondensedSumLayoutNode * node = new (bufferNode) CondensedSumLayoutNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(base, subscript, superscript).array(), 3); + return static_cast(h); +} + +} diff --git a/poincare/src/confidence_interval.cpp b/poincare/src/confidence_interval.cpp index c56b756a2..cc47829ac 100644 --- a/poincare/src/confidence_interval.cpp +++ b/poincare/src/confidence_interval.cpp @@ -41,7 +41,7 @@ Evaluation ConfidenceIntervalNode::templatedApproximate(Context& context, Pre std::complex operands[2]; operands[0] = std::complex(f - 1/std::sqrt(n)); operands[1] = std::complex(f + 1/std::sqrt(n)); - return MatrixComplex(operands, 1, 2); + return MatrixComplex::Builder(operands, 1, 2); } Layout SimplePredictionIntervalNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -52,6 +52,13 @@ int SimplePredictionIntervalNode::serialize(char * buffer, int bufferSize, Prefe return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, SimplePredictionInterval::s_functionHelper.name()); } +ConfidenceInterval ConfidenceInterval::Builder(Expression child0, Expression child1) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(ConfidenceIntervalNode)); + ConfidenceIntervalNode * node = new (bufferNode) ConfidenceIntervalNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); + return static_cast(h); +} + Expression ConfidenceInterval::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { Expression e = Expression::defaultShallowReduce(); @@ -63,13 +70,13 @@ Expression ConfidenceInterval::shallowReduce(Context & context, Preferences::Com Expression c1 = childAtIndex(1); #if MATRIX_EXACT_REDUCING if (c0.type() == ExpressionNode::Type::Matrix || c1.type() == ExpressionNode::Type::Matrix) { - return Undefined(); + return Undefined::Builder(); } #endif if (c0.type() == ExpressionNode::Type::Rational) { Rational r0 = static_cast(c0); if (r0.signedIntegerNumerator().isNegative() || Integer::NaturalOrder(r0.signedIntegerNumerator(), r0.integerDenominator()) > 0) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } @@ -77,7 +84,7 @@ Expression ConfidenceInterval::shallowReduce(Context & context, Preferences::Com if (c1.type() == ExpressionNode::Type::Rational) { Rational r1 = static_cast(c1); if (!r1.integerDenominator().isOne() || r1.signedIntegerNumerator().isNegative()) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } @@ -88,9 +95,9 @@ Expression ConfidenceInterval::shallowReduce(Context & context, Preferences::Com Rational r0 = static_cast(c0); Rational r1 = static_cast(c1); // Compute [r0-1/sqr(r1), r0+1/sqr(r1)] - Expression sqr = Power::Builder(r1, Rational(-1, 2)); + Expression sqr = Power::Builder(r1, Rational::Builder(-1, 2)); Matrix matrix = Matrix::Builder(); - matrix.addChildAtIndexInPlace(Addition::Builder(r0.clone(), Multiplication::Builder(Rational(-1), sqr.clone())), 0, 0); + matrix.addChildAtIndexInPlace(Addition::Builder(r0.clone(), Multiplication::Builder(Rational::Builder(-1), sqr.clone())), 0, 0); matrix.addChildAtIndexInPlace(Addition::Builder(r0, sqr), 1, 1); matrix.setDimensions(1, 2); replaceWithInPlace(matrix); @@ -98,4 +105,11 @@ Expression ConfidenceInterval::shallowReduce(Context & context, Preferences::Com return matrix; } +SimplePredictionInterval SimplePredictionInterval::Builder(Expression child0, Expression child1) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(SimplePredictionIntervalNode)); + SimplePredictionIntervalNode * node = new (bufferNode) SimplePredictionIntervalNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); + return static_cast(h); +} + } diff --git a/poincare/src/conjugate.cpp b/poincare/src/conjugate.cpp index 27ed8cc88..a5f40eabf 100644 --- a/poincare/src/conjugate.cpp +++ b/poincare/src/conjugate.cpp @@ -29,7 +29,7 @@ Expression ConjugateNode::shallowReduce(Context & context, Preferences::ComplexF template Complex ConjugateNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { - return Complex(std::conj(c)); + return Complex::Builder(std::conj(c)); } Expression Conjugate::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { @@ -51,7 +51,7 @@ Expression Conjugate::shallowReduce(Context & context, Preferences::ComplexForma } if (c.type() == ExpressionNode::Type::ComplexCartesian) { ComplexCartesian complexChild = static_cast(c); - Multiplication m = Multiplication::Builder(Rational(-1), complexChild.imag()); + Multiplication m = Multiplication::Builder(Rational::Builder(-1), complexChild.imag()); complexChild.replaceChildAtIndexInPlace(1, m); m.shallowReduce(context, complexFormat, angleUnit, target); replaceWithInPlace(complexChild); @@ -64,4 +64,11 @@ Expression Conjugate::shallowReduce(Context & context, Preferences::ComplexForma return *this; } +Conjugate Conjugate::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(ConjugateNode)); + ConjugateNode * node = new (bufferNode) ConjugateNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); +} + } diff --git a/poincare/src/conjugate_layout.cpp b/poincare/src/conjugate_layout.cpp index ac636dcad..2522718aa 100644 --- a/poincare/src/conjugate_layout.cpp +++ b/poincare/src/conjugate_layout.cpp @@ -104,4 +104,11 @@ bool ConjugateLayoutNode::willReplaceChild(LayoutNode * oldChild, LayoutNode * n return true; } +ConjugateLayout ConjugateLayout::Builder(Layout child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(ConjugateLayoutNode)); + ConjugateLayoutNode * node = new (bufferNode) ConjugateLayoutNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); +} + } diff --git a/poincare/src/constant.cpp b/poincare/src/constant.cpp index a6df6544e..cdc28aebb 100644 --- a/poincare/src/constant.cpp +++ b/poincare/src/constant.cpp @@ -11,6 +11,10 @@ namespace Poincare { +ConstantNode::ConstantNode(const char * newName, int length) : SymbolAbstractNode() { + strlcpy(const_cast(name()), newName, length+1); +} + ExpressionNode::Sign ConstantNode::sign(Context * context) const { if (isPi() || isExponential()) { return Sign::Positive; @@ -59,29 +63,32 @@ template Evaluation ConstantNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { if (isIComplex()) { assert(m_name[1] == 0); - return Complex(0.0, 1.0); + return Complex::Builder(0.0, 1.0); } if (isPi()) { - return Complex(M_PI); + return Complex::Builder(M_PI); } assert(isExponential()); - return Complex(M_E); + return Complex::Builder(M_E); } Expression ConstantNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { return Constant(this).shallowReduce(context, complexFormat, angleUnit, target); } -Constant::Constant(char name) : SymbolAbstract(TreePool::sharedPool()->createTreeNode(SymbolAbstract::AlignedNodeSize(1, sizeof(ConstantNode)))) { - node()->setName(&name, 1); +Constant Constant::Builder(char name) { + void * bufferNode = TreePool::sharedPool()->alloc(SymbolAbstract::AlignedNodeSize(1, sizeof(ConstantNode))); + ConstantNode * node = new (bufferNode) ConstantNode(&name, 1); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); } Expression Constant::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { Expression result; if (complexFormat == Preferences::ComplexFormat::Real && isIComplex()) { - result = Unreal(); + result = Unreal::Builder(); } else if (target == ExpressionNode::ReductionTarget::User && isIComplex()) { - result = ComplexCartesian::Builder(Rational(0), Rational(1)); + result = ComplexCartesian::Builder(Rational::Builder(0), Rational::Builder(1)); } if (!result.isUninitialized()) { replaceWithInPlace(result); diff --git a/poincare/src/cosine.cpp b/poincare/src/cosine.cpp index b0070ff20..46e0a90eb 100644 --- a/poincare/src/cosine.cpp +++ b/poincare/src/cosine.cpp @@ -19,7 +19,7 @@ template Complex CosineNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { std::complex angleInput = Trigonometry::ConvertToRadian(c, angleUnit); std::complex res = std::cos(angleInput); - return Complex(Trigonometry::RoundToMeaningfulDigits(res, angleInput)); + return Complex::Builder(Trigonometry::RoundToMeaningfulDigits(res, angleInput)); } Layout CosineNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -50,4 +50,11 @@ Expression Cosine::shallowReduce(Context & context, Preferences::ComplexFormat c return Trigonometry::shallowReduceDirectFunction(*this, context, complexFormat, angleUnit, target); } +Cosine Cosine::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(CosineNode)); + CosineNode * node = new (bufferNode) CosineNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); +} + } diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index 8272a2a79..f883333c1 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -25,10 +25,11 @@ void removeZeroAtTheEnd(Integer * i) { assert(!i->isOverflow()); } -void DecimalNode::setValue(const native_uint_t * mantissaDigits, uint8_t mantissaSize, int exponent, bool negative) { - m_negative = negative; - m_exponent = exponent; - m_numberOfDigitsInMantissa = mantissaSize; +DecimalNode::DecimalNode(const native_uint_t * mantissaDigits, uint8_t mantissaSize, int exponent, bool negative) : + m_negative(negative), + m_exponent(exponent), + m_numberOfDigitsInMantissa(mantissaSize) +{ memcpy(m_mantissa, mantissaDigits, mantissaSize*sizeof(native_uint_t)); } @@ -40,14 +41,6 @@ Integer DecimalNode::unsignedMantissa() const { return Integer::BuildInteger((native_uint_t *)m_mantissa, m_numberOfDigitsInMantissa, false); } -void DecimalNode::initToMatchSize(size_t goalSize) { - assert(goalSize != sizeof(DecimalNode)); - int mantissaSize = goalSize - sizeof(DecimalNode); - assert(mantissaSize%sizeof(native_uint_t) == 0); - m_numberOfDigitsInMantissa = mantissaSize/sizeof(native_uint_t); - assert(size() == goalSize); -} - static size_t DecimalSize(uint8_t numberOfDigitsInMantissa) { return sizeof(DecimalNode)+ sizeof(native_uint_t)*numberOfDigitsInMantissa; } @@ -268,7 +261,7 @@ int Decimal::Exponent(const char * integralPart, int integralPartLength, const c return exp; } -Decimal::Decimal(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, int exponent) : Number() { +Decimal Decimal::Builder(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, int exponent) { /* Create a Decimal whose mantissa has less than * k_numberOfStoredSignificantDigits. We round exceeding number if necessary. */ Integer zero(0); @@ -301,11 +294,11 @@ Decimal::Decimal(const char * integralPart, int integralPartLength, const char * } numerator = rounding ? Integer::Addition(numerator, Integer(1)) : numerator; exponent = numerator.isZero() ? 0 : exponent; - new (this) Decimal(numerator, exponent); + return Decimal::Builder(numerator, exponent); } template -Decimal::Decimal(T f) : Number() { +Decimal Decimal::Builder(T f) { assert(!std::isnan(f) && !std::isinf(f)); int exp = IEEE754::exponentBase10(f); /* We keep 7 significant digits for if the the Decimal was built from a float @@ -327,17 +320,20 @@ Decimal::Decimal(T f) : Number() { Integer m = Integer((int64_t)(std::round(mantissaf))); /* We get rid of extra 0 at the end of the mantissa. */ removeZeroAtTheEnd(&m); - new (this) Decimal(m, exp); + return Decimal::Builder(m, exp); } /* We do not get rid of the useless 0s ending the mantissa here because we want * to keep them if they were entered by the user. */ -Decimal::Decimal(Integer m, int e) : - Decimal(DecimalSize(m.numberOfDigits()), m, e) {} +Decimal Decimal::Builder(Integer m, int e) { + return Decimal::Builder(DecimalSize(m.numberOfDigits()), m, e); +} - -Decimal::Decimal(size_t size, const Integer & m, int e) : Number(TreePool::sharedPool()->createTreeNode(size)) { - node()->setValue(m.digits(), m.numberOfDigits(), e, m.isNegative()); +Decimal Decimal::Builder(size_t size, const Integer & m, int e) { + void * bufferNode = TreePool::sharedPool()->alloc(size); + DecimalNode * node = new (bufferNode) DecimalNode(m.digits(), m.numberOfDigits(), e, m.isNegative()); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); } Expression Decimal::setSign(ExpressionNode::Sign s) { @@ -369,7 +365,7 @@ Expression Decimal::shallowReduce() { if (numerator.isOverflow() || denominator.isOverflow()) { result = Number::FloatNumber(node()->signedMantissa().template approximate()*std::pow(10.0, (double)exp)); } else { - result = Rational(numerator, denominator); + result = Rational::Builder(numerator, denominator); } replaceWithInPlace(result); return result; @@ -386,7 +382,7 @@ Expression Decimal::shallowBeautify() { return *this; } -template Decimal::Decimal(double); -template Decimal::Decimal(float); +template Decimal Decimal::Decimal::Builder(double); +template Decimal Decimal::Decimal::Builder(float); } diff --git a/poincare/src/derivative.cpp b/poincare/src/derivative.cpp index fffecd1b1..426878745 100644 --- a/poincare/src/derivative.cpp +++ b/poincare/src/derivative.cpp @@ -67,10 +67,10 @@ Evaluation DerivativeNode::templatedApproximate(Context& context, Preferences return Complex::Undefined(); } if (std::fabs(error) < min) { - return Complex(result); + return Complex::Builder(result); } error = std::pow((T)10, std::floor(std::log10(std::fabs(error)))+2); - return Complex(std::round(result/error)*error); + return Complex::Builder(std::round(result/error)*error); } template @@ -149,11 +149,18 @@ Expression Derivative::shallowReduce() { } #if MATRIX_EXACT_REDUCING if (childAtIndex(0).type() == ExpressionNode::Type::Matrix || || childAtIndex(1).type() == ExpressionNode::Type::Matrix || childAtIndex(2).type() == ExpressionNode::Type::Matrix) { - return Undefined(); + return Undefined::Builder(); } #endif // TODO: to be implemented diff(+) -> +diff() etc return *this; } +Derivative Derivative::Builder(Expression child0, Symbol child1, Expression child2) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(DerivativeNode)); + DerivativeNode * node = new (bufferNode) DerivativeNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1, child2).array(), 3); + return static_cast(h); +} + } diff --git a/poincare/src/determinant.cpp b/poincare/src/determinant.cpp index dae48be91..e0b973e25 100644 --- a/poincare/src/determinant.cpp +++ b/poincare/src/determinant.cpp @@ -25,13 +25,20 @@ int DeterminantNode::serialize(char * buffer, int bufferSize, Preferences::Print template Evaluation DeterminantNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { Evaluation input = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); - return Complex(input.determinant()); + return Complex::Builder(input.determinant()); } Expression DeterminantNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { return Determinant(this).shallowReduce(context); } +Determinant Determinant::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(DeterminantNode)); + DeterminantNode * node = new (bufferNode) DeterminantNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); +} + Expression Determinant::shallowReduce(Context & context) { { Expression e = Expression::defaultShallowReduce(); diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index 48c6734c1..8a6f5bb49 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -50,7 +50,7 @@ template Complex DivisionNode::compute(const std::complex c, c if (d.real() == 0.0 && d.imag() == 0.0) { return Complex::Undefined(); } - return Complex(c/d); + return Complex::Builder(c/d); } template MatrixComplex DivisionNode::computeOnComplexAndMatrix(const std::complex c, const MatrixComplex n, Preferences::ComplexFormat complexFormat) { @@ -70,6 +70,20 @@ template MatrixComplex DivisionNode::computeOnMatrices(const Matr // Division +Division Division::Builder() { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(DivisionNode)); + DivisionNode * node = new (bufferNode) DivisionNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); +} + +Division Division::Builder(Expression numerator, Expression denominator) { + Division d = Division::Builder(); + d.replaceChildAtIndexInPlace(0, numerator); + d.replaceChildAtIndexInPlace(1, denominator); + return d; +} + Expression Division::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { Expression e = Expression::defaultShallowReduce(); @@ -77,7 +91,7 @@ Expression Division::shallowReduce(Context & context, Preferences::ComplexFormat return e; } } - Expression p = Power::Builder(childAtIndex(1), Rational(-1)); + Expression p = Power::Builder(childAtIndex(1), Rational::Builder(-1)); Multiplication m = Multiplication::Builder(childAtIndex(0), p); p.shallowReduce(context, complexFormat, angleUnit, target); // Imagine Division::Builder(2,1). p would be 1^(-1) which can be simplified replaceWithInPlace(m); diff --git a/poincare/src/division_quotient.cpp b/poincare/src/division_quotient.cpp index f5ca4f543..b382a54cc 100644 --- a/poincare/src/division_quotient.cpp +++ b/poincare/src/division_quotient.cpp @@ -32,7 +32,14 @@ Evaluation DivisionQuotientNode::templatedApproximate(Context& context, Prefe if (std::isnan(f1) || std::isnan(f2) || f1 != (int)f1 || f2 != (int)f2) { return Complex::Undefined(); } - return Complex(std::floor(f1/f2)); + return Complex::Builder(std::floor(f1/f2)); +} + +DivisionQuotient DivisionQuotient::Builder(Expression child0, Expression child1) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(DivisionQuotientNode)); + DivisionQuotientNode * node = new (bufferNode) DivisionQuotientNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); + return static_cast(h); } Expression DivisionQuotient::shallowReduce() { @@ -46,7 +53,7 @@ Expression DivisionQuotient::shallowReduce() { Expression c1 = childAtIndex(1); #if MATRIX_EXACT_REDUCING if (c0.type() == ExpressionNode::Type::Matrix || c1.type() == ExpressionNode::Type::Matrix) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } @@ -54,7 +61,7 @@ Expression DivisionQuotient::shallowReduce() { if (c0.type() == ExpressionNode::Type::Rational) { Rational r0 = static_cast(c0); if (!r0.integerDenominator().isOne()) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } @@ -62,7 +69,7 @@ Expression DivisionQuotient::shallowReduce() { if (c1.type() == ExpressionNode::Type::Rational) { Rational r1 = static_cast(c1); if (!r1.integerDenominator().isOne()) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } @@ -76,13 +83,13 @@ Expression DivisionQuotient::shallowReduce() { Integer a = r0.signedIntegerNumerator(); Integer b = r1.signedIntegerNumerator(); if (b.isZero()) { - Expression result = Infinity(a.isNegative()); + Expression result = Infinity::Builder(a.isNegative()); replaceWithInPlace(result); return result; } Integer result = Integer::Division(a, b).quotient; assert(!result.isOverflow()); - Expression rationalResult = Rational(result); + Expression rationalResult = Rational::Builder(result); replaceWithInPlace(rationalResult); return rationalResult; } diff --git a/poincare/src/division_remainder.cpp b/poincare/src/division_remainder.cpp index 976d2f16f..030fb33ca 100644 --- a/poincare/src/division_remainder.cpp +++ b/poincare/src/division_remainder.cpp @@ -33,7 +33,14 @@ Evaluation DivisionRemainderNode::templatedApproximate(Context& context, Pref if (std::isnan(f1) || std::isnan(f2) || f1 != (int)f1 || f2 != (int)f2) { return Complex::Undefined(); } - return Complex(std::round(f1-f2*std::floor(f1/f2))); + return Complex::Builder(std::round(f1-f2*std::floor(f1/f2))); +} + +DivisionRemainder DivisionRemainder::Builder(Expression child0, Expression child1) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(DivisionRemainderNode)); + DivisionRemainderNode * node = new (bufferNode) DivisionRemainderNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); + return static_cast(h); } Expression DivisionRemainder::shallowReduce() { @@ -47,13 +54,13 @@ Expression DivisionRemainder::shallowReduce() { Expression c1 = childAtIndex(1); #if MATRIX_EXACT_REDUCING if (c0.type() == ExpressionNode::Type::Matrix || c1.type() == ExpressionNode::Type::Matrix) { - return Undefined(); + return Undefined::Builder(); } #endif if (c0.type() == ExpressionNode::Type::Rational) { Rational r0 = static_cast(c0); if (!r0.integerDenominator().isOne()) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } @@ -61,7 +68,7 @@ Expression DivisionRemainder::shallowReduce() { if (c1.type() == ExpressionNode::Type::Rational) { Rational r1 = static_cast(c1); if (!r1.integerDenominator().isOne()) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } @@ -75,13 +82,13 @@ Expression DivisionRemainder::shallowReduce() { Integer a = r0.signedIntegerNumerator(); Integer b = r1.signedIntegerNumerator(); if (b.isZero()) { - Expression result = Infinity(a.isNegative()); + Expression result = Infinity::Builder(a.isNegative()); replaceWithInPlace(result); return result; } Integer result = Integer::Division(a, b).remainder; assert(!result.isOverflow()); - Expression rationalResult = Rational(result); + Expression rationalResult = Rational::Builder(result); replaceWithInPlace(rationalResult); return rationalResult; } diff --git a/poincare/src/empty_expression.cpp b/poincare/src/empty_expression.cpp index 4cb841349..cf007c671 100644 --- a/poincare/src/empty_expression.cpp +++ b/poincare/src/empty_expression.cpp @@ -11,13 +11,18 @@ int EmptyExpressionNode::serialize(char * buffer, int bufferSize, Preferences::P } Layout EmptyExpressionNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { - return EmptyLayout(); + return EmptyLayout::Builder(); } template Evaluation EmptyExpressionNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { return Complex::Undefined(); } -EmptyExpression::EmptyExpression() : Expression(TreePool::sharedPool()->createTreeNode()) {} +EmptyExpression EmptyExpression::Builder() { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(EmptyExpressionNode)); + EmptyExpressionNode * node = new (bufferNode) EmptyExpressionNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); +} } diff --git a/poincare/src/empty_layout.cpp b/poincare/src/empty_layout.cpp index 00f0b642b..f8a0f8f3b 100644 --- a/poincare/src/empty_layout.cpp +++ b/poincare/src/empty_layout.cpp @@ -95,13 +95,12 @@ void EmptyLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionColor } EmptyLayout::EmptyLayout(const EmptyLayoutNode * n) : Layout(n) {} -EmptyLayout::EmptyLayout(EmptyLayoutNode::Color color, bool visible, const KDFont * font, bool margins) : - Layout(TreePool::sharedPool()->createTreeNode()) -{ - node()->setColor(color); - node()->setVisible(visible); - node()->setFont(font); - node()->setMargins(margins); + +EmptyLayout EmptyLayout::Builder(EmptyLayoutNode::Color color, bool visible, const KDFont * font, bool margins) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(EmptyLayoutNode)); + EmptyLayoutNode * node = new (bufferNode) EmptyLayoutNode(color, visible, font, margins); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); } } diff --git a/poincare/src/equal.cpp b/poincare/src/equal.cpp index dbcb1abaa..e3f9f0c3d 100644 --- a/poincare/src/equal.cpp +++ b/poincare/src/equal.cpp @@ -27,7 +27,7 @@ Expression EqualNode::shallowReduce(Context & context, Preferences::ComplexForma Layout EqualNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { HorizontalLayout result = HorizontalLayout::Builder(); result.addOrMergeChildAtIndex(childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits), 0, false); - result.addChildAtIndex(CharLayout('='), result.numberOfChildren(), result.numberOfChildren(), nullptr); + result.addChildAtIndex(CharLayout::Builder('='), result.numberOfChildren(), result.numberOfChildren(), nullptr); result.addOrMergeChildAtIndex(childAtIndex(1)->createLayout(floatDisplayMode, numberOfSignificantDigits), result.numberOfChildren(), false); return result; } @@ -41,6 +41,13 @@ Evaluation EqualNode::templatedApproximate(Context& context, Preferences::Com return Complex::Undefined(); } +Equal Equal::Builder(Expression child0, Expression child1) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(EqualNode)); + EqualNode * node = new (bufferNode) EqualNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); + return static_cast(h); +} + Expression Equal::standardEquation(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { Expression sub = Subtraction::Builder(childAtIndex(0).clone(), childAtIndex(1).clone()); return sub.reduce(context, complexFormat, angleUnit); @@ -54,7 +61,7 @@ Expression Equal::shallowReduce() { } } if (childAtIndex(0).isIdenticalTo(childAtIndex(1))) { - Expression result = Rational(1); + Expression result = Rational::Builder(1); replaceWithInPlace(result); return result; } diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 544814670..b11eb1a6c 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -166,7 +166,7 @@ bool Expression::getLinearCoefficients(char * variables, int maxVariableSize, Ex int degree = equation.getPolynomialReducedCoefficients(&variables[index*maxVariableSize], polynomialCoefficients, context, complexFormat, angleUnit); switch (degree) { case 0: - coefficients[index] = Rational(0); + coefficients[index] = Rational::Builder(0); break; case 1: coefficients[index] = polynomialCoefficients[1]; @@ -213,10 +213,10 @@ Expression Expression::defaultShallowReduce() { // - the result is unreal is at least one child is unreal // - the result is undefined is at least one child is undefined but no child is unreal if (childAtIndex(i).type() == ExpressionNode::Type::Unreal) { - result = Unreal(); + result = Unreal::Builder(); break; } else if (childAtIndex(i).type() == ExpressionNode::Type::Undefined) { - result = Undefined(); + result = Undefined::Builder(); } } if (!result.isUninitialized()) { @@ -369,7 +369,7 @@ bool Expression::isEqualToItsApproximationLayout(Expression approximation, char * to re-serialize it because the number of stored significative * numbers and the number of displayed significative numbers might not be * identical. (For example, 0.000025 might be displayed "0.00003" and stored - * as Decimal(0.000025) and isEqualToItsApproximationLayout should return + * as Decimal::Builder(0.000025) and isEqualToItsApproximationLayout should return * false) */ Expression approximateOutput = Expression::ParseAndSimplify(buffer, context, complexFormat, angleUnit); bool equal = isIdenticalTo(approximateOutput); @@ -389,7 +389,7 @@ int Expression::serialize(char * buffer, int bufferSize, Preferences::PrintFloat Expression Expression::ParseAndSimplify(const char * text, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { Expression exp = Parse(text); if (exp.isUninitialized()) { - return Undefined(); + return Undefined::Builder(); } exp = exp.simplify(context, complexFormat, angleUnit); /* simplify might have been interrupted, in which case the resulting @@ -404,8 +404,8 @@ void Expression::ParseAndSimplifyAndApproximate(const char * text, Expression * assert(simplifiedExpression); Expression exp = Parse(text); if (exp.isUninitialized()) { - *simplifiedExpression = Undefined(); - *approximateExpression = Undefined(); + *simplifiedExpression = Undefined::Builder(); + *approximateExpression = Undefined::Builder(); return; } exp.simplifyAndApproximate(simplifiedExpression, approximateExpression, context, complexFormat, angleUnit); @@ -449,14 +449,14 @@ void Expression::simplifyAndApproximate(Expression * simplifiedExpression, Expre /* Case 1: the reduced expression is ComplexCartesian or pure real, we can * take into account the complex format to display a+i*b or r*e^(i*th) */ if (e.type() == ExpressionNode::Type::ComplexCartesian || e.isReal(context)) { - ComplexCartesian ecomplex = e.type() == ExpressionNode::Type::ComplexCartesian ? static_cast(e) : ComplexCartesian::Builder(e, Rational(0)); + ComplexCartesian ecomplex = e.type() == ExpressionNode::Type::ComplexCartesian ? static_cast(e) : ComplexCartesian::Builder(e, Rational::Builder(0)); if (approximateExpression) { /* Step 2: Approximation * We compute the approximate expression from the Cartesian form to avoid - * unprecision. For example, if the result is the ComplexCartesian(a,b), + * unprecision. For example, if the result is the ComplexCartesian::Builder(a,b), * the final expression is goind to be sqrt(a^2+b^2)*exp(i*arctan(b/a)... * in Polar ComplexFormat. If we approximate this expression instead of - * ComplexCartesian(a,b), we are going to loose precision on the resulting + * ComplexCartesian::Builder(a,b), we are going to loose precision on the resulting * complex.*/ // Clone the ComplexCartesian to use it to compute the approximation ComplexCartesian ecomplexClone = ecomplex.clone().convert(); @@ -519,12 +519,12 @@ Expression Expression::ExpressionWithoutSymbols(Expression e, Context & context) Expression Expression::radianToDegree() { // e*180/Pi - return Multiplication::Builder(*this, Rational(180), Power::Builder(Constant(Ion::Charset::SmallPi), Rational(-1))); + return Multiplication::Builder(*this, Rational::Builder(180), Power::Builder(Constant::Builder(Ion::Charset::SmallPi), Rational::Builder(-1))); } Expression Expression::degreeToRadian() { // e*Pi/180 - return Multiplication::Builder(*this, Rational(1, 180), Constant(Ion::Charset::SmallPi)); + return Multiplication::Builder(*this, Rational::Builder(1, 180), Constant::Builder(Ion::Charset::SmallPi)); } Expression Expression::reduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { @@ -566,7 +566,7 @@ Expression Expression::setSign(ExpressionNode::Sign s, Context * context, Prefer template Expression Expression::approximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { - return isUninitialized() ? Undefined() : approximateToEvaluation(context, complexFormat, angleUnit).complexToExpression(complexFormat); + return isUninitialized() ? Undefined::Builder() : approximateToEvaluation(context, complexFormat, angleUnit).complexToExpression(complexFormat); } @@ -609,7 +609,7 @@ bool Expression::IsMinusOne(const Expression e) { Expression Expression::CreateComplexExpression(Expression ra, Expression tb, Preferences::ComplexFormat complexFormat, bool undefined, bool isZeroRa, bool isOneRa, bool isZeroTb, bool isOneTb, bool isNegativeRa, bool isNegativeTb) { if (undefined) { - return Undefined(); + return Undefined::Builder(); } switch (complexFormat) { case Preferences::ComplexFormat::Real: @@ -626,9 +626,9 @@ Expression Expression::CreateComplexExpression(Expression ra, Expression tb, Pre } if (!isZeroTb) { if (isOneTb) { - imag = Constant(Ion::Charset::IComplex); + imag = Constant::Builder(Ion::Charset::IComplex); } else { - imag = Multiplication::Builder(tb , Constant(Ion::Charset::IComplex)); + imag = Multiplication::Builder(tb , Constant::Builder(Ion::Charset::IComplex)); } } if (imag.isUninitialized()) { @@ -657,14 +657,14 @@ Expression Expression::CreateComplexExpression(Expression ra, Expression tb, Pre if (!isZeroRa && !isZeroTb) { Expression arg; if (isOneTb) { - arg = Constant(Ion::Charset::IComplex); + arg = Constant::Builder(Ion::Charset::IComplex); } else { - arg = Multiplication::Builder(tb, Constant(Ion::Charset::IComplex)); + arg = Multiplication::Builder(tb, Constant::Builder(Ion::Charset::IComplex)); } if (isNegativeTb) { arg = Opposite::Builder(arg); } - exp = Power::Builder(Constant(Ion::Charset::Exponential), arg); + exp = Power::Builder(Constant::Builder(Ion::Charset::Exponential), arg); } if (exp.isUninitialized()) { return norm; diff --git a/poincare/src/factor.cpp b/poincare/src/factor.cpp index d303b3a06..dd8e005c0 100644 --- a/poincare/src/factor.cpp +++ b/poincare/src/factor.cpp @@ -30,10 +30,17 @@ Expression FactorNode::shallowBeautify(Context & context, Preferences::ComplexFo return Factor(this).shallowBeautify(context, complexFormat, angleUnit); } +Factor Factor::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(FactorNode)); + FactorNode * node = new (bufferNode) FactorNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); +} + Expression Factor::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { Expression c = childAtIndex(0); if (c.type() != ExpressionNode::Type::Rational) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } @@ -44,7 +51,7 @@ Expression Factor::shallowBeautify(Context & context, Preferences::ComplexFormat } Multiplication numeratorDecomp = createMultiplicationOfIntegerPrimeDecomposition(r.unsignedIntegerNumerator(), context, complexFormat, angleUnit); if (numeratorDecomp.numberOfChildren() == 0) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } @@ -52,7 +59,7 @@ Expression Factor::shallowBeautify(Context & context, Preferences::ComplexFormat if (!r.integerDenominator().isOne()) { Multiplication denominatorDecomp = createMultiplicationOfIntegerPrimeDecomposition(r.integerDenominator(), context, complexFormat, angleUnit); if (denominatorDecomp.numberOfChildren() == 0) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } @@ -73,7 +80,7 @@ Multiplication Factor::createMultiplicationOfIntegerPrimeDecomposition(Integer i Integer coefficients[Arithmetic::k_maxNumberOfPrimeFactors]; int numberOfPrimeFactors = Arithmetic::PrimeFactorization(i, factors, coefficients, Arithmetic::k_maxNumberOfPrimeFactors); if (numberOfPrimeFactors == 0) { - m.addChildAtIndexInPlace(Rational(i), 0, 0); + m.addChildAtIndexInPlace(Rational::Builder(i), 0, 0); return m; } if (numberOfPrimeFactors < 0) { @@ -81,9 +88,9 @@ Multiplication Factor::createMultiplicationOfIntegerPrimeDecomposition(Integer i return m; } for (int index = 0; index < numberOfPrimeFactors; index++) { - Expression factor = Rational(factors[index]); + Expression factor = Rational::Builder(factors[index]); if (!coefficients[index].isOne()) { - factor = Power::Builder(factor, Rational(coefficients[index])); + factor = Power::Builder(factor, Rational::Builder(coefficients[index])); } m.addChildAtIndexInPlace(factor, m.numberOfChildren(), m.numberOfChildren()); } diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index 94a03f10b..47786a22b 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -52,17 +52,17 @@ Complex FactorialNode::computeOnComplex(const std::complex c, Preferences: for (int i = 1; i <= (int)n; i++) { result *= (T)i; if (std::isinf(result)) { - return Complex(result); + return Complex::Builder(result); } } - return Complex(std::round(result)); + return Complex::Builder(std::round(result)); } Layout FactorialNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { HorizontalLayout result = HorizontalLayout::Builder(); result.addOrMergeChildAtIndex(childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits), 0, false); int childrenCount = result.numberOfChildren(); - result.addChildAtIndex(CharLayout('!'), childrenCount, childrenCount, nullptr); + result.addChildAtIndex(CharLayout::Builder('!'), childrenCount, childrenCount, nullptr); return result; } @@ -89,6 +89,13 @@ int FactorialNode::serialize(char * buffer, int bufferSize, Preferences::PrintFl return numberOfChar; } +Factorial Factorial::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(FactorialNode)); + FactorialNode * node = new (bufferNode) FactorialNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); +} + Expression Factorial::shallowReduce() { { Expression e = Expression::defaultShallowReduce(); @@ -104,21 +111,21 @@ Expression Factorial::shallowReduce() { if (childAtIndex(0).type() == ExpressionNode::Type::Rational) { Rational r = childAtIndex(0).convert(); if (!r.integerDenominator().isOne() || r.sign() == ExpressionNode::Sign::Negative) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } if (Integer(k_maxOperandValue).isLowerThan(r.unsignedIntegerNumerator())) { return *this; } - Rational fact = Rational(Integer::Factorial(r.unsignedIntegerNumerator())); + Rational fact = Rational::Builder(Integer::Factorial(r.unsignedIntegerNumerator())); assert(!fact.numeratorOrDenominatorIsInfinity()); // because fact < k_maxOperandValue! replaceWithInPlace(fact); return fact; } if (childAtIndex(0).type() == ExpressionNode::Type::Constant) { // e! = undef, i! = undef, pi! = undef - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } diff --git a/poincare/src/float.cpp b/poincare/src/float.cpp index b18b88ec4..1a37e4107 100644 --- a/poincare/src/float.cpp +++ b/poincare/src/float.cpp @@ -8,7 +8,7 @@ Expression FloatNode::setSign(Sign s, Context * context, Preferences::Complex assert(s == ExpressionNode::Sign::Positive || s == ExpressionNode::Sign::Negative); Sign currentSign = m_value < 0 ? Sign::Negative : Sign::Positive; Expression thisExpr = Number(this); - Expression result = Float(s == currentSign ? m_value : -m_value); + Expression result = Float::Builder(s == currentSign ? m_value : -m_value); thisExpr.replaceWithInPlace(result); return result; } @@ -42,14 +42,17 @@ Layout FloatNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, } template -Float::Float(T value) : Number(TreePool::sharedPool()->createTreeNode>()) { - node()->setFloat(value); +Float Float::Builder(T value) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(FloatNode)); + FloatNode * node = new (bufferNode) FloatNode(value); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); } template class FloatNode; template class FloatNode; -template Float::Float(float value); -template Float::Float(double value); +template Float Float::Builder(float value); +template Float Float::Builder(double value); } diff --git a/poincare/src/floor.cpp b/poincare/src/floor.cpp index 8694f4509..207e1c28e 100644 --- a/poincare/src/floor.cpp +++ b/poincare/src/floor.cpp @@ -28,13 +28,20 @@ Complex FloorNode::computeOnComplex(const std::complex c, Preferences::Com if (c.imag() != 0) { return Complex::Undefined(); } - return Complex(std::floor(c.real())); + return Complex::Builder(std::floor(c.real())); } Expression FloorNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { return Floor(this).shallowReduce(); } +Floor Floor::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(FloorNode)); + FloorNode * node = new (bufferNode) FloorNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); +} + Expression Floor::shallowReduce() { { Expression e = Expression::defaultShallowReduce(); @@ -52,10 +59,10 @@ Expression Floor::shallowReduce() { Constant s = static_cast(c); Expression result; if (s.isPi()) { - result = Rational(3); + result = Rational::Builder(3); } if (s.isExponential()) { - result = Rational(2); + result = Rational::Builder(2); } if (!result.isUninitialized()) { replaceWithInPlace(result); @@ -69,7 +76,7 @@ Expression Floor::shallowReduce() { Rational r = static_cast(c); IntegerDivision div = Integer::Division(r.signedIntegerNumerator(), r.integerDenominator()); assert(!div.quotient.isOverflow()); - Expression result = Rational(div.quotient); + Expression result = Rational::Builder(div.quotient); replaceWithInPlace(result); return result; } diff --git a/poincare/src/floor_layout.cpp b/poincare/src/floor_layout.cpp new file mode 100644 index 000000000..d0c04a6dc --- /dev/null +++ b/poincare/src/floor_layout.cpp @@ -0,0 +1,12 @@ +#include + +namespace Poincare { + +FloorLayout FloorLayout::Builder(Layout child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(FloorLayoutNode)); + FloorLayoutNode * node = new (bufferNode) FloorLayoutNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); +} + +} diff --git a/poincare/src/frac_part.cpp b/poincare/src/frac_part.cpp index 1e1702760..20da772b0 100644 --- a/poincare/src/frac_part.cpp +++ b/poincare/src/frac_part.cpp @@ -28,7 +28,14 @@ Complex FracPartNode::computeOnComplex(const std::complex c, Preferences:: if (c.imag() != 0) { return Complex::Undefined(); } - return Complex(c.real()-std::floor(c.real())); + return Complex::Builder(c.real()-std::floor(c.real())); +} + +FracPart FracPart::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(FracPartNode)); + FracPartNode * node = new (bufferNode) FracPartNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); } Expression FracPart::shallowReduce() { @@ -51,7 +58,7 @@ Expression FracPart::shallowReduce() { IntegerDivision div = Integer::Division(r.signedIntegerNumerator(), r.integerDenominator()); assert(!div.remainder.isOverflow()); Integer rDenominator = r.integerDenominator(); - Expression result = Rational(div.remainder, rDenominator); + Expression result = Rational::Builder(div.remainder, rDenominator); replaceWithInPlace(result); return result; } diff --git a/poincare/src/fraction_layout.cpp b/poincare/src/fraction_layout.cpp index f18e88600..d9e15d9bd 100644 --- a/poincare/src/fraction_layout.cpp +++ b/poincare/src/fraction_layout.cpp @@ -95,7 +95,7 @@ void FractionLayoutNode::deleteBeforeCursor(LayoutCursor * cursor) { if (numeratorLayout()->isEmpty() && denominatorLayout()->isEmpty()) { /* Case: Numerator and denominator are empty. Move the cursor and replace * the fraction with an empty layout. */ - thisRef.replaceWith(EmptyLayout(), cursor); + thisRef.replaceWith(EmptyLayout::Builder(), cursor); // WARNING: Do no use "this" afterwards return; } @@ -216,4 +216,11 @@ void FractionLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionCo ctx->fillRect(KDRect(p.x()+Metric::FractionAndConjugateHorizontalMargin, fractionLineY, layoutSize().width()-2*Metric::FractionAndConjugateHorizontalMargin, k_fractionLineHeight), expressionColor); } -} \ No newline at end of file +FractionLayout FractionLayout::Builder(Layout numerator, Layout denominator) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(FractionLayoutNode)); + FractionLayoutNode * node = new (bufferNode) FractionLayoutNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(numerator, denominator).array(), 2); + return static_cast(h); +} + +} diff --git a/poincare/src/function.cpp b/poincare/src/function.cpp index 1eada76cb..caae12cc4 100644 --- a/poincare/src/function.cpp +++ b/poincare/src/function.cpp @@ -9,6 +9,10 @@ namespace Poincare { +FunctionNode::FunctionNode(const char * newName, int length) : SymbolAbstractNode() { + strlcpy(const_cast(name()), newName, length+1); +} + bool FunctionNode::isReal(Context & context) const { Function f(this); return SymbolAbstract::isReal(f, context); @@ -88,10 +92,13 @@ Evaluation FunctionNode::templatedApproximate(Context& context, Preferences:: return e.node()->approximate(T(), context, complexFormat, angleUnit); } -Function::Function(const char * name, size_t length) : - Function(TreePool::sharedPool()->createTreeNode(SymbolAbstract::AlignedNodeSize(length, sizeof(FunctionNode)))) -{ - static_cast(Expression::node())->setName(name, length); +Function Function::Builder(const char * name, size_t length, Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(SymbolAbstract::AlignedNodeSize(length, sizeof(FunctionNode))); + FunctionNode * node = new (bufferNode) FunctionNode(name, length); + Expression * childPointer = child.isUninitialized() ? nullptr : &child; + int numberOfChild = child.isUninitialized() ? 0 : 1; + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, childPointer, numberOfChild); + return static_cast(h); } Expression Function::replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression) { @@ -100,7 +107,7 @@ Expression Function::replaceSymbolWithExpression(const SymbolAbstract & symbol, if (symbol.type() == ExpressionNode::Type::Function && strcmp(name(), symbol.name()) == 0) { Expression value = expression.clone(); // Replace the unknown in the new expression by the function's child - Symbol xSymbol = Symbol(Symbol::SpecialSymbols::UnknownX); + Symbol xSymbol = Symbol::Builder(Symbol::SpecialSymbols::UnknownX); Expression xValue = childAtIndex(0); value = value.replaceSymbolWithExpression(xSymbol, xValue); Expression p = parent(); @@ -128,7 +135,7 @@ Expression Function::shallowReplaceReplaceableSymbols(Context & context) { if (e.isUninitialized()) { return *this; } - e.replaceSymbolWithExpression(Symbol(Symbol::SpecialSymbols::UnknownX), childAtIndex(0)); + e.replaceSymbolWithExpression(Symbol::Builder(Symbol::SpecialSymbols::UnknownX), childAtIndex(0)); replaceWithInPlace(e); return e; } @@ -136,7 +143,7 @@ Expression Function::shallowReplaceReplaceableSymbols(Context & context) { // TODO: should we avoid replacing unknown X in-place but use a context instead? #if 0 VariableContext Function::unknownXContext(Context & parentContext) const { - Symbol unknownXSymbol(Symbol::SpecialSymbols::UnknownX); + Symbol unknownXSymbol = Symbol::Builder(Symbol::SpecialSymbols::UnknownX); Expression child = childAtIndex(0); const char x[] = {Symbol::SpecialSymbols::UnknownX, 0}; /* COMMENT */ diff --git a/poincare/src/great_common_divisor.cpp b/poincare/src/great_common_divisor.cpp index 3697690de..b07b8242f 100644 --- a/poincare/src/great_common_divisor.cpp +++ b/poincare/src/great_common_divisor.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -45,7 +46,14 @@ Evaluation GreatCommonDivisorNode::templatedApproximate(Context& context, Pre a = b; b = r; } - return Complex(std::round((T)a)); + return Complex::Builder(std::round((T)a)); +} + +GreatCommonDivisor GreatCommonDivisor::Builder(Expression child0, Expression child1) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(GreatCommonDivisorNode)); + GreatCommonDivisorNode * node = new (bufferNode) GreatCommonDivisorNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); + return static_cast(h); } Expression GreatCommonDivisor::shallowReduce() { @@ -59,13 +67,13 @@ Expression GreatCommonDivisor::shallowReduce() { Expression c1 = childAtIndex(1); #if MATRIX_EXACT_REDUCING if (c0.type() == ExpressionNode::Type::Matrix || c1.type() == ExpressionNode::Type::Matrix) { - return Undefined(); + return Undefined::Builder(); } #endif if (c0.type() == ExpressionNode::Type::Rational) { Rational r0 = static_cast(c0); if (!r0.integerDenominator().isOne()) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } @@ -73,7 +81,7 @@ Expression GreatCommonDivisor::shallowReduce() { if (c1.type() == ExpressionNode::Type::Rational) { Rational r1 = static_cast(c1); if (!r1.integerDenominator().isOne()) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } @@ -88,7 +96,7 @@ Expression GreatCommonDivisor::shallowReduce() { Integer b = r1.signedIntegerNumerator(); Integer gcd = Arithmetic::GCD(a, b); assert(!gcd.isOverflow()); - Expression result = Rational(gcd); + Expression result = Rational::Builder(gcd); replaceWithInPlace(result); return result; } diff --git a/poincare/src/grid_layout.cpp b/poincare/src/grid_layout.cpp index f10bde101..e96115515 100644 --- a/poincare/src/grid_layout.cpp +++ b/poincare/src/grid_layout.cpp @@ -103,7 +103,7 @@ void GridLayoutNode::addEmptyRow(EmptyLayoutNode::Color color) { int previousRowCount = m_numberOfRows; for (int i = 0; i < columnsCount; i++) { thisRef.addChildAtIndex( - EmptyLayout(color), + EmptyLayout::Builder(color), previousNumberOfChildren, previousNumberOfChildren + i, nullptr); @@ -119,7 +119,7 @@ void GridLayoutNode::addEmptyColumn(EmptyLayoutNode::Color color) { int futureColumnsCount = m_numberOfColumns + 1; for (int i = 0; i < rowsCount; i++) { thisRef.addChildAtIndex( - EmptyLayout(color), + EmptyLayout::Builder(color), i*futureColumnsCount + futureColumnsCount-1, previousNumberOfChildren + i, nullptr); @@ -268,4 +268,11 @@ void GridLayout::setDimensions(int rows, int columns) { setNumberOfColumns(columns); } +GridLayout GridLayout::Builder() { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(GridLayoutNode)); + GridLayoutNode * node = new (bufferNode) GridLayoutNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); +} + } diff --git a/poincare/src/horizontal_layout.cpp b/poincare/src/horizontal_layout.cpp index 871ff5af3..8ebb7dd9f 100644 --- a/poincare/src/horizontal_layout.cpp +++ b/poincare/src/horizontal_layout.cpp @@ -258,7 +258,7 @@ void HorizontalLayoutNode::didRemoveChildAtIndex(int index, LayoutCursor * curso * sibling (e.g. a VerticalOffsetLayout), add an empty layout at index 0 */ if (!force && index == 0 && numberOfChildren() > 0 && childAtIndex(0)->mustHaveLeftSibling()) { - Layout(this).addChildAtIndex(EmptyLayout(), 0, numberOfChildren(), cursor); + Layout(this).addChildAtIndex(EmptyLayout::Builder(), 0, numberOfChildren(), cursor); } } @@ -353,6 +353,13 @@ bool HorizontalLayoutNode::willReplaceChild(LayoutNode * oldChild, LayoutNode * // HorizontalLayout +HorizontalLayout HorizontalLayout::Builder() { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(HorizontalLayoutNode)); + HorizontalLayoutNode * node = new (bufferNode) HorizontalLayoutNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); +} + void HorizontalLayout::addOrMergeChildAtIndex(Layout l, int index, bool removeEmptyChildren, LayoutCursor * cursor) { if (l.isHorizontal()) { mergeChildrenAtIndex(HorizontalLayout(static_cast(l.node())), index, removeEmptyChildren, cursor); diff --git a/poincare/src/hyperbolic_arc_cosine.cpp b/poincare/src/hyperbolic_arc_cosine.cpp index 189059533..59f74b32c 100644 --- a/poincare/src/hyperbolic_arc_cosine.cpp +++ b/poincare/src/hyperbolic_arc_cosine.cpp @@ -23,7 +23,14 @@ Complex HyperbolicArcCosineNode::computeOnComplex(const std::complex c, Pr * on this cut. We followed the convention chosen by the lib c++ of llvm on * ]-inf+0i, 1+0i] (warning: atanh takes the other side of the cut values on * ]-inf-0i, 1-0i[).*/ - return Complex(Trigonometry::RoundToMeaningfulDigits(result, c)); + return Complex::Builder(Trigonometry::RoundToMeaningfulDigits(result, c)); +} + +HyperbolicArcCosine HyperbolicArcCosine::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(HyperbolicArcCosineNode)); + HyperbolicArcCosineNode * node = new (bufferNode) HyperbolicArcCosineNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); } template Complex Poincare::HyperbolicArcCosineNode::computeOnComplex(std::complex, Preferences::ComplexFormat, Preferences::AngleUnit); diff --git a/poincare/src/hyperbolic_arc_sine.cpp b/poincare/src/hyperbolic_arc_sine.cpp index c736f6c97..38fba0d13 100644 --- a/poincare/src/hyperbolic_arc_sine.cpp +++ b/poincare/src/hyperbolic_arc_sine.cpp @@ -26,7 +26,14 @@ Complex HyperbolicArcSineNode::computeOnComplex(const std::complex c, Pref if (c.real() == 0 && c.imag() < 1) { result.real(-result.real()); // other side of the cut } - return Complex(Trigonometry::RoundToMeaningfulDigits(result, c)); + return Complex::Builder(Trigonometry::RoundToMeaningfulDigits(result, c)); +} + +HyperbolicArcSine HyperbolicArcSine::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(HyperbolicArcSineNode)); + HyperbolicArcSineNode * node = new (bufferNode) HyperbolicArcSineNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); } template Complex Poincare::HyperbolicArcSineNode::computeOnComplex(std::complex, Preferences::ComplexFormat, Preferences::AngleUnit); diff --git a/poincare/src/hyperbolic_arc_tangent.cpp b/poincare/src/hyperbolic_arc_tangent.cpp index 11a72ddcf..83b52592b 100644 --- a/poincare/src/hyperbolic_arc_tangent.cpp +++ b/poincare/src/hyperbolic_arc_tangent.cpp @@ -27,7 +27,14 @@ Complex HyperbolicArcTangentNode::computeOnComplex(const std::complex c, P if (c.imag() == 0 && c.real() > 1) { result.imag(-result.imag()); // other side of the cut } - return Complex(Trigonometry::RoundToMeaningfulDigits(result, c)); + return Complex::Builder(Trigonometry::RoundToMeaningfulDigits(result, c)); +} + +HyperbolicArcTangent HyperbolicArcTangent::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(HyperbolicArcTangentNode)); + HyperbolicArcTangentNode * node = new (bufferNode) HyperbolicArcTangentNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); } template Complex Poincare::HyperbolicArcTangentNode::computeOnComplex(std::complex, Preferences::ComplexFormat, Preferences::AngleUnit); diff --git a/poincare/src/hyperbolic_cosine.cpp b/poincare/src/hyperbolic_cosine.cpp index bbd76e355..cfa001d4a 100644 --- a/poincare/src/hyperbolic_cosine.cpp +++ b/poincare/src/hyperbolic_cosine.cpp @@ -15,7 +15,14 @@ int HyperbolicCosineNode::serialize(char * buffer, int bufferSize, Preferences:: template Complex HyperbolicCosineNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { - return Complex(Trigonometry::RoundToMeaningfulDigits(std::cosh(c), c)); + return Complex::Builder(Trigonometry::RoundToMeaningfulDigits(std::cosh(c), c)); +} + +HyperbolicCosine HyperbolicCosine::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(HyperbolicCosineNode)); + HyperbolicCosineNode * node = new (bufferNode) HyperbolicCosineNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); } template Complex Poincare::HyperbolicCosineNode::computeOnComplex(std::complex, Preferences::ComplexFormat, Preferences::AngleUnit); diff --git a/poincare/src/hyperbolic_sine.cpp b/poincare/src/hyperbolic_sine.cpp index 5b1534c73..ef3064d2d 100644 --- a/poincare/src/hyperbolic_sine.cpp +++ b/poincare/src/hyperbolic_sine.cpp @@ -15,7 +15,14 @@ int HyperbolicSineNode::serialize(char * buffer, int bufferSize, Preferences::Pr template Complex HyperbolicSineNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { - return Complex(Trigonometry::RoundToMeaningfulDigits(std::sinh(c), c)); + return Complex::Builder(Trigonometry::RoundToMeaningfulDigits(std::sinh(c), c)); +} + +HyperbolicSine HyperbolicSine::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(HyperbolicSineNode)); + HyperbolicSineNode * node = new (bufferNode) HyperbolicSineNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); } template Complex Poincare::HyperbolicSineNode::computeOnComplex(std::complex, Preferences::ComplexFormat, Preferences::AngleUnit); diff --git a/poincare/src/hyperbolic_tangent.cpp b/poincare/src/hyperbolic_tangent.cpp index 89f0bab4b..2f7b3cec8 100644 --- a/poincare/src/hyperbolic_tangent.cpp +++ b/poincare/src/hyperbolic_tangent.cpp @@ -15,7 +15,14 @@ int HyperbolicTangentNode::serialize(char * buffer, int bufferSize, Preferences: template Complex HyperbolicTangentNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { - return Complex(Trigonometry::RoundToMeaningfulDigits(std::tanh(c), c)); + return Complex::Builder(Trigonometry::RoundToMeaningfulDigits(std::tanh(c), c)); +} + +HyperbolicTangent HyperbolicTangent::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(HyperbolicTangentNode)); + HyperbolicTangentNode * node = new (bufferNode) HyperbolicTangentNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); } template Complex Poincare::HyperbolicTangentNode::computeOnComplex(std::complex, Preferences::ComplexFormat, Preferences::AngleUnit); diff --git a/poincare/src/imaginary_part.cpp b/poincare/src/imaginary_part.cpp index 7667e535b..439900869 100644 --- a/poincare/src/imaginary_part.cpp +++ b/poincare/src/imaginary_part.cpp @@ -24,6 +24,13 @@ Expression ImaginaryPartNode::shallowReduce(Context & context, Preferences::Comp return ImaginaryPart(this).shallowReduce(context, complexFormat, angleUnit, target); } +ImaginaryPart ImaginaryPart::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(ImaginaryPartNode)); + ImaginaryPartNode * node = new (bufferNode) ImaginaryPartNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); +} + Expression ImaginaryPart::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { Expression e = Expression::defaultShallowReduce(); @@ -38,7 +45,7 @@ Expression ImaginaryPart::shallowReduce(Context & context, Preferences::ComplexF } #endif if (c.isReal(context)) { - Expression result = Rational(0); + Expression result = Rational::Builder(0); replaceWithInPlace(result); return result; } diff --git a/poincare/src/infinity.cpp b/poincare/src/infinity.cpp index a862b81db..71eb0287b 100644 --- a/poincare/src/infinity.cpp +++ b/poincare/src/infinity.cpp @@ -28,12 +28,19 @@ int InfinityNode::serialize(char * buffer, int bufferSize, Preferences::PrintFlo } template Evaluation InfinityNode::templatedApproximate() const { - return Complex(m_negative ? -INFINITY : INFINITY); + return Complex::Builder(m_negative ? -INFINITY : INFINITY); +} + +Infinity Infinity::Builder(bool negative) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(InfinityNode)); + InfinityNode * node = new (bufferNode) InfinityNode(negative); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); } Expression Infinity::setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { assert(s == ExpressionNode::Sign::Positive || s == ExpressionNode::Sign::Negative); - Expression result = Infinity(s == ExpressionNode::Sign::Negative); + Expression result = Infinity::Builder(s == ExpressionNode::Sign::Negative); replaceWithInPlace(result); return result; } diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 361ce2955..675bf0b44 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -45,14 +45,10 @@ static inline int8_t sign(bool negative) { return 1 - 2*(int8_t)negative; } -void IntegerNode::initToMatchSize(size_t goalSize) { - assert(goalSize != sizeof(IntegerNode)); - int digitsSize = goalSize - sizeof(IntegerNode); - assert(digitsSize%sizeof(native_uint_t) == 0); - /* We are initing the Integer to match a specific size. The built integer - * is dummy. */ - m_numberOfDigits = digitsSize/sizeof(native_uint_t); - assert(size() == goalSize); +IntegerNode::IntegerNode(const native_uint_t * digits, uint8_t numberOfDigits) : + m_numberOfDigits(numberOfDigits) +{ + memcpy(m_digits, digits, numberOfDigits*sizeof(native_uint_t)); } static size_t IntegerSize(uint8_t numberOfDigits) { @@ -87,11 +83,6 @@ void IntegerNode::log(std::ostream & stream) const { #endif -void IntegerNode::setDigits(const native_uint_t * digits, uint8_t numberOfDigits) { - m_numberOfDigits = numberOfDigits; - memcpy(m_digits, digits, numberOfDigits*sizeof(native_uint_t)); -} - // Constructor Integer Integer::BuildInteger(native_uint_t * digits, uint16_t numberOfDigits, bool negative, bool enableOverflow) { @@ -109,11 +100,17 @@ Integer Integer::BuildInteger(native_uint_t * digits, uint16_t numberOfDigits, b } // Private constructor -Integer::Integer(native_uint_t * digits, uint16_t numberOfDigits, bool negative) : - TreeHandle(TreePool::sharedPool()->createTreeNode(IntegerSize(numberOfDigits))), - m_negative(negative) -{ - node()->setDigits(digits, numberOfDigits); + +Integer::Integer(native_uint_t * digits, uint16_t numberOfDigits, bool negative) { + void * bufferNode = TreePool::sharedPool()->alloc(IntegerSize(numberOfDigits)); + IntegerNode * node = new (bufferNode) IntegerNode(digits, numberOfDigits); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + /* Integer is a TreeHandle that keeps an extra integer. We cannot just cast + * the TreeHandle in Integer, we have to build a new Integer. To do so, we + * pilfer the TreeHandle identifier. We thus have to increment the node + * reference counter to prevent its destruction when we leave this scope. */ + node->retain(); + new (this) Integer(h.identifier(), negative); } Integer::Integer(native_int_t i) : TreeHandle(TreeNode::NoNodeIdentifier) { diff --git a/poincare/src/integral.cpp b/poincare/src/integral.cpp index 00d64baad..91816bb9b 100644 --- a/poincare/src/integral.cpp +++ b/poincare/src/integral.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -62,7 +63,7 @@ Evaluation IntegralNode::templatedApproximate(Context & context, Preferences: #else T result = adaptiveQuadrature(a, b, 0.1, k_maxNumberOfIterations, context, complexFormat, angleUnit); #endif - return Complex(result); + return Complex::Builder(result); } template @@ -209,6 +210,13 @@ T IntegralNode::adaptiveQuadrature(T a, T b, T eps, int numberOfIterations, Cont } #endif +Integral Integral::Builder(Expression child0, Symbol child1, Expression child2, Expression child3) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(IntegralNode)); + IntegralNode * node = new (bufferNode) IntegralNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1, child2, child3).array(), 4); + return static_cast(h); +} + Expression Integral::shallowReduce() { { Expression e = Expression::defaultShallowReduce(); @@ -222,7 +230,7 @@ Expression Integral::shallowReduce() { || childAtIndex(2).type() == ExpressionNode::Type::Matrix || childAtIndex(3).type() == ExpressionNode::Type::Matrix) { - return Undefined(); + return Undefined::Builder(); } #endif return *this; diff --git a/poincare/src/integral_layout.cpp b/poincare/src/integral_layout.cpp index b53035fa6..43e366540 100644 --- a/poincare/src/integral_layout.cpp +++ b/poincare/src/integral_layout.cpp @@ -247,4 +247,11 @@ void IntegralLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionCo ctx->drawString("d", dPosition, k_font, expressionColor, backgroundColor); } +IntegralLayout IntegralLayout::Builder(Layout integrand, Layout differential, Layout lowerBound, Layout upperBound) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(IntegralLayoutNode)); + IntegralLayoutNode * node = new (bufferNode) IntegralLayoutNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(integrand, differential, lowerBound, upperBound).array(), 4); + return static_cast(h); +} + } diff --git a/poincare/src/layout.cpp b/poincare/src/layout.cpp index da2c66c5e..103f5fa6d 100644 --- a/poincare/src/layout.cpp +++ b/poincare/src/layout.cpp @@ -82,7 +82,7 @@ void Layout::replaceChild(Layout oldChild, Layout newChild, LayoutCursor * curso } void Layout::replaceChildWithEmpty(Layout oldChild, LayoutCursor * cursor) { - replaceChild(oldChild, EmptyLayout(), cursor); + replaceChild(oldChild, EmptyLayout::Builder(), cursor); } void Layout::replaceWith(Layout newChild, LayoutCursor * cursor) { diff --git a/poincare/src/layout_cursor.cpp b/poincare/src/layout_cursor.cpp index 22a7915b4..07b205b4c 100644 --- a/poincare/src/layout_cursor.cpp +++ b/poincare/src/layout_cursor.cpp @@ -73,9 +73,9 @@ void LayoutCursor::move(MoveDirection direction, bool * shouldRecomputeLayout) { /* Layout modification */ void LayoutCursor::addEmptyExponentialLayout() { - EmptyLayout emptyLayout; + EmptyLayout emptyLayout = EmptyLayout::Builder(); HorizontalLayout sibling = HorizontalLayout::Builder( - CharLayout(Ion::Charset::Exponential), + CharLayout::Builder(Ion::Charset::Exponential), VerticalOffsetLayout::Builder(emptyLayout, VerticalOffsetLayoutNode::Type::Superscript)); m_layout.addSibling(this, sibling, false); m_layout = emptyLayout; @@ -83,17 +83,17 @@ void LayoutCursor::addEmptyExponentialLayout() { void LayoutCursor::addEmptyMatrixLayout() { MatrixLayout matrixLayout = MatrixLayout::Builder( - EmptyLayout(EmptyLayoutNode::Color::Yellow), - EmptyLayout(EmptyLayoutNode::Color::Grey), - EmptyLayout(EmptyLayoutNode::Color::Grey), - EmptyLayout(EmptyLayoutNode::Color::Grey)); + EmptyLayout::Builder(EmptyLayoutNode::Color::Yellow), + EmptyLayout::Builder(EmptyLayoutNode::Color::Grey), + EmptyLayout::Builder(EmptyLayoutNode::Color::Grey), + EmptyLayout::Builder(EmptyLayoutNode::Color::Grey)); m_layout.addSibling(this, matrixLayout, false); m_layout = matrixLayout.childAtIndex(0); m_position = Position::Right; } void LayoutCursor::addEmptySquareRootLayout() { - HorizontalLayout child1 = HorizontalLayout::Builder(EmptyLayout()); + HorizontalLayout child1 = HorizontalLayout::Builder(EmptyLayout::Builder()); NthRootLayout newChild = NthRootLayout::Builder(child1); m_layout.addSibling(this, newChild, false); m_layout = newChild.childAtIndex(0); @@ -101,22 +101,22 @@ void LayoutCursor::addEmptySquareRootLayout() { } void LayoutCursor::addEmptyPowerLayout() { - VerticalOffsetLayout offsetLayout = VerticalOffsetLayout::Builder(EmptyLayout(), VerticalOffsetLayoutNode::Type::Superscript); + VerticalOffsetLayout offsetLayout = VerticalOffsetLayout::Builder(EmptyLayout::Builder(), VerticalOffsetLayoutNode::Type::Superscript); privateAddEmptyPowerLayout(offsetLayout); m_layout = offsetLayout.childAtIndex(0); } void LayoutCursor::addEmptySquarePowerLayout() { - VerticalOffsetLayout offsetLayout = VerticalOffsetLayout::Builder(CharLayout('2'), VerticalOffsetLayoutNode::Type::Superscript); + VerticalOffsetLayout offsetLayout = VerticalOffsetLayout::Builder(CharLayout::Builder('2'), VerticalOffsetLayoutNode::Type::Superscript); privateAddEmptyPowerLayout(offsetLayout); } void LayoutCursor::addEmptyTenPowerLayout() { - EmptyLayout emptyLayout; + EmptyLayout emptyLayout = EmptyLayout::Builder(); HorizontalLayout sibling = HorizontalLayout::Builder( - CharLayout(Ion::Charset::MiddleDot), - CharLayout('1'), - CharLayout('0'), + CharLayout::Builder(Ion::Charset::MiddleDot), + CharLayout::Builder('1'), + CharLayout::Builder('0'), VerticalOffsetLayout::Builder( emptyLayout, VerticalOffsetLayoutNode::Type::Superscript)); @@ -125,15 +125,15 @@ void LayoutCursor::addEmptyTenPowerLayout() { } void LayoutCursor::addFractionLayoutAndCollapseSiblings() { - HorizontalLayout child1 = HorizontalLayout::Builder(EmptyLayout()); - HorizontalLayout child2 = HorizontalLayout::Builder(EmptyLayout()); + HorizontalLayout child1 = HorizontalLayout::Builder(EmptyLayout::Builder()); + HorizontalLayout child2 = HorizontalLayout::Builder(EmptyLayout::Builder()); FractionLayout newChild = FractionLayout::Builder(child1, child2); m_layout.addSibling(this, newChild, true); Layout(newChild.node()).collapseSiblings(this); } void LayoutCursor::addXNTCharLayout() { - m_layout.addSibling(this, CharLayout(m_layout.XNTChar()), true); + m_layout.addSibling(this, CharLayout::Builder(m_layout.XNTChar()), true); } void LayoutCursor::insertText(const char * text) { @@ -148,7 +148,7 @@ void LayoutCursor::insertText(const char * text) { continue; } if (text[i] == Ion::Charset::MultiplicationSign) { - newChild = CharLayout(Ion::Charset::MiddleDot); + newChild = CharLayout::Builder(Ion::Charset::MiddleDot); } else if (text[i] == '(') { newChild = LeftParenthesisLayout::Builder(); if (pointedChild.isUninitialized()) { @@ -167,7 +167,7 @@ void LayoutCursor::insertText(const char * text) { } #endif else { - newChild = CharLayout(text[i]); + newChild = CharLayout::Builder(text[i]); } m_layout.addSibling(this, newChild, true); } @@ -217,7 +217,7 @@ void LayoutCursor::privateAddEmptyPowerLayout(VerticalOffsetLayout v) { return; } // Else, add an empty base - EmptyLayout e = EmptyLayout(); + EmptyLayout e = EmptyLayout::Builder(); HorizontalLayout newChild = HorizontalLayout::Builder(e, v); m_layout.addSibling(this, newChild, true); } diff --git a/poincare/src/layout_helper.cpp b/poincare/src/layout_helper.cpp index 9d7c584a6..7a61da0b8 100644 --- a/poincare/src/layout_helper.cpp +++ b/poincare/src/layout_helper.cpp @@ -34,7 +34,7 @@ Layout LayoutHelper::Prefix(const Expression & expression, Preferences::PrintFlo if (numberOfChildren > 0) { args.addOrMergeChildAtIndex(expression.childAtIndex(0).createLayout(floatDisplayMode, numberOfSignificantDigits), 0, true); for (int i = 1; i < numberOfChildren; i++) { - args.addChildAtIndex(CharLayout(','), args.numberOfChildren(), args.numberOfChildren(), nullptr); + args.addChildAtIndex(CharLayout::Builder(','), args.numberOfChildren(), args.numberOfChildren(), nullptr); args.addOrMergeChildAtIndex(expression.childAtIndex(i).createLayout(floatDisplayMode, numberOfSignificantDigits), args.numberOfChildren(), true); } } @@ -57,7 +57,7 @@ HorizontalLayout LayoutHelper::String(const char * buffer, int bufferLen, const assert(bufferLen > 0); HorizontalLayout resultLayout = HorizontalLayout::Builder(); for (int i = 0; i < bufferLen; i++) { - resultLayout.addChildAtIndex(CharLayout(buffer[i], font), i, i, nullptr); + resultLayout.addChildAtIndex(CharLayout::Builder(buffer[i], font), i, i, nullptr); } return resultLayout; } diff --git a/poincare/src/least_common_multiple.cpp b/poincare/src/least_common_multiple.cpp index 0549f0a75..6096658d7 100644 --- a/poincare/src/least_common_multiple.cpp +++ b/poincare/src/least_common_multiple.cpp @@ -35,7 +35,7 @@ Evaluation LeastCommonMultipleNode::templatedApproximate(Context& context, Pr return Complex::Undefined(); } if (f1 == 0.0f || f2 == 0.0f) { - return Complex(0.0); + return Complex::Builder(0.0); } int a = (int)f2; int b = (int)f1; @@ -50,7 +50,14 @@ Evaluation LeastCommonMultipleNode::templatedApproximate(Context& context, Pr a = b; b = r; } - return Complex(product/a); + return Complex::Builder(product/a); +} + +LeastCommonMultiple LeastCommonMultiple::Builder(Expression child0, Expression child1) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(LeastCommonMultipleNode)); + LeastCommonMultipleNode * node = new (bufferNode) LeastCommonMultipleNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); + return static_cast(h); } Expression LeastCommonMultiple::shallowReduce() { @@ -64,13 +71,13 @@ Expression LeastCommonMultiple::shallowReduce() { Expression c1 = childAtIndex(1); #if MATRIX_EXACT_REDUCING if (c0.type() == Type::Matrix || c1.type() == Type::Matrix) { - return Undefined(); + return Undefined::Builder(); } #endif if (c0.type() == ExpressionNode::Type::Rational) { Rational r0 = static_cast(c0); if (!r0.integerDenominator().isOne()) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } @@ -78,7 +85,7 @@ Expression LeastCommonMultiple::shallowReduce() { if (c1.type() == ExpressionNode::Type::Rational) { Rational r1 = static_cast(c1); if (!r1.integerDenominator().isOne()) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } @@ -95,7 +102,7 @@ Expression LeastCommonMultiple::shallowReduce() { if (lcm.isOverflow()) { return *this; } - Expression result = Rational(lcm); + Expression result = Rational::Builder(lcm); replaceWithInPlace(result); return result; } diff --git a/poincare/src/left_parenthesis_layout.cpp b/poincare/src/left_parenthesis_layout.cpp index 8ddd2dea5..1ec811828 100644 --- a/poincare/src/left_parenthesis_layout.cpp +++ b/poincare/src/left_parenthesis_layout.cpp @@ -59,4 +59,11 @@ void LeftParenthesisLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expre RenderWithChildHeight(ParenthesisLayoutNode::ChildHeightGivenLayoutHeight(layoutSize().height()), ctx, p, expressionColor, backgroundColor); } +LeftParenthesisLayout LeftParenthesisLayout::Builder() { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(LeftParenthesisLayoutNode)); + LeftParenthesisLayoutNode * node = new (bufferNode) LeftParenthesisLayoutNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); +} + } diff --git a/poincare/src/left_square_bracket_layout.cpp b/poincare/src/left_square_bracket_layout.cpp index 2a8d85c92..7a64a0253 100644 --- a/poincare/src/left_square_bracket_layout.cpp +++ b/poincare/src/left_square_bracket_layout.cpp @@ -8,4 +8,11 @@ void LeftSquareBracketLayoutNode::render(KDContext * ctx, KDPoint p, KDColor exp ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y() + childHeight(), k_bracketWidth, k_lineThickness), expressionColor); } +LeftSquareBracketLayout LeftSquareBracketLayout::Builder() { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(LeftSquareBracketLayoutNode)); + LeftSquareBracketLayoutNode * node = new (bufferNode) LeftSquareBracketLayoutNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); +} + } diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 9e69d9de8..a2ed4480c 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -82,7 +83,14 @@ template Evaluation LogarithmNode<2>::templatedApproximate(Contex std::complex nc = (static_cast&>(n)).stdComplex(); result = DivisionNode::compute(computeOnComplex(xc, complexFormat, angleUnit).stdComplex(), computeOnComplex(nc, complexFormat, angleUnit).stdComplex(), complexFormat).stdComplex(); } - return Complex(result); + return Complex::Builder(result); +} + +CommonLogarithm CommonLogarithm::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(LogarithmNode<1>)); + LogarithmNode<1> * node = new (bufferNode) LogarithmNode<1>(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); } Expression CommonLogarithm::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target){ @@ -100,11 +108,18 @@ Expression CommonLogarithm::shallowReduce(Context & context, Preferences::Comple } #endif #endif - Logarithm log = Logarithm::Builder(childAtIndex(0), Rational(10)); + Logarithm log = Logarithm::Builder(childAtIndex(0), Rational::Builder(10)); replaceWithInPlace(log); return log.shallowReduce(context, complexFormat, angleUnit, target); } +Logarithm Logarithm::Builder(Expression child0, Expression child1) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(LogarithmNode<2>)); + LogarithmNode<2> * node = new (bufferNode) LogarithmNode<2>(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); + return static_cast(h); +} + Expression Logarithm::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target){ { Expression e = Expression::defaultShallowReduce(); @@ -116,7 +131,7 @@ Expression Logarithm::shallowReduce(Context & context, Preferences::ComplexForma #if MATRIX_EXACT_REDUCING #if 0 if (c.type() == ExpressionNode::Type::Matrix || childAtIndex(1).type() == ExpressionNode::Type::Matrix) { - return Undefined(); + return Undefined::Builder(); } #endif #endif @@ -196,7 +211,7 @@ Expression Logarithm::shallowReduce(Context & context, Preferences::ComplexForma Integer b = childAtIndex(1).convert().signedIntegerNumerator(); Integer newNumerator = simplifyLogarithmIntegerBaseInteger(r.signedIntegerNumerator(), b, a, false); Integer newDenomitor = simplifyLogarithmIntegerBaseInteger(r.integerDenominator(), b, a, true); - r = Rational(newNumerator, newDenomitor); + r = Rational::Builder(newNumerator, newDenomitor); } // log(r) = a0log(p0)+a1log(p1)+... with r = p0^a0*p1^a1*... (Prime decomposition) a.addChildAtIndexInPlace(splitLogarithmInteger(r.signedIntegerNumerator(), false, context, complexFormat, angleUnit, target), a.numberOfChildren(), a.numberOfChildren()); @@ -212,26 +227,26 @@ Expression Logarithm::simpleShallowReduce(Context & context, Preferences::Comple Expression b = childAtIndex(1); // log(0,0)->Undefined if (c.type() == ExpressionNode::Type::Rational && b.type() == ExpressionNode::Type::Rational && static_cast(b).isZero() && static_cast(c).isZero()) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } // log(x,1)->Undefined if (b.type() == ExpressionNode::Type::Rational && static_cast(b).isOne()) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } bool infiniteArg = c.recursivelyMatchesInfinity(context); // log(x,x)->1 with x != inf and log(inf,inf) = undef if (c.isIdenticalTo(b)) { - Expression result = infiniteArg ? Undefined().convert() : Rational(1).convert(); + Expression result = infiniteArg ? Undefined::Builder().convert() : Rational::Builder(1).convert(); replaceWithInPlace(result); return result; } // log(x,0)->0 with x != inf and log(inf,0) = undef if (b.type() == ExpressionNode::Type::Rational && static_cast(b).isZero()) { - Expression result = infiniteArg ? Undefined().convert() : Rational(0).convert(); + Expression result = infiniteArg ? Undefined::Builder().convert() : Rational::Builder(0).convert(); replaceWithInPlace(result); return result; } @@ -243,7 +258,7 @@ Expression Logarithm::simpleShallowReduce(Context & context, Preferences::Comple bool infiniteBase = b.recursivelyMatchesInfinity(context); // Special case: log(0,inf) -> undef if (infiniteBase) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } @@ -252,16 +267,16 @@ Expression Logarithm::simpleShallowReduce(Context & context, Preferences::Comple Evaluation baseApproximation = b.node()->approximate(1.0f, context, complexFormat, angleUnit); std::complex logDenominator = std::log10(static_cast&>(baseApproximation).stdComplex()); if (logDenominator.imag() != 0.0f || logDenominator.real() == 0.0f) { - result = Undefined(); + result = Undefined::Builder(); } isNegative = logDenominator.real() > 0.0; - result = result.isUninitialized() ? Infinity(isNegative) : result; + result = result.isUninitialized() ? Infinity::Builder(isNegative) : result; replaceWithInPlace(result); return result; } // log(1) = 0; if (r.isOne()) { - Expression result = Rational(0); + Expression result = Rational::Builder(0); replaceWithInPlace(result); return result; } @@ -297,7 +312,7 @@ Integer Logarithm::simplifyLogarithmIntegerBaseInteger(Integer i, Integer & base IntegerDivision div = Integer::Division(i, base); while (!div.quotient.isOverflow() && div.remainder.isZero()) { i = div.quotient; - a.addChildAtIndexInPlace(isDenominator ? Rational(-1) : Rational(1), a.numberOfChildren(), a.numberOfChildren()); // a++ + a.addChildAtIndexInPlace(isDenominator ? Rational::Builder(-1) : Rational::Builder(1), a.numberOfChildren(), a.numberOfChildren()); // a++ div = Integer::Division(i, base); } return i; @@ -310,17 +325,17 @@ Expression Logarithm::splitLogarithmInteger(Integer i, bool isDenominator, Conte Integer coefficients[Arithmetic::k_maxNumberOfPrimeFactors]; int numberOfPrimeFactors = Arithmetic::PrimeFactorization(i, factors, coefficients, Arithmetic::k_maxNumberOfPrimeFactors); if (numberOfPrimeFactors == 0) { - return Rational(0); + return Rational::Builder(0); } if (numberOfPrimeFactors < 0) { /* We could not break i in prime factor (either it might take too many * factors or too much time). */ Expression e = clone(); - e.replaceChildAtIndexInPlace(0, Rational(i)); + e.replaceChildAtIndexInPlace(0, Rational::Builder(i)); if (!isDenominator) { return e; } - Multiplication m = Multiplication::Builder(Rational(-1), e); + Multiplication m = Multiplication::Builder(Rational::Builder(-1), e); return m; } Addition a = Addition::Builder(); @@ -329,8 +344,8 @@ Expression Logarithm::splitLogarithmInteger(Integer i, bool isDenominator, Conte coefficients[index].setNegative(true); } Logarithm e = clone().convert(); - e.replaceChildAtIndexInPlace(0, Rational(factors[index])); - Multiplication m = Multiplication::Builder(Rational(coefficients[index]), e); + e.replaceChildAtIndexInPlace(0, Rational::Builder(factors[index])); + Multiplication m = Multiplication::Builder(Rational::Builder(coefficients[index]), e); e.simpleShallowReduce(context, complexFormat, angleUnit); a.addChildAtIndexInPlace(m, a.numberOfChildren(), a.numberOfChildren()); m.shallowReduce(context, complexFormat, angleUnit, target); @@ -340,13 +355,13 @@ Expression Logarithm::splitLogarithmInteger(Integer i, bool isDenominator, Conte Expression Logarithm::shallowBeautify() { assert(numberOfChildren() == 2); - Constant e = Constant(Ion::Charset::Exponential); + Constant e = Constant::Builder(Ion::Charset::Exponential); if (childAtIndex(1).isIdenticalTo(e)) { NaperianLogarithm np = NaperianLogarithm::Builder(childAtIndex(0)); replaceWithInPlace(np); return np; } - Rational ten(10); + Rational ten = Rational::Builder(10); if (childAtIndex(1).isIdenticalTo(ten)) { CommonLogarithm l = CommonLogarithm::Builder(childAtIndex(0)); replaceWithInPlace(l); diff --git a/poincare/src/matrix.cpp b/poincare/src/matrix.cpp index 66177d840..42e0bfad8 100644 --- a/poincare/src/matrix.cpp +++ b/poincare/src/matrix.cpp @@ -79,7 +79,7 @@ int MatrixNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloat template Evaluation MatrixNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { - MatrixComplex matrix; + MatrixComplex matrix = MatrixComplex::Builder(); for (ExpressionNode * c : children()) { matrix.addChildAtIndexInPlace(c->approximate(T(), context, complexFormat, angleUnit), matrix.numberOfChildren(), matrix.numberOfChildren()); } @@ -89,6 +89,13 @@ Evaluation MatrixNode::templatedApproximate(Context& context, Preferences::Co // MATRIX +Matrix Matrix::Builder() { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(MatrixNode)); + MatrixNode * node = new (bufferNode) MatrixNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); +} + void Matrix::setDimensions(int rows, int columns) { assert(rows * columns == numberOfChildren()); setNumberOfRows(rows); @@ -180,7 +187,7 @@ Matrix Matrix::rowCanonize(Context & context, Preferences::ComplexFormat complex // No non-null coefficient in this column, skip k++; // Update determinant: det *= 0 - if (!determinant.isUninitialized()) { determinant.addChildAtIndexInPlace(Rational(0), 0, determinant.numberOfChildren()); } + if (!determinant.isUninitialized()) { determinant.addChildAtIndexInPlace(Rational::Builder(0), 0, determinant.numberOfChildren()); } } else { // Swap row h and iPivot if (iPivot != h) { @@ -188,7 +195,7 @@ Matrix Matrix::rowCanonize(Context & context, Preferences::ComplexFormat complex swapChildrenInPlace(iPivot*n+col, h*n+col); } // Update determinant: det *= -1 - if (!determinant.isUninitialized()) { determinant.addChildAtIndexInPlace(Rational(-1), 0, determinant.numberOfChildren()); } + if (!determinant.isUninitialized()) { determinant.addChildAtIndexInPlace(Rational::Builder(-1), 0, determinant.numberOfChildren()); } } /* Set to 1 M[h][k] by linear combination */ Expression divisor = matrixChild(h, k); @@ -200,7 +207,7 @@ Matrix Matrix::rowCanonize(Context & context, Preferences::ComplexFormat complex replaceChildAtIndexInPlace(h*n+j, newOpHJ); newOpHJ = newOpHJ.shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::System); } - replaceChildInPlace(divisor, Rational(1)); + replaceChildInPlace(divisor, Rational::Builder(1)); /* Set to 0 all M[i][j] i != h, j > k by linear combination */ for (int i = 0; i < m; i++) { @@ -213,7 +220,7 @@ Matrix Matrix::rowCanonize(Context & context, Preferences::ComplexFormat complex newOpIJ.childAtIndex(1).shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::System); newOpIJ = newOpIJ.shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::System); } - replaceChildAtIndexInPlace(i*n+k, Rational(0)); + replaceChildAtIndexInPlace(i*n+k, Rational::Builder(0)); } h++; k++; @@ -292,7 +299,7 @@ Matrix Matrix::createIdentity(int dim) { Matrix matrix(); for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { - matrix.addChildAtIndexInPlace(i == j ? Rational(1) : Rational(0), i*dim+j, i*dim+j); + matrix.addChildAtIndexInPlace(i == j ? Rational::Builder(1) : Rational::Builder(0), i*dim+j, i*dim+j); } } matrix.setDimensions(dim, dim); @@ -301,7 +308,7 @@ Matrix Matrix::createIdentity(int dim) { Expression Matrix::inverse(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { if (m_numberOfRows != m_numberOfColumns) { - return Undefined(); + return Undefined::Builder(); } int dim = m_numberOfRows; /* Create the matrix inv = (A|I) with A the input matrix and I the dim identity matrix */ @@ -311,7 +318,7 @@ Expression Matrix::inverse(Context & context, Preferences::ComplexFormat complex AI.addChildAtIndexInPlace(matrixChild(i, j), i*2*dim+j, i*2*dim+j); } for (int j = dim; j < 2*dim; j++) { - AI.addChildAtIndexInPlace(j-dim == i ? Rational(1) : Rational(0), i*2*dim+j, i*2*dim+j); + AI.addChildAtIndexInPlace(j-dim == i ? Rational::Builder(1) : Rational::Builder(0), i*2*dim+j, i*2*dim+j); } } AI.setDimensions(dim, 2*dim); @@ -319,7 +326,7 @@ Expression Matrix::inverse(Context & context, Preferences::ComplexFormat complex // Check inversibility for (int i = 0; i < dim; i++) { if (AI.matrixChild(i, i)->type() != ExpressionNode::Type::Rational || !static_cast(AI.matrixChild(i, i)->node())->isOne()) { - return Undefined(); + return Undefined::Builder(); } } Matrix inverse(); diff --git a/poincare/src/matrix_complex.cpp b/poincare/src/matrix_complex.cpp index 7e7d34906..416b194ea 100644 --- a/poincare/src/matrix_complex.cpp +++ b/poincare/src/matrix_complex.cpp @@ -44,7 +44,7 @@ Expression MatrixComplexNode::complexToExpression(Preferences::ComplexFormat if (c->type() == EvaluationNode::Type::Complex) { matrix.addChildAtIndexInPlace(c->complexToExpression(complexFormat), i, i); } else { - matrix.addChildAtIndexInPlace(Undefined(), i, i); + matrix.addChildAtIndexInPlace(Undefined::Builder(), i, i); } i++; } @@ -100,7 +100,7 @@ MatrixComplex MatrixComplexNode::inverse() const { if (result == 0) { /* Intentionally swapping dimensions for inverse, although it doesn't make a * difference because it is square. */ - return MatrixComplex(operandsCopy, m_numberOfColumns, m_numberOfRows); + return MatrixComplex::Builder(operandsCopy, m_numberOfColumns, m_numberOfRows); } return MatrixComplex::Undefined(); } @@ -108,10 +108,10 @@ MatrixComplex MatrixComplexNode::inverse() const { template MatrixComplex MatrixComplexNode::transpose() const { // Intentionally swapping dimensions for transpose - MatrixComplex result; + MatrixComplex result = MatrixComplex::Builder(); for (int j = 0; j < numberOfColumns(); j++) { for (int i = 0; i < numberOfRows(); i++) { - result.addChildAtIndexInPlace(Complex(complexAtIndex(i*numberOfColumns()+j)), result.numberOfChildren(), result.numberOfChildren()); + result.addChildAtIndexInPlace(Complex::Builder(complexAtIndex(i*numberOfColumns()+j)), result.numberOfChildren(), result.numberOfChildren()); } } result.setDimensions(numberOfColumns(), numberOfRows()); @@ -121,30 +121,35 @@ MatrixComplex MatrixComplexNode::transpose() const { // MATRIX COMPLEX REFERENCE template -MatrixComplex::MatrixComplex(std::complex * operands, int numberOfRows, int numberOfColumns) : - MatrixComplex() -{ +MatrixComplex MatrixComplex::Builder(std::complex * operands, int numberOfRows, int numberOfColumns) { + MatrixComplex m = MatrixComplex::Builder(); for (int i=0; i(operands[i]), i, i); + m.addChildAtIndexInPlace(Complex::Builder(operands[i]), i, i); } - setDimensions(numberOfRows, numberOfColumns); + m.setDimensions(numberOfRows, numberOfColumns); + return m; } template -MatrixComplex::MatrixComplex() : Evaluation(TreePool::sharedPool()->createTreeNode >()) {} +MatrixComplex MatrixComplex::Builder() { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(MatrixComplexNode)); + MatrixComplexNode * node = new (bufferNode) MatrixComplexNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast &>(h); +} template MatrixComplex MatrixComplex::Undefined() { std::complex undef = std::complex(NAN, NAN); - return MatrixComplex((std::complex *)&undef, 1, 1); + return MatrixComplex::Builder((std::complex *)&undef, 1, 1); } template MatrixComplex MatrixComplex::createIdentity(int dim) { - MatrixComplex result; + MatrixComplex result = MatrixComplex::Builder(); for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { - Complex c = i == j ? Complex(1.0) : Complex(0.0); + Complex c = i == j ? Complex::Builder(1.0) : Complex::Builder(0.0); result.addChildAtIndexInPlace(c, i*dim+j, i*dim+j); } } diff --git a/poincare/src/matrix_dimension.cpp b/poincare/src/matrix_dimension.cpp index d9cd3e758..24e1e273e 100644 --- a/poincare/src/matrix_dimension.cpp +++ b/poincare/src/matrix_dimension.cpp @@ -34,7 +34,14 @@ Evaluation MatrixDimensionNode::templatedApproximate(Context& context, Prefer operands[0] = std::complex(1.0); operands[1] = std::complex(1.0); } - return MatrixComplex(operands, 1, 2); + return MatrixComplex::Builder(operands, 1, 2); +} + +MatrixDimension MatrixDimension::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(MatrixDimensionNode)); + MatrixDimensionNode * node = new (bufferNode) MatrixDimensionNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); } Expression MatrixDimension::shallowReduce() { @@ -49,15 +56,15 @@ Expression MatrixDimension::shallowReduce() { if (c.type() == ExpressionNode::Type::Matrix) { Matrix m = static_cast(c); Matrix result = Matrix::Builder(); - result.addChildAtIndexInPlace(Rational(m.numberOfRows()), 0, 0); - result.addChildAtIndexInPlace(Rational(m.numberOfColumns()), 1, 1); + result.addChildAtIndexInPlace(Rational::Builder(m.numberOfRows()), 0, 0); + result.addChildAtIndexInPlace(Rational::Builder(m.numberOfColumns()), 1, 1); result.setDimensions(1, 2); return result; } if (!c.recursivelyMatches(Expression::IsMatrix)) { Matrix result = Matrix::Builder(); - result.addChildAtIndexInPlace(Rational(1), 0, 0); - result.addChildAtIndexInPlace(Rational(1), 1, 1); + result.addChildAtIndexInPlace(Rational::Builder(1), 0, 0); + result.addChildAtIndexInPlace(Rational::Builder(1), 1, 1); result.setDimensions(1, 2); return result; } @@ -65,8 +72,8 @@ Expression MatrixDimension::shallowReduce() { #else if (c.type() != ExpressionNode::Type::Matrix) { Matrix result = Matrix::Builder(); - result.addChildAtIndexInPlace(Rational(1), 0, 0); - result.addChildAtIndexInPlace(Rational(1), 1, 1); + result.addChildAtIndexInPlace(Rational::Builder(1), 0, 0); + result.addChildAtIndexInPlace(Rational::Builder(1), 1, 1); result.setDimensions(1, 2); replaceWithInPlace(result); return result; diff --git a/poincare/src/matrix_inverse.cpp b/poincare/src/matrix_inverse.cpp index 16e29a94a..d12e8164d 100644 --- a/poincare/src/matrix_inverse.cpp +++ b/poincare/src/matrix_inverse.cpp @@ -34,7 +34,7 @@ Evaluation MatrixInverseNode::templatedApproximate(Context& context, Preferen if (input.type() == EvaluationNode::Type::MatrixComplex) { inverse = static_cast&>(input).inverse(); } else if (input.type() == EvaluationNode::Type::Complex) { - inverse = Complex(std::complex(1)/(static_cast&>(input).stdComplex())); + inverse = Complex::Builder(std::complex(1)/(static_cast&>(input).stdComplex())); } if (inverse.isUninitialized()) { inverse = Complex::Undefined(); @@ -42,6 +42,13 @@ Evaluation MatrixInverseNode::templatedApproximate(Context& context, Preferen return inverse; } +MatrixInverse MatrixInverse::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(MatrixInverseNode)); + MatrixInverseNode * node = new (bufferNode) MatrixInverseNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); +} + Expression MatrixInverse::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { Expression e = Expression::defaultShallowReduce(); @@ -53,19 +60,19 @@ Expression MatrixInverse::shallowReduce(Context & context, Preferences::ComplexF #if MATRIX_EXACT_REDUCING #if 0 if (!c.recursivelyMatches(Expression::IsMatrix)) { - return Power::Builder(c, Rational(-1).shallowReduce(context, complexFormat, angleUnit, target); + return Power::Builder(c, Rational::Builder(-1).shallowReduce(context, complexFormat, angleUnit, target); } if (c.type() == ExpressionNode::Type::Matrix) { Matrix mat = static_cast(c); if (mat.numberOfRows() != mat.numberOfColumns()) { - return Undefined(); + return Undefined::Builder(); } } return *this; #endif #else if (c.type() != ExpressionNode::Type::Matrix) { - Expression result = Power::Builder(c, Rational(-1)); + Expression result = Power::Builder(c, Rational::Builder(-1)); replaceWithInPlace(result); result = result.shallowReduce(context, complexFormat, angleUnit, target); return result; diff --git a/poincare/src/matrix_layout.cpp b/poincare/src/matrix_layout.cpp index 32d07c60f..e184fc8f1 100644 --- a/poincare/src/matrix_layout.cpp +++ b/poincare/src/matrix_layout.cpp @@ -266,4 +266,11 @@ void MatrixLayoutNode::didReplaceChildAtIndex(int index, LayoutCursor * cursor, } } +MatrixLayout MatrixLayout::Builder() { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(MatrixLayoutNode)); + MatrixLayoutNode * node = new (bufferNode) MatrixLayoutNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); +} + } diff --git a/poincare/src/matrix_trace.cpp b/poincare/src/matrix_trace.cpp index 6fcf1a326..1ff3c58a1 100644 --- a/poincare/src/matrix_trace.cpp +++ b/poincare/src/matrix_trace.cpp @@ -28,10 +28,17 @@ int MatrixTraceNode::serialize(char * buffer, int bufferSize, Preferences::Print template Evaluation MatrixTraceNode::templatedApproximate(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { Evaluation input = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); - Complex result = Complex(input.trace()); + Complex result = Complex::Builder(input.trace()); return result; } +MatrixTrace MatrixTrace::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(MatrixTraceNode)); + MatrixTraceNode * node = new (bufferNode) MatrixTraceNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); +} + Expression MatrixTrace::shallowReduce() { { Expression e = Expression::defaultShallowReduce(); @@ -45,10 +52,10 @@ Expression MatrixTrace::shallowReduce() { if (c.type() == ExpressionNode::Type::Matrix) { Matrix m = static_cast(c); if (m.numberOfRows() != m.numberOfColumns()) { - return Undefined(); + return Undefined::Builder(); } int n = m.numberOfRows(); - Addition a = Addition(); + Addition a = Addition::Builder(); for (int i = 0; i < n; i++) { a.addChildAtIndexInPlace(m.childAtIndex(i+n*i), i, a.numberOfChildren()); } diff --git a/poincare/src/matrix_transpose.cpp b/poincare/src/matrix_transpose.cpp index b85a71918..c7e01c7be 100644 --- a/poincare/src/matrix_transpose.cpp +++ b/poincare/src/matrix_transpose.cpp @@ -37,6 +37,13 @@ Evaluation MatrixTransposeNode::templatedApproximate(Context& context, Prefer return transpose; } +MatrixTranspose MatrixTranspose::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(MatrixTransposeNode)); + MatrixTransposeNode * node = new (bufferNode) MatrixTransposeNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); +} + Expression MatrixTranspose::shallowReduce() { { Expression e = Expression::defaultShallowReduce(); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 7e927711f..f87398e91 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -52,14 +52,14 @@ MatrixComplex MultiplicationNode::computeOnMatrices(const MatrixComplex m, if (m.numberOfColumns() != n.numberOfRows()) { return MatrixComplex::Undefined(); } - MatrixComplex result; + MatrixComplex result = MatrixComplex::Builder(); for (int i = 0; i < m.numberOfRows(); i++) { for (int j = 0; j < n.numberOfColumns(); j++) { std::complex c(0.0); for (int k = 0; k < m.numberOfColumns(); k++) { c += m.complexAtIndex(i*m.numberOfColumns()+k)*n.complexAtIndex(k*n.numberOfColumns()+j); } - result.addChildAtIndexInPlace(Complex(c), i*n.numberOfColumns()+j, result.numberOfChildren()); + result.addChildAtIndexInPlace(Complex::Builder(c), i*n.numberOfColumns()+j, result.numberOfChildren()); } } result.setDimensions(m.numberOfRows(), n.numberOfColumns()); @@ -108,6 +108,21 @@ Expression MultiplicationNode::denominator(Context & context, Preferences::Compl /* Multiplication */ +Multiplication Multiplication::Builder() { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(AdditionNode)); + MultiplicationNode * node = new (bufferNode) MultiplicationNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); +} + +Multiplication Multiplication::Builder(Expression * children, size_t numberOfChildren) { + Multiplication m = Multiplication::Builder(); + for (int i = 0; i < numberOfChildren; i++) { + m.addChildAtIndexInPlace(children[i], i, i); + } + return m; +} + template void Multiplication::computeOnArrays(T * m, T * n, T * result, int mNumberOfColumns, int mNumberOfRows, int nNumberOfColumns) { for (int i = 0; i < mNumberOfRows; i++) { @@ -204,9 +219,9 @@ int Multiplication::getPolynomialCoefficients(Context & context, const char * sy } // Initialization of coefficients for (int i = 1; i <= deg; i++) { - coefficients[i] = Rational(0); + coefficients[i] = Rational::Builder(0); } - coefficients[0] = Rational(1); + coefficients[0] = Rational::Builder(1); Expression intermediateCoefficients[Expression::k_maxNumberOfPolynomialCoefficients]; // Let's note result = a(0)+a(1)*X+a(2)*X^2+a(3)*x^3+.. @@ -292,7 +307,7 @@ Expression Multiplication::privateShallowReduce(Context & context, Preferences:: int on = currentMatrix->numberOfRows(); int om = currentMatrix->numberOfColumns(); if (om != n) { - return replaceWith(new Undefined(), true); + return replaceWith(new Undefined::Builder(), true); } // Create the matrix resulting of the multiplication of the current matrix and the result matrix /* resultMatrix @@ -316,7 +331,7 @@ Expression Multiplication::privateShallowReduce(Context & context, Preferences:: * */ Expression ** newMatrixOperands = new Expression * [on*m]; for (int e = 0; e < on*m; e++) { - newMatrixOperands[e] = new Addition(); + newMatrixOperands[e] = new Addition::Builder(); int i2 = e%m; int i1 = e/m; for (int j = 0; j < n; j++) { @@ -622,10 +637,10 @@ void Multiplication::addMissingFactors(Expression factor, Context & context, Pre assert(childAtIndex(0).convert().integerDenominator().isOne()); Integer lcm = Arithmetic::LCM(static_cast(factor).unsignedIntegerNumerator(), childAtIndex(0).convert().unsignedIntegerNumerator()); if (lcm.isOverflow()) { - addChildAtIndexInPlace(Rational(static_cast(factor).unsignedIntegerNumerator()), 1, numberOfChildren()); + addChildAtIndexInPlace(Rational::Builder(static_cast(factor).unsignedIntegerNumerator()), 1, numberOfChildren()); return; } - replaceChildAtIndexInPlace(0, Rational(lcm)); + replaceChildAtIndexInPlace(0, Rational::Builder(lcm)); return; } if (factor.type() != ExpressionNode::Type::Rational) { @@ -683,7 +698,7 @@ void Multiplication::factorizeSineAndCosine(int i, int j, Context & context, Pre childAtIndex(j).shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); } else { // Replace cos(x)^q by tan(x)^(-q) - Expression newPower = Power::Builder(tan, Number::Multiplication(q, Rational(-1))); + Expression newPower = Power::Builder(tan, Number::Multiplication(q, Rational::Builder(-1))); newPower.childAtIndex(1).shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); replaceChildAtIndexInPlace(j, newPower); newPower.shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); @@ -712,7 +727,7 @@ bool Multiplication::HaveSameNonNumeralFactors(const Expression & e1, const Expr } const Expression Multiplication::CreateExponent(Expression e) { - Expression result = e.type() == ExpressionNode::Type::Power ? e.childAtIndex(1).clone() : Rational(1); + Expression result = e.type() == ExpressionNode::Type::Power ? e.childAtIndex(1).clone() : Rational::Builder(1); return result; } @@ -747,11 +762,11 @@ Expression Multiplication::mergeNegativePower(Context & context, Preferences::Co // Special case for rational p/q: if q != 1, q should be at denominator if (childAtIndex(0).type() == ExpressionNode::Type::Rational && !childAtIndex(0).convert().integerDenominator().isOne()) { Rational r = childAtIndex(0).convert(); - m.addChildAtIndexInPlace(Rational(r.integerDenominator()), 0, m.numberOfChildren()); + m.addChildAtIndexInPlace(Rational::Builder(r.integerDenominator()), 0, m.numberOfChildren()); if (r.signedIntegerNumerator().isOne()) { removeChildAtIndexInPlace(0); } else { - replaceChildAtIndexInPlace(0, Rational(r.signedIntegerNumerator())); + replaceChildAtIndexInPlace(0, Rational::Builder(r.signedIntegerNumerator())); } } int i = 0; @@ -778,7 +793,7 @@ Expression Multiplication::mergeNegativePower(Context & context, Preferences::Co return *this; } m.sortChildrenInPlace([](const ExpressionNode * e1, const ExpressionNode * e2, bool canBeInterrupted) { return ExpressionNode::SimplificationOrder(e1, e2, true, canBeInterrupted); }, true); - Power p = Power::Builder(m.squashUnaryHierarchyInPlace(), Rational(-1)); + Power p = Power::Builder(m.squashUnaryHierarchyInPlace(), Rational::Builder(-1)); addChildAtIndexInPlace(p, 0, numberOfChildren()); sortChildrenInPlace([](const ExpressionNode * e1, const ExpressionNode * e2, bool canBeInterrupted) { return ExpressionNode::SimplificationOrder(e1, e2, true, canBeInterrupted); }, true); return squashUnaryHierarchyInPlace(); diff --git a/poincare/src/naperian_logarithm.cpp b/poincare/src/naperian_logarithm.cpp index 351c359b6..520dd5f3d 100644 --- a/poincare/src/naperian_logarithm.cpp +++ b/poincare/src/naperian_logarithm.cpp @@ -22,6 +22,13 @@ Expression NaperianLogarithmNode::shallowReduce(Context & context, Preferences:: return NaperianLogarithm(this).shallowReduce(context, complexFormat, angleUnit, target); } +NaperianLogarithm NaperianLogarithm::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(NaperianLogarithmNode)); + NaperianLogarithmNode * node = new (bufferNode) NaperianLogarithmNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); +} + Expression NaperianLogarithm::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { Expression e = Expression::defaultShallowReduce(); @@ -34,7 +41,7 @@ Expression NaperianLogarithm::shallowReduce(Context & context, Preferences::Comp return SimplificationHelper::Map(*this, context, angleUnit); } #endif - Logarithm l = Logarithm::Builder(childAtIndex(0), Constant(Ion::Charset::Exponential)); + Logarithm l = Logarithm::Builder(childAtIndex(0), Constant::Builder(Ion::Charset::Exponential)); replaceWithInPlace(l); return l.shallowReduce(context, complexFormat, angleUnit, target); } diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index 5c1cac751..ecb3b2b18 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -54,7 +54,7 @@ Evaluation NthRootNode::templatedApproximate(Context& context, Preferences::C Complex absBasePowIndex = PowerNode::compute(absBasec, std::complex(1.0)/(indexc), complexFormat); // q odd if (-1)^q = -1 if (std::pow((T)-1.0, (T)indexc.real()) < 0.0) { - return basec.real() < 0 ? Complex(-absBasePowIndex.stdComplex()) : absBasePowIndex; + return basec.real() < 0 ? Complex::Builder(-absBasePowIndex.stdComplex()) : absBasePowIndex; } } } @@ -63,6 +63,13 @@ Evaluation NthRootNode::templatedApproximate(Context& context, Preferences::C return result; } +NthRoot NthRoot::Builder(Expression child0, Expression child1) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(NthRootNode)); + NthRootNode * node = new (bufferNode) NthRootNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); + return static_cast(h); +} + Expression NthRoot::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { Expression e = Expression::defaultShallowReduce(); @@ -72,10 +79,10 @@ Expression NthRoot::shallowReduce(Context & context, Preferences::ComplexFormat } #if MATRIX_EXACT_REDUCING if (childAtIndex(0).type() == ExpressionNode::Type::Matrix || childAtIndex(1).type() == ExpressionNode:Type::Matrix) { - return Undefined(); + return Undefined::Builder(); } #endif - Expression invIndex = Power::Builder(childAtIndex(1), Rational(-1)); + Expression invIndex = Power::Builder(childAtIndex(1), Rational::Builder(-1)); Power p = Power::Builder(childAtIndex(0), invIndex); invIndex.shallowReduce(context, complexFormat, angleUnit, target); replaceWithInPlace(p); diff --git a/poincare/src/nth_root_layout.cpp b/poincare/src/nth_root_layout.cpp index b19ea55d2..59cab9af3 100644 --- a/poincare/src/nth_root_layout.cpp +++ b/poincare/src/nth_root_layout.cpp @@ -270,4 +270,18 @@ void NthRootLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionCol } } +NthRootLayout NthRootLayout::Builder(Layout child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(NthRootLayoutNode)); + NthRootLayoutNode * node = new (bufferNode) NthRootLayoutNode(false); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); +} + +NthRootLayout NthRootLayout::Builder(Layout child, Layout index) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(NthRootLayoutNode)); + NthRootLayoutNode * node = new (bufferNode) NthRootLayoutNode(true); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child, index).array(), 2); + return static_cast(h); +} + } diff --git a/poincare/src/number.cpp b/poincare/src/number.cpp index 16e8501db..bd5c613af 100644 --- a/poincare/src/number.cpp +++ b/poincare/src/number.cpp @@ -42,7 +42,7 @@ Number Number::ParseNumber(const char * integralPart, size_t integralLength, con if (exponentLength == 0 && decimalLenght == 0) { Integer i(integralPart, integralLength, false); if (!i.isOverflow()) { - return Rational(i); + return Rational::Builder(i); } } int exp; @@ -55,32 +55,32 @@ Number Number::ParseNumber(const char * integralPart, size_t integralLength, con // Avoid Decimal with exponent > k_maxExponentLength if (exponentLength >= Decimal::k_maxExponentLength || exp > Decimal::k_maxExponent || exp < -Decimal::k_maxExponent) { if (exp < 0) { - return Decimal(0.0); + return Decimal::Builder(0.0); } else { - return Infinity(false); + return Infinity::Builder(false); } } - return Decimal(integralPart, integralLength, decimalPart, decimalLenght, exp); + return Decimal::Builder(integralPart, integralLength, decimalPart, decimalLenght, exp); } template Number Number::DecimalNumber(T f) { if (std::isnan(f)) { - return Undefined(); + return Undefined::Builder(); } if (std::isinf(f)) { - return Infinity(f < 0.0); + return Infinity::Builder(f < 0.0); } - return Decimal(f); + return Decimal::Builder(f); } Number Number::FloatNumber(double d) { if (std::isnan(d)) { - return Undefined(); + return Undefined::Builder(); } else if (std::isinf(d)) { - return Infinity(d < 0.0); + return Infinity::Builder(d < 0.0); } else { - return Float(d); + return Float::Builder(d); } } @@ -112,7 +112,7 @@ Number Number::Power(const Number & i, const Number & j) { [](const Rational & i, const Rational & j) { if (!j.integerDenominator().isOne()) { // We return an overflown result to reach the escape case Float+Float - return Rational(Integer::Overflow(false)); + return Rational::Builder(Integer::Overflow(false)); } return Rational::IntegerPower(i, j.signedIntegerNumerator()); }, diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index 12aa72853..9d2d33613 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -41,7 +41,7 @@ bool OppositeNode::childNeedsParenthesis(const TreeNode * child) const { } Layout OppositeNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { - HorizontalLayout result = HorizontalLayout::Builder(CharLayout('-')); + HorizontalLayout result = HorizontalLayout::Builder(CharLayout::Builder('-')); if (childAtIndex(0)->type() == Type::Opposite) { result.addOrMergeChildAtIndex(LayoutHelper::Parentheses(childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits), false), 1, false); } else { @@ -69,6 +69,19 @@ Expression OppositeNode::shallowReduce(Context & context, Preferences::ComplexFo /* Simplification */ +Opposite Opposite::Builder() { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(OppositeNode)); + OppositeNode * node = new (bufferNode) OppositeNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); +} + +Opposite Opposite::Builder(Expression child) { + Opposite d = Opposite::Builder(); + d.replaceChildAtIndexInPlace(0, child); + return d; +} + Expression Opposite::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { Expression result = Expression::defaultShallowReduce(); if (result.isUndefined()) { @@ -77,7 +90,7 @@ Expression Opposite::shallowReduce(Context & context, Preferences::ComplexFormat Expression child = result.childAtIndex(0); #if MATRIX_EXACT_REDUCING #endif - result = Multiplication::Builder(Rational(-1), child); + result = Multiplication::Builder(Rational::Builder(-1), child); replaceWithInPlace(result); return result.shallowReduce(context, complexFormat, angleUnit, target); } diff --git a/poincare/src/parenthesis.cpp b/poincare/src/parenthesis.cpp index 4fd94f1b8..ce87f1b89 100644 --- a/poincare/src/parenthesis.cpp +++ b/poincare/src/parenthesis.cpp @@ -25,6 +25,13 @@ Evaluation ParenthesisNode::templatedApproximate(Context& context, Preference return childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); } +Parenthesis Parenthesis::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(ParenthesisNode)); + ParenthesisNode * node = new (bufferNode) ParenthesisNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); +} + Expression Parenthesis::shallowReduce() { Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { diff --git a/poincare/src/parsing/parser.cpp b/poincare/src/parsing/parser.cpp index ae1024e34..0925f4f4a 100644 --- a/poincare/src/parsing/parser.cpp +++ b/poincare/src/parsing/parser.cpp @@ -164,7 +164,7 @@ void Parser::parseEmpty(Expression & leftHandSide, Token::Type stoppingType) { m_status = Status::Error; //FIXME return; } - leftHandSide = EmptyExpression(); + leftHandSide = EmptyExpression::Builder(); } void Parser::parseMinus(Expression & leftHandSide, Token::Type stoppingType) { @@ -220,7 +220,7 @@ void Parser::parseEqual(Expression & leftHandSide, Token::Type stoppingType) { if (parseBinaryOperator(leftHandSide, rightHandSide, Token::Equal)) { /* We parse until finding a token of lesser precedence than Equal. The next * token is thus either EndOfStream or Store. */ - leftHandSide = Equal(leftHandSide, rightHandSide); + leftHandSide = Equal::Builder(leftHandSide, rightHandSide); } if (!m_nextToken.is(Token::EndOfStream)) { m_status = Status::Error; // Equal should be top-most expression in Tree @@ -323,7 +323,7 @@ bool Parser::currentTokenIsSpecialIdentifier() const { } void Parser::parseConstant(Expression & leftHandSide, Token::Type stoppingType) { - leftHandSide = Constant(m_currentToken.text()[0]); + leftHandSide = Constant::Builder(m_currentToken.text()[0]); isThereImplicitMultiplication(); } @@ -360,12 +360,12 @@ void Parser::parseSequence(Expression & leftHandSide, const char name, Token::Ty if (m_status != Status::Progress) { } else if (!popTokenIfType(rightDelimiter)) { m_status = Status::Error; // Right delimiter missing. - } else if (rank.isIdenticalTo(Symbol("n",1))) { + } else if (rank.isIdenticalTo(Symbol::Builder("n",1))) { char sym[5] = {name, '(', 'n', ')', 0}; - leftHandSide = Symbol(sym, 4); - } else if (rank.isIdenticalTo(Addition::Builder(Symbol("n",1),Rational("1")))) { + leftHandSide = Symbol::Builder(sym, 4); + } else if (rank.isIdenticalTo(Addition::Builder(Symbol::Builder("n",1),Rational::Builder("1")))) { char sym[7] = {name, '(', 'n', '+', '1', ')', 0}; - leftHandSide = Symbol(sym, 6); + leftHandSide = Symbol::Builder(sym, 6); } else { m_status = Status::Error; // Unexpected parameter. } @@ -376,11 +376,11 @@ void Parser::parseSpecialIdentifier(Expression & leftHandSide) { if (m_currentToken.compareTo(Symbol::k_ans) == 0) { leftHandSide = Symbol::Ans(); } else if (m_currentToken.compareTo(Infinity::Name()) == 0) { - leftHandSide = Infinity(false); + leftHandSide = Infinity::Builder(false); } else if (m_currentToken.compareTo(Undefined::Name()) == 0) { - leftHandSide = Undefined(); + leftHandSide = Undefined::Builder(); } else if (m_currentToken.compareTo(Unreal::Name()) == 0) { - leftHandSide = Unreal(); + leftHandSide = Unreal::Builder(); } else if (m_currentToken.compareTo("u_") == 0 || m_currentToken.compareTo("v_") == 0) { // Special case for sequences (e.g. "u_{n}") parseSequence(leftHandSide, m_currentToken.text()[0], Token::LeftBrace, Token::RightBrace); } else if (m_currentToken.compareTo("u") == 0 || m_currentToken.compareTo("v") == 0) { // Special case for sequences (e.g. "u(n)") @@ -412,7 +412,7 @@ void Parser::parseCustomIdentifier(Expression & leftHandSide, const char * name, return; } if (!popTokenIfType(Token::LeftParenthesis)) { - leftHandSide = Symbol(name, length); + leftHandSide = Symbol::Builder(name, length); return; } Expression parameter = parseCommaSeparatedList(); @@ -430,7 +430,7 @@ void Parser::parseCustomIdentifier(Expression & leftHandSide, const char * name, } else if (!popTokenIfType(Token::RightParenthesis)) { m_status = Status::Error; // Right parenthesis missing. } else { - leftHandSide = Function(name, length, parameter); + leftHandSide = Function::Builder(name, length, parameter); } } diff --git a/poincare/src/permute_coefficient.cpp b/poincare/src/permute_coefficient.cpp index 61b77a357..767295862 100644 --- a/poincare/src/permute_coefficient.cpp +++ b/poincare/src/permute_coefficient.cpp @@ -37,16 +37,23 @@ Evaluation PermuteCoefficientNode::templatedApproximate(Context& context, Pre return Complex::Undefined(); } if (k > n) { - return Complex(0.0); + return Complex::Builder(0.0); } T result = 1; for (int i = (int)n-(int)k+1; i <= (int)n; i++) { result *= i; if (std::isinf(result) || std::isnan(result)) { - return Complex(result); + return Complex::Builder(result); } } - return Complex(std::round(result)); + return Complex::Builder(std::round(result)); +} + +PermuteCoefficient PermuteCoefficient::Builder(Expression child0, Expression child1) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(PermuteCoefficientNode)); + PermuteCoefficientNode * node = new (bufferNode) PermuteCoefficientNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); + return static_cast(h); } Expression PermuteCoefficient::shallowReduce() { @@ -60,13 +67,13 @@ Expression PermuteCoefficient::shallowReduce() { Expression c1 = childAtIndex(1); #if MATRIX_EXACT_REDUCING if (c0.type() == ExpressionNode::Type::Matrix || c1.type() == ExpressionNode::Type::Matrix) { - return replaceWith(new Undefined(), true); + return replaceWith(new Undefined::Builder(), true); } #endif if (c0.type() == ExpressionNode::Type::Rational) { Rational r0 = static_cast(c0); if (!r0.integerDenominator().isOne() || r0.sign() == ExpressionNode::Sign::Negative) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } @@ -74,7 +81,7 @@ Expression PermuteCoefficient::shallowReduce() { if (c1.type() == ExpressionNode::Type::Rational) { Rational r1 = static_cast(c1); if (!r1.integerDenominator().isOne() || r1.sign() == ExpressionNode::Sign::Negative) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } @@ -88,7 +95,7 @@ Expression PermuteCoefficient::shallowReduce() { Integer n = r0.unsignedIntegerNumerator(); Integer k = r1.unsignedIntegerNumerator(); if (n.isLowerThan(k)) { - Expression result = Rational(0); + Expression result = Rational::Builder(0); replaceWithInPlace(result); return result; } @@ -104,7 +111,7 @@ Expression PermuteCoefficient::shallowReduce() { result = Integer::Multiplication(result, factor); } assert(!result.isOverflow()); // < permute(k_maxNValue, k_maxNValue-1)~10^158 - Expression rationalResult = Rational(result); + Expression rationalResult = Rational::Builder(result); replaceWithInPlace(rationalResult); return rationalResult; diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 620dcc3e7..2384d25f9 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -123,7 +123,7 @@ Complex PowerNode::compute(const std::complex c, const std::complex d, * avoid weird results as e(i*pi) = -1+6E-17*i, we compute the argument of * the result of c^d and if arg ~ 0 [Pi], we discard the residual imaginary * part and if arg ~ Pi/2 [Pi], we discard the residual real part. */ - return Complex(ApproximationHelper::TruncateRealOrImaginaryPartAccordingToArgument(result)); + return Complex::Builder(ApproximationHelper::TruncateRealOrImaginaryPartAccordingToArgument(result)); } // Layout @@ -162,8 +162,6 @@ int PowerNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatM return SerializationHelper::Infix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, "^"); } - - // Simplify Expression PowerNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { @@ -179,7 +177,7 @@ int PowerNode::simplificationOrderGreaterType(const ExpressionNode * e, bool asc if (baseComparison != 0) { return baseComparison; } - Rational one(1); + Rational one = Rational::Builder(1); return SimplificationOrder(childAtIndex(1), one.node(), ascending, canBeInterrupted); } @@ -206,7 +204,7 @@ template MatrixComplex PowerNode::computeOnMatrixAndComplex(const if (m.numberOfRows() != m.numberOfColumns()) { return MatrixComplex::Undefined(); } - T power = Complex(d).toScalar(); + T power = Complex::Builder(d).toScalar(); if (std::isnan(power) || std::isinf(power) || power != (int)power || std::fabs(power) > k_maxApproximatePowerMatrix) { return MatrixComplex::Undefined(); } @@ -215,7 +213,7 @@ template MatrixComplex PowerNode::computeOnMatrixAndComplex(const if (inverse.isUninitialized()) { return MatrixComplex::Undefined(); } - Complex minusC = Complex(-d); + Complex minusC = Complex::Builder(-d); MatrixComplex result = PowerNode::computeOnMatrixAndComplex(inverse, minusC.stdComplex(), complexFormat); return result; } @@ -236,6 +234,13 @@ template MatrixComplex PowerNode::computeOnMatrices(const MatrixC // Power +Power Power::Builder(Expression base, Expression exponent) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(PowerNode)); + PowerNode * node = new (bufferNode) PowerNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(base, exponent).array(), 2); + return static_cast(h); +} + Expression Power::setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { assert(s == ExpressionNode::Sign::Positive); if (childAtIndex(0).sign(context) == ExpressionNode::Sign::Negative) { @@ -268,9 +273,9 @@ int Power::getPolynomialCoefficients(Context & context, const char * symbolName, int n = num.extractedInt(); if (n <= k_maxPolynomialDegree) { for (int i = 0; i < n; i++) { - coefficients[i] = Rational(0); + coefficients[i] = Rational::Builder(0); } - coefficients[n] = Rational(1); + coefficients[n] = Rational::Builder(1); return n; } } @@ -290,16 +295,16 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co #if 0 /* Step 0: get rid of matrix */ if (childAtIndex(1)->type() == ExpressionNode::Type::Matrix) { - return replaceWith(new Undefined(), true); + return replaceWith(new Undefined::Builder(), true); } if (childAtIndex(0)->type() == ExpressionNode::Type::Matrix) { Matrix * mat = static_cast(childAtIndex(0)); if (childAtIndex(1)->type() != ExpressionNode::Type::Rational || !static_cast(childAtIndex(1))->denominator().isOne()) { - return replaceWith(new Undefined(), true); + return replaceWith(new Undefined::Builder(), true); } Integer exponent = static_cast(childAtIndex(1))->numerator(); if (mat->numberOfRows() != mat->numberOfColumns()) { - return replaceWith(new Undefined(), true); + return replaceWith(new Undefined::Builder(), true); } if (exponent.isNegative()) { childAtIndex(1)->setSign(Sign::Positive, context, complexFormat, angleUnit); @@ -346,7 +351,7 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co if (b.isZero()) { // 0^0 = undef or (±inf)^0 = undef if ((childAtIndex(0).type() == ExpressionNode::Type::Rational && childAtIndex(0).convert().isZero()) || childAtIndex(0).type() == ExpressionNode::Type::Infinity) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } @@ -356,7 +361,7 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co * we replace x^0 by one. This is almost always true except when x = 0. * However, not substituting x^0 by one would prevent from simplifying * many expressions like x/x->1. */ - Expression result = Rational(1); + Expression result = Rational::Builder(1); replaceWithInPlace(result); return result; } @@ -374,20 +379,20 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co if (a.isZero()) { // 0^x with x > 0 = 0 if (childAtIndex(1).sign(&context) == ExpressionNode::Sign::Positive) { - Expression result = Rational(0); + Expression result = Rational::Builder(0); replaceWithInPlace(result); return result; } // 0^x with x < 0 = undef if (childAtIndex(1).sign(&context) == ExpressionNode::Sign::Negative) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } } // 1^x = 1 if x != ±inf if (a.isOne() && !childAtIndex(1).recursivelyMatchesInfinity(context)) { - Expression result = Rational(1); + Expression result = Rational::Builder(1); replaceWithInPlace(result); return result; } @@ -443,8 +448,8 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co if ((!letPowerAtRoot && base.isReal(context) && index.type() == ExpressionNode::Type::ComplexCartesian) || (!letPowerAtRoot && base.type() == ExpressionNode::Type::ComplexCartesian && index.isReal(context)) || (!letPowerAtRoot && base.type() == ExpressionNode::Type::ComplexCartesian && index.type() == ExpressionNode::Type::ComplexCartesian)) { - complexBase = base.type() == ExpressionNode::Type::ComplexCartesian ? static_cast(base) : ComplexCartesian::Builder(base, Rational(0)); - complexIndex = index.type() == ExpressionNode::Type::ComplexCartesian ? static_cast(index) : ComplexCartesian::Builder(index, Rational(0)); + complexBase = base.type() == ExpressionNode::Type::ComplexCartesian ? static_cast(base) : ComplexCartesian::Builder(base, Rational::Builder(0)); + complexIndex = index.type() == ExpressionNode::Type::ComplexCartesian ? static_cast(index) : ComplexCartesian::Builder(index, Rational::Builder(0)); result = complexBase.power(complexIndex, context, complexFormat, angleUnit, target); replaceWithInPlace(result); return result.shallowReduce(); @@ -464,7 +469,7 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co const Rational b = childAtIndex(1).convert(); // i^(p/q) if (childAtIndex(0).type() == ExpressionNode::Type::Constant && childAtIndex(0).convert().isIComplex()) { - Number r = Number::Multiplication(b, Rational(1, 2)); + Number r = Number::Multiplication(b, Rational::Builder(1, 2)); Expression result = CreateComplexExponent(r, context, complexFormat, angleUnit, target); replaceWithInPlace(result); return result.shallowReduce(context, complexFormat, angleUnit, target); @@ -476,13 +481,13 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co Expression result; if (childAtIndex(1).sign(&context) == ExpressionNode::Sign::Negative) { // --> 0 if x < 0 - result = Rational(0); + result = Rational::Builder(0); } else if (childAtIndex(1).sign(&context) == ExpressionNode::Sign::Positive) { // --> (±inf) if x > 0 - result = Infinity(false); + result = Infinity::Builder(false); if (childAtIndex(0).sign(&context) == ExpressionNode::Sign::Negative) { // (-inf)^x --> (-1)^x*inf - Power p(Rational(-1), childAtIndex(1)); + Power p = Power::Builder(Rational::Builder(-1), childAtIndex(1)); result = Multiplication::Builder(p, result); p.shallowReduce(context, complexFormat, angleUnit, target); } @@ -520,10 +525,10 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co if (!m0.isUninitialized()) { replaceChildAtIndexInPlace(0, m0); // m0 doest not need to be shallowReduce as makePositiveAnyNegativeNumeralFactor returns a reduced expression - Multiplication m1; + Multiplication m1 = Multiplication::Builder(); replaceWithInPlace(m1); // Multiply m1 by i complex - Constant i(Ion::Charset::IComplex); + Constant i = Constant::Builder(Ion::Charset::IComplex); m1.addChildAtIndexInPlace(i, 0, 0); i.shallowReduce(context, complexFormat, angleUnit, target); m1.addChildAtIndexInPlace(*this, 1, 1); @@ -537,7 +542,7 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co Expression i = m.childAtIndex(m.numberOfChildren()-2); static_cast(m).removeChildAtIndexInPlace(m.numberOfChildren()-2); if (angleUnit == Preferences::AngleUnit::Degree) { - m.replaceChildAtIndexInPlace(m.numberOfChildren()-1, Rational(180)); + m.replaceChildAtIndexInPlace(m.numberOfChildren()-1, Rational::Builder(180)); } Expression cos = Cosine::Builder(m); m = m.shallowReduce(context, complexFormat, angleUnit, target); @@ -612,7 +617,7 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co // (sign(a)*b*...)^r if (factor.sign(&context) == ExpressionNode::Sign::Negative) { - m.replaceChildAtIndexInPlace(i, Rational(-1)); + m.replaceChildAtIndexInPlace(i, Rational::Builder(-1)); factor = factor.setSign(ExpressionNode::Sign::Positive, &context, complexFormat, angleUnit, target); } else { m.removeChildAtIndexInPlace(i); @@ -633,7 +638,7 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co } } } - // Step 12: a^(p/q+c+...) -> Rational(a^p)*a^(1/q+c+...) with a rational and a != 0 and p, q integers + // Step 12: a^(p/q+c+...) -> Rational::Builder(a^p)*a^(1/q+c+...) with a rational and a != 0 and p, q integers if (!letPowerAtRoot && childAtIndex(0).type() == ExpressionNode::Type::Rational && !childAtIndex(0).convert().isZero() @@ -729,7 +734,7 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co } } if (nr.sign() == ExpressionNode::Sign::Negative) { - nr.replaceWithInPlace(Rational(-1)); + nr.replaceWithInPlace(Rational::Builder(-1)); return shallowReduce(context, complexFormat, angleUnit, target); } else { replaceWithInPlace(result); @@ -750,11 +755,11 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co int clippedN = n.extractedInt(); // Authorized because n < k_maxExpandedBinome < k_maxNValue Expression * x0 = childAtIndex(0)->childAtIndex(0); Expression * x1 = childAtIndex(0)->childAtIndex(1); - Addition * a = new Addition(); + Addition * a = new Addition::Builder(); for (int i = 0; i <= clippedN; i++) { - Rational * r = new Rational(static_cast(BinomialCoefficient::compute(static_cast(i), static_cast(clippedN)))); - Power * p0 = new Power::Builder(x0->clone(), new Rational(i), false); - Power * p1 = new Power::Builder(x1->clone(), new Rational(clippedN-i), false); + Rational * r = new Rational::Builder(static_cast(BinomialCoefficient::compute(static_cast(i), static_cast(clippedN)))); + Power * p0 = new Power::Builder(x0->clone(), new Rational::Builder(i), false); + Power * p1 = new Power::Builder(x1->clone(), new Rational::Builder(clippedN-i), false); const Expression * operands[3] = {r, p0, p1}; Multiplication * m = new Multiplication::Builder(operands, 3, false); p0->shallowReduce(context, complexFormat, angleUnit, target); @@ -763,7 +768,7 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co m->shallowReduce(context, complexFormat, angleUnit, target); } if (nr->sign(&context) == Sign::Negative) { - nr->replaceWith(new Rational(-1), true); + nr->replaceWith(new Rational::Builder(-1), true); childAtIndex(0)->replaceWith(a, true)->shallowReduce(context, complexFormat, angleUnit, target); return shallowReduce(context, complexFormat, angleUnit, target); } else { @@ -779,7 +784,7 @@ Expression Power::shallowBeautify(Context & context, Preferences::ComplexFormat Expression p = denominator(context, complexFormat, angleUnit); // If the denominator is initialized, the index of the power is of form -y if (!p.isUninitialized()) { - Division d = Division::Builder(Rational(1), p); + Division d = Division::Builder(Rational::Builder(1), p); p.shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); replaceWithInPlace(d); return d.shallowBeautify(context, complexFormat, angleUnit, target); @@ -793,7 +798,7 @@ Expression Power::shallowBeautify(Context & context, Preferences::ComplexFormat replaceWithInPlace(result); return result; } - Expression result = NthRoot::Builder(childAtIndex(0), Rational(index)); + Expression result = NthRoot::Builder(childAtIndex(0), Rational::Builder(index)); replaceWithInPlace(result); return result; } @@ -806,8 +811,8 @@ Expression Power::shallowBeautify(Context & context, Preferences::ComplexFormat if (target == ExpressionNode::ReductionTarget::System && childAtIndex(1).type() == ExpressionNode::Type::Rational) { Integer p = childAtIndex(1).convert().signedIntegerNumerator(); Integer q = childAtIndex(1).convert().integerDenominator(); - Expression nthRoot = q.isOne() ? childAtIndex(0) : NthRoot::Builder(childAtIndex(0), Rational(q)); - Expression result = p.isOne() ? nthRoot : Power::Builder(nthRoot, Rational(p)); + Expression nthRoot = q.isOne() ? childAtIndex(0) : NthRoot::Builder(childAtIndex(0), Rational::Builder(q)); + Expression result = p.isOne() ? nthRoot : Power::Builder(nthRoot, Rational::Builder(p)); replaceWithInPlace(result); return result; } @@ -895,7 +900,7 @@ Expression Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational r, bo assert(!i.isZero()); assert(r.sign() == ExpressionNode::Sign::Positive); if (i.isOne()) { - return Rational(1); + return Rational::Builder(1); } Integer factors[Arithmetic::k_maxNumberOfPrimeFactors]; Integer coefficients[Arithmetic::k_maxNumberOfPrimeFactors]; @@ -904,7 +909,7 @@ Expression Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational r, bo /* We could not break i in prime factors (it might take either too many * factors or too much time). */ Expression rClone = r.clone().setSign(isDenominator ? ExpressionNode::Sign::Negative : ExpressionNode::Sign::Positive, &context, complexFormat, angleUnit, target); - return Power::Builder(Rational(i), rClone); + return Power::Builder(Rational::Builder(i), rClone); } Integer r1(1); @@ -917,18 +922,18 @@ Expression Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational r, bo } if (r2.isOverflow() || r1.isOverflow()) { // we overflow Integer at one point: we abort - return Power::Builder(Rational(i), r.clone()); + return Power::Builder(Rational::Builder(i), r.clone()); } - Rational p1 = Rational(r2); + Rational p1 = Rational::Builder(r2); Integer oneExponent = isDenominator ? Integer(-1) : Integer(1); Integer rDenominator = r.integerDenominator(); - Rational p2 = Rational(oneExponent, rDenominator); + Rational p2 = Rational::Builder(oneExponent, rDenominator); Power p = Power::Builder(p1, p2); if (r1.isEqualTo(Integer(1)) && !i.isNegative()) { return p; } Integer one(1); - Rational r3 = isDenominator ? Rational(one, r1) : Rational(r1); + Rational r3 = isDenominator ? Rational::Builder(one, r1) : Rational::Builder(r1); Multiplication m = Multiplication::Builder(); m.addChildAtIndexInPlace(r3, 0, 0); if (!r2.isOne()) { @@ -942,9 +947,9 @@ Expression Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational r, bo * - has no real solution otherwise */ if (!r.unsignedIntegerNumerator().isEven()) { if (r.integerDenominator().isEven()) { - return Unreal(); + return Unreal::Builder(); } else { - m.addChildAtIndexInPlace(Rational(-1), 0, m.numberOfChildren()); + m.addChildAtIndexInPlace(Rational::Builder(-1), 0, m.numberOfChildren()); } } } else { @@ -977,12 +982,12 @@ Expression Power::removeSquareRootsFromDenominator(Context & context, Preference if (pq.isOverflow()) { return result; } - Power sqrt = Power::Builder(Rational(pq), Rational(1, 2)); + Power sqrt = Power::Builder(Rational::Builder(pq), Rational::Builder(1, 2)); Integer one(1); if (castedChild1.isHalf()) { - result = Multiplication::Builder(Rational(one, q), sqrt); + result = Multiplication::Builder(Rational::Builder(one, q), sqrt); } else { - result = Multiplication::Builder(Rational(one, p), sqrt); // We use here the assertion that p != 0 + result = Multiplication::Builder(Rational::Builder(one, p), sqrt); // We use here the assertion that p != 0 } sqrt.shallowReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); } @@ -1032,16 +1037,16 @@ Expression Power::removeSquareRootsFromDenominator(Context & context, Preference // Compute the numerator Integer pq1 = Integer::Multiplication(p1, q1); Integer pq2 = Integer::Multiplication(p2, q2); - Power sqrt1 = Power::Builder(Rational(pq1), Rational(1, 2)); - Power sqrt2 = Power::Builder(Rational(pq2), Rational(1, 2)); + Power sqrt1 = Power::Builder(Rational::Builder(pq1), Rational::Builder(1, 2)); + Power sqrt2 = Power::Builder(Rational::Builder(pq2), Rational::Builder(1, 2)); Integer factor1 = Integer::Multiplication( Integer::Multiplication(n1, d1), Integer::Multiplication(Integer::Power(d2, Integer(2)), q2)); - Multiplication m1 = Multiplication::Builder(Rational(factor1), sqrt1); + Multiplication m1 = Multiplication::Builder(Rational::Builder(factor1), sqrt1); Integer factor2 = Integer::Multiplication( Integer::Multiplication(n2, d2), Integer::Multiplication(Integer::Power(d1, Integer(2)), q1)); - Multiplication m2 = Multiplication::Builder(Rational(factor2), sqrt2); + Multiplication m2 = Multiplication::Builder(Rational::Builder(factor2), sqrt2); Expression numerator; if (denominator.isNegative()) { numerator = Subtraction::Builder(m2, m1); @@ -1054,7 +1059,7 @@ Expression Power::removeSquareRootsFromDenominator(Context & context, Preference } numerator = numerator.deepReduce(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User); Integer one(1); - result = Multiplication::Builder(numerator, Rational(one, denominator)); + result = Multiplication::Builder(numerator, Rational::Builder(one, denominator)); } if (!result.isUninitialized()) { @@ -1123,13 +1128,13 @@ bool Power::isNthRootOfUnity() const { Expression Power::equivalentExpressionUsingStandardExpression() const { if (childAtIndex(1).type() == ExpressionNode::Type::Rational) { if (childAtIndex(1).convert().isMinusOne()) { - return Division::Builder(Rational(1), childAtIndex(0).clone()); + return Division::Builder(Rational::Builder(1), childAtIndex(0).clone()); } if (childAtIndex(1).convert().isHalf()) { return SquareRoot::Builder(childAtIndex(0).clone()); } if (childAtIndex(1).convert().isMinusHalf()) { - return Division::Builder(Rational(1), SquareRoot::Builder(childAtIndex(0).clone())); + return Division::Builder(Rational::Builder(1), SquareRoot::Builder(childAtIndex(0).clone())); } } return Expression(); @@ -1137,17 +1142,17 @@ Expression Power::equivalentExpressionUsingStandardExpression() const { Expression Power::CreateComplexExponent(const Expression & r, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { // Returns e^(i*pi*r) - const Constant exp = Constant(Ion::Charset::Exponential); - Constant iComplex = Constant(Ion::Charset::IComplex); - const Constant pi = Constant(Ion::Charset::SmallPi); + const Constant exp = Constant::Builder(Ion::Charset::Exponential); + Constant iComplex = Constant::Builder(Ion::Charset::IComplex); + const Constant pi = Constant::Builder(Ion::Charset::SmallPi); Multiplication mExp = Multiplication::Builder(iComplex, pi, r.clone()); iComplex.shallowReduce(context, complexFormat, angleUnit, target); - Power p(exp, mExp); + Power p = Power::Builder(exp, mExp); mExp.shallowReduce(context, complexFormat, angleUnit, target); return p; #if 0 - const Constant iComplex = Constant(Ion::Charset::IComplex); - const Constant pi = Constant(Ion::Charset::SmallPi); + const Constant iComplex = Constant::Builder(Ion::Charset::IComplex); + const Constant pi = Constant::Builder(Ion::Charset::SmallPi); Expression op = Multiplication::Builder(pi, r).shallowReduce(context, complexFormat, angleUnit, false); Cosine cos = Cosine(op).shallowReduce(context, complexFormat, angleUnit, false);; Sine sin = Sine(op).shallowReduce(context, complexFormat, angleUnit, false); @@ -1183,7 +1188,7 @@ bool Power::TermIsARationalSquareRootOrRational(const Expression & e) { const Rational Power::RadicandInExpression(const Expression & e) { if (e.type() == ExpressionNode::Type::Rational) { - return Rational(1); + return Rational::Builder(1); } else if (e.type() == ExpressionNode::Type::Power) { assert(e.type() == ExpressionNode::Type::Power); assert(e.childAtIndex(0).type() == ExpressionNode::Type::Rational); @@ -1200,7 +1205,7 @@ const Rational Power::RationalFactorInExpression(const Expression & e) { if (e.type() == ExpressionNode::Type::Rational) { return static_cast(e); } else if (e.type() == ExpressionNode::Type::Power) { - return Rational(1); + return Rational::Builder(1); } else { assert(e.type() == ExpressionNode::Type::Multiplication); assert(e.childAtIndex(0).type() == ExpressionNode::Type::Rational); diff --git a/poincare/src/prediction_interval.cpp b/poincare/src/prediction_interval.cpp index fd8074ee3..7f95e0f84 100644 --- a/poincare/src/prediction_interval.cpp +++ b/poincare/src/prediction_interval.cpp @@ -43,7 +43,14 @@ Evaluation PredictionIntervalNode::templatedApproximate(Context& context, Pre std::complex operands[2]; operands[0] = std::complex(p - 1.96*std::sqrt(p*(1.0-p))/std::sqrt(n)); operands[1] = std::complex(p + 1.96*std::sqrt(p*(1.0-p))/std::sqrt(n)); - return MatrixComplex(operands, 1, 2); + return MatrixComplex::Builder(operands, 1, 2); +} + +PredictionInterval PredictionInterval::Builder(Expression child0, Expression child1) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(PredictionIntervalNode)); + PredictionIntervalNode * node = new (bufferNode) PredictionIntervalNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); + return static_cast(h); } Expression PredictionInterval::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { @@ -57,13 +64,13 @@ Expression PredictionInterval::shallowReduce(Context & context, Preferences::Com Expression c1 = childAtIndex(1); #if MATRIX_EXACT_REDUCING if (c0.type() == ExpressionNode::Type::Matrix || c1.type() == ExpressionNode::Type::Matrix) { - return Undefined(); + return Undefined::Builder(); } #endif if (c0.type() == ExpressionNode::Type::Rational) { Rational r0 = static_cast(c0); if (r0.sign() == ExpressionNode::Sign::Negative || Integer::NaturalOrder(r0.unsignedIntegerNumerator(), r0.integerDenominator()) > 0) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } @@ -71,7 +78,7 @@ Expression PredictionInterval::shallowReduce(Context & context, Preferences::Com if (c1.type() == ExpressionNode::Type::Rational) { Rational r1 = static_cast(c1); if (!r1.integerDenominator().isOne() || r1.sign() == ExpressionNode::Sign::Negative) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } @@ -82,7 +89,7 @@ Expression PredictionInterval::shallowReduce(Context & context, Preferences::Com Rational r0 = static_cast(c0); Rational r1 = static_cast(c1); if (!r1.integerDenominator().isOne() || r1.sign() == ExpressionNode::Sign::Negative || r0.sign() == ExpressionNode::Sign::Negative || Integer::NaturalOrder(r0.unsignedIntegerNumerator(), r0.integerDenominator()) > 0) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } @@ -90,15 +97,15 @@ Expression PredictionInterval::shallowReduce(Context & context, Preferences::Com // Compute numerator = r0*(1-r0) Integer factorNumerator = Integer::Subtraction(r0.integerDenominator(), r0.unsignedIntegerNumerator()); Integer factorDenominator = r0.integerDenominator(); - Rational numerator = Rational::Multiplication(r0, Rational(factorNumerator, factorDenominator)); + Rational numerator = Rational::Multiplication(r0, Rational::Builder(factorNumerator, factorDenominator)); if (numerator.numeratorOrDenominatorIsInfinity()) { return *this; } // Compute sqr = sqrt(r0*(1-r0)/r1) - Expression sqr = Power::Builder(Division::Builder(numerator, r1), Rational(1, 2)); - Expression m = Multiplication::Builder(Rational(196, 100), sqr); + Expression sqr = Power::Builder(Division::Builder(numerator, r1), Rational::Builder(1, 2)); + Expression m = Multiplication::Builder(Rational::Builder(196, 100), sqr); Matrix matrix = Matrix::Builder(); - matrix.addChildAtIndexInPlace(Addition::Builder(r0.clone(), Multiplication::Builder(Rational(-1), m.clone())), 0, 0); + matrix.addChildAtIndexInPlace(Addition::Builder(r0.clone(), Multiplication::Builder(Rational::Builder(-1), m.clone())), 0, 0); matrix.addChildAtIndexInPlace(Addition::Builder(r0.clone(), m), 1, 1); matrix.setDimensions(1, 2); replaceWithInPlace(matrix); diff --git a/poincare/src/product.cpp b/poincare/src/product.cpp index f855e9974..bb422b85d 100644 --- a/poincare/src/product.cpp +++ b/poincare/src/product.cpp @@ -31,7 +31,7 @@ Evaluation ProductNode::templatedApproximateWithNextTerm(Evaluation a, Eva if (a.type() == EvaluationNode::Type::Complex && b.type() == EvaluationNode::Type::Complex) { Complex c = static_cast&>(a); Complex d = static_cast&>(b); - return Complex(c.stdComplex()*d.stdComplex()); + return Complex::Builder(c.stdComplex()*d.stdComplex()); } if (a.type() == EvaluationNode::Type::Complex) { Complex c = static_cast &>(a); @@ -46,4 +46,11 @@ Evaluation ProductNode::templatedApproximateWithNextTerm(Evaluation a, Eva return MultiplicationNode::computeOnMatrices(m, n, complexFormat); } +Product Product::Builder(Expression child0, Symbol child1, Expression child2, Expression child3) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(ProductNode)); + ProductNode * node = new (bufferNode) ProductNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1, child2, child3).array(), 4); + return static_cast(h); +} + } diff --git a/poincare/src/product_layout.cpp b/poincare/src/product_layout.cpp index 8be05d651..3685b81f9 100644 --- a/poincare/src/product_layout.cpp +++ b/poincare/src/product_layout.cpp @@ -30,4 +30,11 @@ void ProductLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionCol SequenceLayoutNode::render(ctx, p, expressionColor, backgroundColor); } +ProductLayout ProductLayout::Builder(Layout argument, Layout variable, Layout lowerB, Layout upperB) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(ProductLayoutNode)); + ProductLayoutNode * node = new (bufferNode) ProductLayoutNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(argument, variable, lowerB, upperB).array(), 4); + return static_cast(h); +} + } diff --git a/poincare/src/randint.cpp b/poincare/src/randint.cpp index 269e0a1a4..645e1ca88 100644 --- a/poincare/src/randint.cpp +++ b/poincare/src/randint.cpp @@ -34,7 +34,14 @@ template Evaluation RandintNode::templateApproximate(Context & c } T result = std::floor(Random::random()*(b+1.0-a)+a); - return Complex(result); + return Complex::Builder(result); +} + +Randint Randint::Builder(Expression child0, Expression child1) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(RandintNode)); + RandintNode * node = new (bufferNode) RandintNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); + return static_cast(h); } } diff --git a/poincare/src/random.cpp b/poincare/src/random.cpp index e31bde088..3d8e0e546 100644 --- a/poincare/src/random.cpp +++ b/poincare/src/random.cpp @@ -26,7 +26,14 @@ int RandomNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloat } template Evaluation RandomNode::templateApproximate() const { - return Complex(Random::random()); + return Complex::Builder(Random::random()); +} + +Random Random::Builder() { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(RandomNode)); + RandomNode * node = new (bufferNode) RandomNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); } Expression Random::setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index 504aa05cf..3247d5c2d 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -15,10 +15,11 @@ namespace Poincare { /* Rational Node */ -void RationalNode::setDigits(const native_uint_t * numeratorDigits, uint8_t numeratorSize, const native_uint_t * denominatorDigits, uint8_t denominatorSize, bool negative) { - m_negative = negative; - m_numberOfDigitsNumerator = numeratorSize; - m_numberOfDigitsDenominator = denominatorSize; +RationalNode::RationalNode(const native_uint_t * numeratorDigits, uint8_t numeratorSize, const native_uint_t * denominatorDigits, uint8_t denominatorSize, bool negative) : + m_negative(negative), + m_numberOfDigitsNumerator(numeratorSize), + m_numberOfDigitsDenominator(denominatorSize) +{ if (numeratorDigits) { memcpy(m_digits, numeratorDigits, numeratorSize*sizeof(native_uint_t)); } @@ -27,20 +28,6 @@ void RationalNode::setDigits(const native_uint_t * numeratorDigits, uint8_t nume } } -void RationalNode::initToMatchSize(size_t goalSize) { - assert(goalSize != sizeof(RationalNode)); - int digitsSize = goalSize - sizeof(RationalNode); - assert(digitsSize%sizeof(native_uint_t) == 0); - /* We are initing the Rational to match a specific size. The built rational - * is dummy. However, we cannot assign to m_numberOfDigitsNumerator (or - * m_numberOfDigitsDenominator) values that are aboce k_maxNumberOfDigits. - * To prevent that, we evenly separe digits between numerator and denominator. */ - size_t numberOfDigits = digitsSize/sizeof(native_uint_t); - m_numberOfDigitsNumerator = numberOfDigits/2; - m_numberOfDigitsDenominator = numberOfDigits-m_numberOfDigitsNumerator; - assert(size() == goalSize); -} - Integer RationalNode::signedNumerator() const { return Integer::BuildInteger((native_uint_t *)m_digits, m_numberOfDigitsNumerator, m_negative); } @@ -163,7 +150,7 @@ Expression RationalNode::denominator(Context & context, Preferences::ComplexForm // Constructors -Rational::Rational(Integer & num, Integer & den) : Number() { +Rational Rational::Builder(Integer & num, Integer & den) { assert(!den.isZero()); if (!num.isOne() && !den.isOne()) { // Avoid computing GCD if possible @@ -172,34 +159,33 @@ Rational::Rational(Integer & num, Integer & den) : Number() { den = Integer::Division(den, gcd).quotient; } bool negative = (!num.isNegative() && den.isNegative()) || (!den.isNegative() && num.isNegative()); - new (this) Rational(num.digits(), num.numberOfDigits(), den.digits(), den.numberOfDigits(), negative); + return Rational::Builder(num.digits(), num.numberOfDigits(), den.digits(), den.numberOfDigits(), negative); } -Rational::Rational(const Integer & numerator) : Number() { +Rational Rational::Builder(const Integer & numerator) { native_uint_t one = 1; - new (this) Rational(numerator.digits(), numerator.numberOfDigits(), &one, 1, numerator.isNegative()); + return Rational::Builder(numerator.digits(), numerator.numberOfDigits(), &one, 1, numerator.isNegative()); } -Rational::Rational(native_int_t i) : Number() { +Rational Rational::Builder(native_int_t i) { native_uint_t one = 1; if (i == 0) { - new (this) Rational(nullptr, 0, &one, 1, false); - return; + return Rational::Builder(nullptr, 0, &one, 1, false); } native_uint_t absI = i < 0 ? -i : i; - new (this) Rational(&absI, 1, &one, 1, i < 0); + return Rational::Builder(&absI, 1, &one, 1, i < 0); } -Rational::Rational(native_int_t i, native_int_t j) : Number() { +Rational Rational::Builder(native_int_t i, native_int_t j) { Integer iInteger(i); Integer jInteger(j); - new (this) Rational(iInteger, jInteger); + return Rational::Builder(iInteger, jInteger); } -Rational::Rational(const char * iString, const char * jString) : Number() { +Rational Rational::Builder(const char * iString, const char * jString) { Integer iInteger(iString); Integer jInteger(jString); - new (this) Rational(iInteger, jInteger); + return Rational::Builder(iInteger, jInteger); } bool Rational::numeratorOrDenominatorIsInfinity() const { @@ -211,13 +197,13 @@ bool Rational::numeratorOrDenominatorIsInfinity() const { Rational Rational::Addition(const Rational & i, const Rational & j) { Integer newNumerator = Integer::Addition(Integer::Multiplication(i.signedIntegerNumerator(), j.integerDenominator()), Integer::Multiplication(j.signedIntegerNumerator(), i.integerDenominator())); Integer newDenominator = Integer::Multiplication(i.integerDenominator(), j.integerDenominator()); - return Rational(newNumerator, newDenominator); + return Rational::Builder(newNumerator, newDenominator); } Rational Rational::Multiplication(const Rational & i, const Rational & j) { Integer newNumerator = Integer::Multiplication(i.signedIntegerNumerator(), j.signedIntegerNumerator()); Integer newDenominator = Integer::Multiplication(i.integerDenominator(), j.integerDenominator()); - return Rational(newNumerator, newDenominator); + return Rational::Builder(newNumerator, newDenominator); } Rational Rational::IntegerPower(const Rational & i, const Integer & j) { @@ -226,15 +212,16 @@ Rational Rational::IntegerPower(const Rational & i, const Integer & j) { Integer newNumerator = Integer::Power(i.signedIntegerNumerator(), absJ); Integer newDenominator = Integer::Power(i.integerDenominator(), absJ); if (j.isNegative()) { - return Rational(newDenominator, newNumerator); + return Rational::Builder(newDenominator, newNumerator); } - return Rational(newNumerator, newDenominator); + return Rational::Builder(newNumerator, newDenominator); } -Rational::Rational(const native_uint_t * i, uint8_t numeratorSize, const native_uint_t * j, uint8_t denominatorSize, bool negative) : - Number(TreePool::sharedPool()->createTreeNode(RationalSize(numeratorSize, denominatorSize))) -{ - static_cast(node())->setDigits(i, numeratorSize, j, denominatorSize, negative); +Rational Rational::Builder(const native_uint_t * i, uint8_t numeratorSize, const native_uint_t * j, uint8_t denominatorSize, bool negative) { + void * bufferNode = TreePool::sharedPool()->alloc(RationalSize(numeratorSize, denominatorSize)); + RationalNode * node = new (bufferNode) RationalNode(i, numeratorSize, j, denominatorSize, negative); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); } Expression Rational::shallowReduce() { @@ -246,17 +233,17 @@ Expression Rational::shallowReduce() { #if 0 if (unsignedIntegerNumerator().isOverflow() && integerDenominator().isOverflow()) { assert(false); - return Undefined(); + return Undefined::Builder(); } // Turn into Infinite if the numerator is too big. if (unsignedIntegerNumerator().isOverflow()) { assert(false); - return Infinity(sign(&context) == ExpressionNode::Sign::Negative); + return Infinity::Builder(sign(&context) == ExpressionNode::Sign::Negative); } // Turn into 0 if the denominator is too big. if (integerDenominator().isOverflow()) { assert(false); - return Rational(0); + return Rational::Builder(0); } #endif assert(!numeratorOrDenominatorIsInfinity()); @@ -280,9 +267,9 @@ Expression Rational::denominator(Context & context, Preferences::ComplexFormat c return Expression(); } if (d.isOverflow()) { - return Infinity(false); + return Infinity::Builder(false); } - return Rational(d); + return Rational::Builder(d); } Expression Rational::setSign(ExpressionNode::Sign s) { diff --git a/poincare/src/real_part.cpp b/poincare/src/real_part.cpp index 4d5e58c7e..95cf8534b 100644 --- a/poincare/src/real_part.cpp +++ b/poincare/src/real_part.cpp @@ -24,6 +24,13 @@ Expression RealPartNode::shallowReduce(Context & context, Preferences::ComplexFo return RealPart(this).shallowReduce(context, complexFormat, angleUnit, target); } +RealPart RealPart::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(RealPartNode)); + RealPartNode * node = new (bufferNode) RealPartNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); +} + Expression RealPart::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { Expression e = Expression::defaultShallowReduce(); diff --git a/poincare/src/right_parenthesis_layout.cpp b/poincare/src/right_parenthesis_layout.cpp index d38345f20..68a267f96 100644 --- a/poincare/src/right_parenthesis_layout.cpp +++ b/poincare/src/right_parenthesis_layout.cpp @@ -59,4 +59,11 @@ void RightParenthesisLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expr RenderWithChildHeight(ParenthesisLayoutNode::ChildHeightGivenLayoutHeight(layoutSize().height()), ctx, p, expressionColor, backgroundColor); } +RightParenthesisLayout RightParenthesisLayout::Builder() { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(RightParenthesisLayoutNode)); + RightParenthesisLayoutNode * node = new (bufferNode) RightParenthesisLayoutNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); +} + } diff --git a/poincare/src/right_square_bracket_layout.cpp b/poincare/src/right_square_bracket_layout.cpp index cd1608a02..3707312fe 100644 --- a/poincare/src/right_square_bracket_layout.cpp +++ b/poincare/src/right_square_bracket_layout.cpp @@ -8,4 +8,11 @@ void RightSquareBracketLayoutNode::render(KDContext * ctx, KDPoint p, KDColor ex ctx->fillRect(KDRect(p.x()+k_widthMargin-k_bracketWidth+1, p.y() + childHeight(), k_bracketWidth, k_lineThickness), expressionColor); } +RightSquareBracketLayout RightSquareBracketLayout::Builder() { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(RightSquareBracketLayoutNode)); + RightSquareBracketLayoutNode * node = new (bufferNode) RightSquareBracketLayoutNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); +} + } diff --git a/poincare/src/round.cpp b/poincare/src/round.cpp index f0205ef19..5fc95311c 100644 --- a/poincare/src/round.cpp +++ b/poincare/src/round.cpp @@ -35,7 +35,14 @@ Evaluation RoundNode::templatedApproximate(Context& context, Preferences::Com return Complex::Undefined(); } T err = std::pow(10, std::floor(f2)); - return Complex(std::round(f1*err)/err); + return Complex::Builder(std::round(f1*err)/err); +} + +Round Round::Builder(Expression child0, Expression child1) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(RoundNode)); + RoundNode * node = new (bufferNode) RoundNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); + return static_cast(h); } Expression Round::shallowReduce() { @@ -47,7 +54,7 @@ Expression Round::shallowReduce() { } #if MATRIX_EXACT_REDUCING if (childAtIndex(0).type() == ExpressionNode::Type::Matrix || childAtIndex(1).type() == ExpressionNode::Type::Matrix) { - return Undefined(); + return Undefined::Builder(); } #endif /* We reduce only round(Rational, Rational). We do not reduce @@ -56,11 +63,11 @@ Expression Round::shallowReduce() { Rational r1 = childAtIndex(0).convert(); Rational r2 = childAtIndex(1).convert(); if (!r2.integerDenominator().isOne()) { - Expression result = Undefined(); + Expression result = Undefined::Builder(); replaceWithInPlace(result); return result; } - const Rational ten(10); + const Rational ten = Rational::Builder(10); if (Power::RationalExponentShouldNotBeReduced(ten, r2)) { return *this; } @@ -69,10 +76,10 @@ Expression Round::shallowReduce() { IntegerDivision d = Integer::Division(mult.signedIntegerNumerator(), mult.integerDenominator()); Integer rounding = d.quotient; Integer multDenominator = mult.integerDenominator(); - if (Rational::NaturalOrder(Rational(d.remainder, multDenominator), Rational(1,2)) >= 0) { + if (Rational::NaturalOrder(Rational::Builder(d.remainder, multDenominator), Rational::Builder(1,2)) >= 0) { rounding = Integer::Addition(rounding, Integer(1)); } - Rational result = Rational::Multiplication(rounding, Rational::IntegerPower(Rational(1,10), r2.signedIntegerNumerator())); + Rational result = Rational::Multiplication(Rational::Builder(rounding), Rational::IntegerPower(Rational::Builder(1,10), r2.signedIntegerNumerator())); if (result.numeratorOrDenominatorIsInfinity()) { return *this; } diff --git a/poincare/src/sequence.cpp b/poincare/src/sequence.cpp index 336a164b4..5e09b9732 100644 --- a/poincare/src/sequence.cpp +++ b/poincare/src/sequence.cpp @@ -29,7 +29,7 @@ Evaluation SequenceNode::templatedApproximate(Context& context, Preferences:: return Complex::Undefined(); } VariableContext nContext = VariableContext(static_cast(childAtIndex(1))->name(), &context); - Evaluation result = Complex((T)emptySequenceValue()); + Evaluation result = Complex::Builder((T)emptySequenceValue()); for (int i = (int)start; i <= (int)end; i++) { if (Expression::ShouldStopProcessing()) { return Complex::Undefined(); diff --git a/poincare/src/sign_function.cpp b/poincare/src/sign_function.cpp index 340beb9a8..0099b02c7 100644 --- a/poincare/src/sign_function.cpp +++ b/poincare/src/sign_function.cpp @@ -20,7 +20,7 @@ ExpressionNode::Sign SignFunctionNode::sign(Context * context) const { Expression SignFunctionNode::setSign(Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { assert(s == ExpressionNode::Sign::Positive || s == ExpressionNode::Sign::Negative); SignFunction sign(this); - Rational r(s == ExpressionNode::Sign::Positive ? 1 : -1); + Rational r = Rational::Builder(s == ExpressionNode::Sign::Positive ? 1 : -1); sign.replaceWithInPlace(r); return r; } @@ -43,12 +43,19 @@ Complex SignFunctionNode::computeOnComplex(const std::complex c, Preferenc return Complex::Undefined(); } if (c.real() == 0) { - return Complex(0.0); + return Complex::Builder(0.0); } if (c.real() < 0) { - return Complex(-1.0); + return Complex::Builder(-1.0); } - return Complex(1.0); + return Complex::Builder(1.0); +} + +SignFunction SignFunction::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(SignFunctionNode)); + SignFunctionNode * node = new (bufferNode) SignFunctionNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); } Expression SignFunction::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { @@ -63,11 +70,11 @@ Expression SignFunction::shallowReduce(Context & context, Preferences::ComplexFo return SimplificationHelper::Map(*this, context, angleUnit); } #endif - Rational resultSign(1); + Rational resultSign = Rational::Builder(1); Expression child = childAtIndex(0); ExpressionNode::Sign s = child.sign(&context); if (s == ExpressionNode::Sign::Negative) { - resultSign = Rational(-1); + resultSign = Rational::Builder(-1); } else { Evaluation childApproximated = child.node()->approximate(1.0f, context, complexFormat, angleUnit); assert(childApproximated.type() == EvaluationNode::Type::Complex); @@ -83,15 +90,15 @@ Expression SignFunction::shallowReduce(Context & context, Preferences::ComplexFo return *this; } Expression sign = *this; - Multiplication m = Multiplication::Builder(Rational(-1)); + Multiplication m = Multiplication::Builder(Rational::Builder(-1)); replaceWithInPlace(m); m.addChildAtIndexInPlace(sign, 1, 1); // sign does not need to be shallowReduced because -x = NAN --> x = NAN return m; // m does not need to be shallowReduced, -1*sign cannot be reduced } } else if (c.real() < 0) { - resultSign = Rational(-1); + resultSign = Rational::Builder(-1); } else if (c.real() == 0) { - resultSign = Rational(0); + resultSign = Rational::Builder(0); } } replaceWithInPlace(resultSign); diff --git a/poincare/src/sine.cpp b/poincare/src/sine.cpp index 9ecf57eaa..5099382d2 100644 --- a/poincare/src/sine.cpp +++ b/poincare/src/sine.cpp @@ -19,7 +19,7 @@ template Complex SineNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { std::complex angleInput = Trigonometry::ConvertToRadian(c, angleUnit); std::complex res = std::sin(angleInput); - return Complex(Trigonometry::RoundToMeaningfulDigits(res, angleInput)); + return Complex::Builder(Trigonometry::RoundToMeaningfulDigits(res, angleInput)); } Layout SineNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { @@ -34,6 +34,13 @@ Expression SineNode::shallowReduce(Context & context, Preferences::ComplexFormat return Sine(this).shallowReduce(context, complexFormat, angleUnit, target); } +Sine Sine::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(SineNode)); + SineNode * node = new (bufferNode) SineNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); +} + Expression Sine::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { Expression e = Expression::defaultShallowReduce(); diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index 8438dd663..747d48c51 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -35,13 +35,20 @@ Complex SquareRootNode::computeOnComplex(const std::complex c, Preferences * weird results as sqrt(-1) = 6E-16+i, we compute the argument of the result * of sqrt(c) and if arg ~ 0 [Pi], we discard the residual imaginary part and * if arg ~ Pi/2 [Pi], we discard the residual real part.*/ - return Complex(ApproximationHelper::TruncateRealOrImaginaryPartAccordingToArgument(result)); + return Complex::Builder(ApproximationHelper::TruncateRealOrImaginaryPartAccordingToArgument(result)); } Expression SquareRootNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { return SquareRoot(this).shallowReduce(context, complexFormat, angleUnit, target); } +SquareRoot SquareRoot::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(SquareRootNode)); + SquareRootNode * node = new (bufferNode) SquareRootNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); +} + Expression SquareRoot::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { Expression e = Expression::defaultShallowReduce(); @@ -54,7 +61,7 @@ Expression SquareRoot::shallowReduce(Context & context, Preferences::ComplexForm return SimplificationHelper::Map(this, context, angleUnit); } #endif - Power p = Power::Builder(childAtIndex(0), Rational(1, 2)); + Power p = Power::Builder(childAtIndex(0), Rational::Builder(1, 2)); replaceWithInPlace(p); return p.shallowReduce(context, complexFormat, angleUnit, target); } diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index 1c1bdc2f3..4eb0830b0 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -34,7 +34,7 @@ int StoreNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatM Layout StoreNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { HorizontalLayout result = HorizontalLayout::Builder(); result.addOrMergeChildAtIndex(childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits), 0, false); - result.addChildAtIndex(CharLayout(Ion::Charset::Sto), result.numberOfChildren(), result.numberOfChildren(), nullptr); + result.addChildAtIndex(CharLayout::Builder(Ion::Charset::Sto), result.numberOfChildren(), result.numberOfChildren(), nullptr); result.addOrMergeChildAtIndex(childAtIndex(1)->createLayout(floatDisplayMode, numberOfSignificantDigits), result.numberOfChildren(), false); return result; } @@ -69,13 +69,20 @@ Expression Store::shallowReduce(Context & context, Preferences::ComplexFormat co return storedExpression; } +Store Store::Builder(Expression value, SymbolAbstract symbol) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(StoreNode)); + StoreNode * node = new (bufferNode) StoreNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(value, symbol).array(), 2); + return static_cast(h); +} + Expression Store::storeValueForSymbol(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { Expression finalValue; if (symbol().type() == ExpressionNode::Type::Function) { // In tata + 2 ->f(tata), replace tata with xUnknown symbol assert(symbol().childAtIndex(0).type() == ExpressionNode::Type::Symbol); Expression userDefinedUnknown = symbol().childAtIndex(0); - Symbol xUnknown = Symbol(Symbol::SpecialSymbols::UnknownX); + Symbol xUnknown = Symbol::Builder(Symbol::SpecialSymbols::UnknownX); finalValue = childAtIndex(0).replaceSymbolWithExpression(static_cast(userDefinedUnknown), xUnknown); } else { assert(symbol().type() == ExpressionNode::Type::Symbol); @@ -86,13 +93,13 @@ Expression Store::storeValueForSymbol(Context& context, Preferences::ComplexForm Expression storedExpression = context.expressionForSymbol(symbol(), true); if (storedExpression.isUninitialized()) { - return Undefined(); + return Undefined::Builder(); } if (symbol().type() == ExpressionNode::Type::Function) { // Replace the xUnknown symbol with the variable initially used assert(symbol().childAtIndex(0).type() == ExpressionNode::Type::Symbol); Expression userDefinedUnknown = symbol().childAtIndex(0); - Symbol xUnknown = Symbol(Symbol::SpecialSymbols::UnknownX); + Symbol xUnknown = Symbol::Builder(Symbol::SpecialSymbols::UnknownX); storedExpression = storedExpression.replaceSymbolWithExpression(xUnknown, static_cast(userDefinedUnknown)); } return storedExpression; diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index 4dabad1b0..8978925b0 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -44,7 +44,7 @@ int SubtractionNode::serialize(char * buffer, int bufferSize, Preferences::Print template MatrixComplex SubtractionNode::computeOnComplexAndMatrix(const std::complex c, const MatrixComplex m, Preferences::ComplexFormat complexFormat) { MatrixComplex opposite = computeOnMatrixAndComplex(m, c, complexFormat); - MatrixComplex result; + MatrixComplex result = MatrixComplex::Builder(); for (int i = 0; i < opposite.numberOfChildren(); i++) { result.addChildAtIndexInPlace(OppositeNode::compute(opposite.complexAtIndex(i), complexFormat), i, i); } @@ -56,12 +56,26 @@ Expression SubtractionNode::shallowReduce(Context & context, Preferences::Comple return Subtraction(this).shallowReduce(context, complexFormat, angleUnit, target); } +Subtraction Subtraction::Builder() { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(SubtractionNode)); + SubtractionNode * node = new (bufferNode) SubtractionNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); +} + +Subtraction Subtraction::Builder(Expression child0, Expression child1) { + Subtraction d = Subtraction::Builder(); + d.replaceChildAtIndexInPlace(0, child0); + d.replaceChildAtIndexInPlace(1, child1); + return d; +} + Expression Subtraction::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { return e; } - Expression m = Multiplication::Builder(Rational(-1), childAtIndex(1)); + Expression m = Multiplication::Builder(Rational::Builder(-1), childAtIndex(1)); Addition a = Addition::Builder(childAtIndex(0), m); m = m.shallowReduce(context, complexFormat, angleUnit, target); replaceWithInPlace(a); diff --git a/poincare/src/sum.cpp b/poincare/src/sum.cpp index ffc0620ad..e8bdeac55 100644 --- a/poincare/src/sum.cpp +++ b/poincare/src/sum.cpp @@ -31,7 +31,7 @@ Evaluation SumNode::templatedApproximateWithNextTerm(Evaluation a, Evaluat if (a.type() == EvaluationNode::Type::Complex && b.type() == EvaluationNode::Type::Complex) { Complex c = static_cast&>(a); Complex d = static_cast&>(b); - return Complex(c.stdComplex()+d.stdComplex()); + return Complex::Builder(c.stdComplex()+d.stdComplex()); } if (a.type() == EvaluationNode::Type::Complex) { Complex c = static_cast &>(a); @@ -46,4 +46,11 @@ Evaluation SumNode::templatedApproximateWithNextTerm(Evaluation a, Evaluat return AdditionNode::computeOnMatrices(m, n, complexFormat); } +Sum Sum::Builder(Expression child0, Symbol child1, Expression child2, Expression child3) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(SumNode)); + SumNode * node = new (bufferNode) SumNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1, child2, child3).array(), 4); + return static_cast(h); +} + } diff --git a/poincare/src/sum_layout.cpp b/poincare/src/sum_layout.cpp index 9c9a079e8..1297b124a 100644 --- a/poincare/src/sum_layout.cpp +++ b/poincare/src/sum_layout.cpp @@ -45,4 +45,11 @@ void SumLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionColor, SequenceLayoutNode::render(ctx, p, expressionColor, backgroundColor); } +SumLayout SumLayout::Builder(Layout child0, Layout child1, Layout child2, Layout child3) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(SumLayoutNode)); + SumLayoutNode * node = new (bufferNode) SumLayoutNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1, child2, child3).array(), 4); + return static_cast(h); +} + } diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index f497b5458..3e28c2ab7 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -15,6 +15,10 @@ namespace Poincare { constexpr char Symbol::k_ans[]; +SymbolNode::SymbolNode(const char * newName, int length) : SymbolAbstractNode() { + strlcpy(const_cast(name()), newName, length+1); +} + Expression SymbolNode::replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression) { return Symbol(this).replaceSymbolWithExpression(symbol, expression); } @@ -77,32 +81,32 @@ bool SymbolNode::isReal(Context & context) const { Layout SymbolNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { if (m_name[0] == Symbol::SpecialSymbols::UnknownX) { assert(m_name[1] == 0); - return CharLayout(Symbol::k_unknownXReadableChar); + return CharLayout::Builder(Symbol::k_unknownXReadableChar); } if (strcmp(m_name, "u(n)") == 0) { return HorizontalLayout::Builder( - CharLayout('u'), + CharLayout::Builder('u'), VerticalOffsetLayout::Builder( - CharLayout('n'), + CharLayout::Builder('n'), VerticalOffsetLayoutNode::Type::Subscript)); } if (strcmp(m_name, "u(n+1)") == 0) { return HorizontalLayout::Builder( - CharLayout('u'), + CharLayout::Builder('u'), VerticalOffsetLayout::Builder( LayoutHelper::String("n+1", 3), VerticalOffsetLayoutNode::Type::Subscript)); } if (strcmp(m_name, "v(n)") == 0) { return HorizontalLayout::Builder( - CharLayout('v'), + CharLayout::Builder('v'), VerticalOffsetLayout::Builder( - CharLayout('n'), + CharLayout::Builder('n'), VerticalOffsetLayoutNode::Type::Subscript)); } if (strcmp(m_name, "v(n+1)") == 0) { return HorizontalLayout::Builder( - CharLayout('v'), + CharLayout::Builder('v'), VerticalOffsetLayout::Builder( LayoutHelper::String("n+1", 3), VerticalOffsetLayoutNode::Type::Subscript)); @@ -135,11 +139,14 @@ Evaluation SymbolNode::templatedApproximate(Context& context, Preferences::Co return e.node()->approximate(T(), context, complexFormat, angleUnit); } -Symbol::Symbol(const char * name, int length) : SymbolAbstract(TreePool::sharedPool()->createTreeNode(SymbolAbstract::AlignedNodeSize(length, sizeof(SymbolNode)))) { - node()->setName(name, length); +Symbol Symbol::Builder(const char * name, int length) { + void * bufferNode = TreePool::sharedPool()->alloc(SymbolAbstract::AlignedNodeSize(length, sizeof(SymbolNode))); + SymbolNode * node = new (bufferNode) SymbolNode(name, length); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); } -Symbol::Symbol(char name) : Symbol(&name, 1) {} +Symbol Symbol::Builder(char name) { return Symbol::Builder(&name, 1); } bool Symbol::isSeriesSymbol(const char * c) { // [NV][1-3] @@ -184,13 +191,13 @@ Expression Symbol::replaceSymbolWithExpression(const SymbolAbstract & symbol, co Expression Symbol::replaceUnknown(const Symbol & symbol) { assert(!symbol.isUninitialized()); assert(symbol.type() == ExpressionNode::Type::Symbol); - return replaceSymbolWithExpression(symbol, Symbol(SpecialSymbols::UnknownX)); + return replaceSymbolWithExpression(symbol, Symbol::Builder(SpecialSymbols::UnknownX)); } int Symbol::getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const { if (strcmp(name(), symbolName) == 0) { - coefficients[0] = Rational(0); - coefficients[1] = Rational(1); + coefficients[0] = Rational::Builder(0); + coefficients[1] = Rational::Builder(1); return 1; } coefficients[0] = clone(); diff --git a/poincare/src/symbol_abstract.cpp b/poincare/src/symbol_abstract.cpp index 188a1cd05..3ea31e3ab 100644 --- a/poincare/src/symbol_abstract.cpp +++ b/poincare/src/symbol_abstract.cpp @@ -8,26 +8,10 @@ namespace Poincare { -void SymbolAbstractNode::setName(const char * newName, int length) { - strlcpy(const_cast(name()), newName, length+1); -} - size_t SymbolAbstractNode::size() const { return SymbolAbstract::AlignedNodeSize(strlen(name()), nodeSize()); } -void SymbolAbstractNode::initToMatchSize(size_t goalSize) { - assert(goalSize != nodeSize()); - assert(goalSize > nodeSize()); - size_t nameSize = goalSize - nodeSize(); - char * modifiableName = const_cast(name()); - for (size_t i = 0; i < nameSize - 1; i++) { - modifiableName[i] = 'a'; - } - modifiableName[nameSize-1] = 0; - assert(size() == goalSize); -} - ExpressionNode::Sign SymbolAbstractNode::sign(Context * context) const { SymbolAbstract s(this); Expression e = SymbolAbstract::Expand(s, *context, false); @@ -74,7 +58,7 @@ Expression SymbolAbstract::Expand(const SymbolAbstract & symbol, Context & conte * symbols are defined circularly. */ e = Expression::ExpressionWithoutSymbols(e, context); if (!e.isUninitialized() && isFunction) { - e = e.replaceSymbolWithExpression(Symbol(Symbol::SpecialSymbols::UnknownX), symbol.childAtIndex(0)); + e = e.replaceSymbolWithExpression(Symbol::Builder(Symbol::SpecialSymbols::UnknownX), symbol.childAtIndex(0)); } return e; } diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp index 01510753c..cb162eb5a 100644 --- a/poincare/src/tangent.cpp +++ b/poincare/src/tangent.cpp @@ -30,13 +30,20 @@ template Complex TangentNode::computeOnComplex(const std::complex c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) { std::complex angleInput = Trigonometry::ConvertToRadian(c, angleUnit); std::complex res = std::tan(angleInput); - return Complex(Trigonometry::RoundToMeaningfulDigits(res, angleInput)); + return Complex::Builder(Trigonometry::RoundToMeaningfulDigits(res, angleInput)); } Expression TangentNode::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target) { return Tangent(this).shallowReduce(context, complexFormat, angleUnit, target); } +Tangent Tangent::Builder(Expression child) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(TangentNode)); + TangentNode * node = new (bufferNode) TangentNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + return static_cast(h); +} + Expression Tangent::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { Expression e = Expression::defaultShallowReduce(); diff --git a/poincare/src/tree_handle.cpp b/poincare/src/tree_handle.cpp index 51cd46dc0..7493b56b4 100644 --- a/poincare/src/tree_handle.cpp +++ b/poincare/src/tree_handle.cpp @@ -185,6 +185,32 @@ TreeHandle::TreeHandle(const TreeNode * node) : TreeHandle() { } } +TreeHandle TreeHandle::BuildWithBasicChildren(TreeNode * node, TreeHandle * children, int numberOfChildren) { + assert(node != nullptr); + TreePool * pool = TreePool::sharedPool(); + int expectedNumberOfChildren = node->numberOfChildren(); + /* Ensure the pool is syntaxically correct by creating ghost children for + * nodes that have a fixed, non-zero number of children. */ + for (int i = 0; i < expectedNumberOfChildren; i++) { + GhostNode * ghost = new (pool->alloc(sizeof(GhostNode))) GhostNode(); + ghost->rename(pool->generateIdentifier(), false); + ghost->retain(); + pool->move(node->next(), ghost, 0); + } + node->rename(pool->generateIdentifier(), false); + TreeHandle h = TreeHandle(node); + /* Add or replace ghost children by the children given as arguments if + * possible. */ + for (int i = 0; i < numberOfChildren; i++) { + if (i < expectedNumberOfChildren) { + h.replaceChildAtIndexInPlace(i, children[i]); + } else { + h.addChildAtIndexInPlace(children[i], i, i); + } + } + return h; +} + void TreeHandle::setIdentifierAndRetain(int newId) { m_identifier = newId; if (!isUninitialized()) { diff --git a/poincare/src/tree_pool.cpp b/poincare/src/tree_pool.cpp index 56f928125..9769f299a 100644 --- a/poincare/src/tree_pool.cpp +++ b/poincare/src/tree_pool.cpp @@ -20,19 +20,6 @@ void TreePool::freeIdentifier(int identifier) { } } -template -T * TreePool::createTreeNode(size_t size) { - T * node = new(alloc(size)) T(); - if (size != sizeof(T)) { - /* If the node does not have a standard size, it should init itself so that - * T::size gives the right result, otherwise TreeNode::next() does not work - * and addGhostChildrenAndRename might not work. */ - node->initToMatchSize(size); - } - addGhostChildrenAndRename(node); - return node; -} - void TreePool::move(TreeNode * destination, TreeNode * source, int realNumberOfSourceChildren) { size_t moveSize = source->deepSize(realNumberOfSourceChildren); moveNodes(destination, source, moveSize); @@ -152,17 +139,6 @@ void TreePool::dealloc(TreeNode * node, size_t size) { updateNodeForIdentifierFromNode(node); } -void TreePool::addGhostChildrenAndRename(TreeNode * node) { - /* Ensure the pool is syntaxically correct by creating ghost children for - * nodes that have a fixed, non-zero number of children. */ - for (int i = 0; i < node->numberOfChildren(); i++) { - TreeNode * ghost = createTreeNode(); - ghost->retain(); - move(node->next(), ghost, 0); - } - node->rename(generateIdentifier(), false); -} - void TreePool::discardTreeNode(TreeNode * node) { int nodeIdentifier = node->identifier(); size_t size = node->size(); @@ -202,107 +178,4 @@ void TreePool::freePoolFromNode(TreeNode * firstNodeToDiscard) { m_cursor = reinterpret_cast(firstNodeToDiscard); } -template HorizontalLayoutNode * Poincare::TreePool::createTreeNode(size_t size); -template EmptyLayoutNode * Poincare::TreePool::createTreeNode(size_t size); -template CharLayoutNode * Poincare::TreePool::createTreeNode(size_t size); -template VerticalOffsetLayoutNode * Poincare::TreePool::createTreeNode(size_t size); -template NthRootLayoutNode * Poincare::TreePool::createTreeNode(size_t size); -template FractionLayoutNode * Poincare::TreePool::createTreeNode(size_t size); -template LeftParenthesisLayoutNode * Poincare::TreePool::createTreeNode(size_t size); -template RightParenthesisLayoutNode * Poincare::TreePool::createTreeNode(size_t size); -template AbsoluteValueNode * Poincare::TreePool::createTreeNode(size_t size); -template AdditionNode * Poincare::TreePool::createTreeNode(size_t size); -template ArcCosineNode * Poincare::TreePool::createTreeNode(size_t size); -template ArcSineNode * Poincare::TreePool::createTreeNode(size_t size); -template ArcTangentNode * Poincare::TreePool::createTreeNode(size_t size); -template UndefinedNode * Poincare::TreePool::createTreeNode(size_t size); -template UnrealNode * Poincare::TreePool::createTreeNode(size_t size); -template BinomialCoefficientNode * Poincare::TreePool::createTreeNode(size_t size); -template CeilingNode * Poincare::TreePool::createTreeNode(size_t size); -template OppositeNode * Poincare::TreePool::createTreeNode(size_t size); -template PowerNode * Poincare::TreePool::createTreeNode(size_t size); -template ComplexArgumentNode * Poincare::TreePool::createTreeNode(size_t size); -template ComplexCartesianNode * Poincare::TreePool::createTreeNode(size_t size); -template ConfidenceIntervalNode * Poincare::TreePool::createTreeNode(size_t size); -template ConjugateNode * Poincare::TreePool::createTreeNode(size_t size); -template ConstantNode * Poincare::TreePool::createTreeNode(size_t size); -template CosineNode * Poincare::TreePool::createTreeNode(size_t size); -template DecimalNode * Poincare::TreePool::createTreeNode(size_t size); -template DerivativeNode * Poincare::TreePool::createTreeNode(size_t size); -template DeterminantNode * Poincare::TreePool::createTreeNode(size_t size); -template DivisionNode * Poincare::TreePool::createTreeNode(size_t size); -template DivisionQuotientNode * Poincare::TreePool::createTreeNode(size_t size); -template DivisionRemainderNode * Poincare::TreePool::createTreeNode(size_t size); -template EmptyExpressionNode * Poincare::TreePool::createTreeNode(size_t size); -template FunctionNode * Poincare::TreePool::createTreeNode(size_t size); -template HyperbolicArcCosineNode * Poincare::TreePool::createTreeNode(size_t size); -template HyperbolicArcSineNode * Poincare::TreePool::createTreeNode(size_t size); -template HyperbolicArcTangentNode * Poincare::TreePool::createTreeNode(size_t size); -template HyperbolicCosineNode * Poincare::TreePool::createTreeNode(size_t size); -template SimplePredictionIntervalNode * Poincare::TreePool::createTreeNode(size_t size); -template HyperbolicSineNode * Poincare::TreePool::createTreeNode(size_t size); -template HyperbolicTangentNode * Poincare::TreePool::createTreeNode(size_t size); -template LogarithmNode<2> * Poincare::TreePool::createTreeNode >(size_t size); -template SymbolNode * Poincare::TreePool::createTreeNode(size_t size); -template LogarithmNode<1> * Poincare::TreePool::createTreeNode >(size_t size); -template ParenthesisNode * Poincare::TreePool::createTreeNode(size_t size); -template StoreNode * Poincare::TreePool::createTreeNode(size_t size); -template EqualNode * Poincare::TreePool::createTreeNode(size_t size); -template FactorNode * Poincare::TreePool::createTreeNode(size_t size); -template FactorialNode * Poincare::TreePool::createTreeNode(size_t size); -template FloorNode * Poincare::TreePool::createTreeNode(size_t size); -template FracPartNode * Poincare::TreePool::createTreeNode(size_t size); -template MatrixNode * Poincare::TreePool::createTreeNode(size_t size); -template FloatNode * Poincare::TreePool::createTreeNode >(size_t size); -template GreatCommonDivisorNode * Poincare::TreePool::createTreeNode(size_t size); -template ImaginaryPartNode * Poincare::TreePool::createTreeNode(size_t size); -template IntegerNode * Poincare::TreePool::createTreeNode(size_t size); -template IntegralNode * Poincare::TreePool::createTreeNode(size_t size); -template LeastCommonMultipleNode * Poincare::TreePool::createTreeNode(size_t size); -template MatrixDimensionNode * Poincare::TreePool::createTreeNode(size_t size); -template MatrixInverseNode * Poincare::TreePool::createTreeNode(size_t size); -template MatrixTraceNode * Poincare::TreePool::createTreeNode(size_t size); -template MatrixTransposeNode * Poincare::TreePool::createTreeNode(size_t size); -template MultiplicationNode * Poincare::TreePool::createTreeNode(size_t size); -template NaperianLogarithmNode * Poincare::TreePool::createTreeNode(size_t size); -template NthRootNode * Poincare::TreePool::createTreeNode(size_t size); -template InfinityNode * Poincare::TreePool::createTreeNode(size_t size); -template PermuteCoefficientNode * Poincare::TreePool::createTreeNode(size_t size); -template PredictionIntervalNode * Poincare::TreePool::createTreeNode(size_t size); -template ProductNode * Poincare::TreePool::createTreeNode(size_t size); -template RandintNode * Poincare::TreePool::createTreeNode(size_t size); -template RandomNode * Poincare::TreePool::createTreeNode(size_t size); -template RationalNode * Poincare::TreePool::createTreeNode(size_t size); -template RealPartNode * Poincare::TreePool::createTreeNode(size_t size); -template RoundNode * Poincare::TreePool::createTreeNode(size_t size); -template SignFunctionNode * Poincare::TreePool::createTreeNode(size_t size); -template SineNode * Poincare::TreePool::createTreeNode(size_t size); -template SquareRootNode * Poincare::TreePool::createTreeNode(size_t size); -template SubtractionNode * Poincare::TreePool::createTreeNode(size_t size); -template SumNode * Poincare::TreePool::createTreeNode(size_t size); -template TangentNode * Poincare::TreePool::createTreeNode(size_t size); -template GhostNode * Poincare::TreePool::createTreeNode(size_t size); - -template MatrixLayoutNode* TreePool::createTreeNode(size_t size); -template AbsoluteValueLayoutNode* TreePool::createTreeNode(size_t size); -template ComplexNode* TreePool::createTreeNode >(size_t size); -template ComplexNode* TreePool::createTreeNode >(size_t size); -template MatrixComplexNode* TreePool::createTreeNode >(size_t size); -template MatrixComplexNode* TreePool::createTreeNode >(size_t size); -template BinomialCoefficientLayoutNode* TreePool::createTreeNode(size_t size); -template CeilingLayoutNode* TreePool::createTreeNode(size_t size); -template CondensedSumLayoutNode* TreePool::createTreeNode(size_t size); -template ConjugateLayoutNode* TreePool::createTreeNode(size_t size); -template FloorLayoutNode* TreePool::createTreeNode(size_t size); -template IntegralLayoutNode* TreePool::createTreeNode(size_t size); -template ProductLayoutNode* TreePool::createTreeNode(size_t size); -template SumLayoutNode* TreePool::createTreeNode(size_t size); -template FloatNode* TreePool::createTreeNode >(size_t size); - -template LeftSquareBracketLayoutNode* TreePool::createTreeNode(size_t size); -template RightSquareBracketLayoutNode* TreePool::createTreeNode(size_t size); - -template BlobNode* TreePool::createTreeNode(size_t size); -template PairNode* TreePool::createTreeNode(size_t size); - } diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 1daeec03f..71e174ca0 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -36,7 +36,7 @@ float Trigonometry::characteristicXRange(const Expression & e, Context & context assert(d == 1); /* To compute a, the slope of the expression child(0), we compute the * derivative of child(0) for any x value. */ - Poincare::Derivative derivative = Poincare::Derivative::Builder(e.childAtIndex(0).clone(), Symbol(x, 1), Float(1.0f)); + Poincare::Derivative derivative = Poincare::Derivative::Builder(e.childAtIndex(0).clone(), Symbol::Builder(x, 1), Float::Builder(1.0f)); float a = derivative.node()->approximate(float(), context, Preferences::ComplexFormat::Real, angleUnit).toScalar(); float pi = angleUnit == Preferences::AngleUnit::Radian ? M_PI : 180.0f; return 2.0f*pi/std::fabs(a); @@ -107,13 +107,13 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& co Expression sqrt = Power::Builder( Addition::Builder( - Rational(1), + Rational::Builder(1), Multiplication::Builder( - Rational(-1), - Power::Builder(e.childAtIndex(0).childAtIndex(0), Rational(2)) + Rational::Builder(-1), + Power::Builder(e.childAtIndex(0).childAtIndex(0), Rational::Builder(2)) ) ), - Rational(1,2) + Rational::Builder(1,2) ); // reduce x^2 sqrt.childAtIndex(0).childAtIndex(1).childAtIndex(1).shallowReduce(context, complexFormat, angleUnit, target); @@ -136,12 +136,12 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& co Expression res = Power::Builder( Addition::Builder( - Rational(1), + Rational::Builder(1), Power::Builder( e.type() == ExpressionNode::Type::Cosine ? x : x.clone(), - Rational(2)) + Rational::Builder(2)) ), - Rational(-1,2) + Rational::Builder(-1,2) ); // reduce x^2 @@ -167,7 +167,7 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& co return e.shallowReduce(context, complexFormat, angleUnit, target); } else { // sin(-a) = -sin(a) or tan(-a) = -tan(a) - Multiplication m = Multiplication::Builder(Rational(-1)); + Multiplication m = Multiplication::Builder(Rational::Builder(-1)); e.replaceWithInPlace(m); m.addChildAtIndexInPlace(e, 1, 1); e.shallowReduce(context, complexFormat, angleUnit, target); @@ -220,7 +220,7 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& co } // Step 4.5. Build the new result. Integer rDenominator = r.integerDenominator(); - Expression newR = Rational(div.remainder, rDenominator); + Expression newR = Rational::Builder(div.remainder, rDenominator); Expression rationalParent = angleUnit == Preferences::AngleUnit::Radian ? e.childAtIndex(0) : e; rationalParent.replaceChildAtIndexInPlace(0, newR); newR.shallowReduce(context, complexFormat, angleUnit, target); @@ -233,7 +233,7 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, Context& co unaryCoefficient *= -1; } Expression simplifiedCosine = e.shallowReduce(context, complexFormat, angleUnit, target); // recursive - Multiplication m = Multiplication::Builder(Rational(unaryCoefficient)); + Multiplication m = Multiplication::Builder(Rational::Builder(unaryCoefficient)); simplifiedCosine.replaceWithInPlace(m); m.addChildAtIndexInPlace(simplifiedCosine, 1, 1); return m.shallowReduce(context, complexFormat, angleUnit, target); @@ -278,12 +278,12 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& c * reduced to undef) */ if (target == ExpressionNode::ReductionTarget::User || x.isNumber()) { Expression sign = SignFunction::Builder(x.clone()); - Multiplication m0 = Multiplication::Builder(Rational(1,2), sign, Constant(Ion::Charset::SmallPi)); + Multiplication m0 = Multiplication::Builder(Rational::Builder(1,2), sign, Constant::Builder(Ion::Charset::SmallPi)); sign.shallowReduce(context, complexFormat, angleUnit, target); e.replaceChildAtIndexInPlace(0, x); Addition a = Addition::Builder(m0); e.replaceWithInPlace(a); - Multiplication m1 = Multiplication::Builder(Rational(-1), e); + Multiplication m1 = Multiplication::Builder(Rational::Builder(-1), e); e.shallowReduce(context, complexFormat, angleUnit, target); a.addChildAtIndexInPlace(m1, 1, 1); return a.shallowReduce(context, complexFormat, angleUnit, target); @@ -314,7 +314,7 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& c // The argument was made positive // acos(-x) = pi-acos(x) if (e.type() == ExpressionNode::Type::ArcCosine) { - Expression pi = angleUnit == Preferences::AngleUnit::Radian ? static_cast(Constant(Ion::Charset::SmallPi)) : static_cast(Rational(180)); + Expression pi = angleUnit == Preferences::AngleUnit::Radian ? static_cast(Constant::Builder(Ion::Charset::SmallPi)) : static_cast(Rational::Builder(180)); Subtraction s = Subtraction::Builder(); e.replaceWithInPlace(s); s.replaceChildAtIndexInPlace(0, pi); @@ -323,7 +323,7 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Context& c return s.shallowReduce(context, complexFormat, angleUnit, target); } else { // asin(-x) = -asin(x) or atan(-x) = -atan(x) - Multiplication m = Multiplication::Builder(Rational(-1)); + Multiplication m = Multiplication::Builder(Rational::Builder(-1)); e.replaceWithInPlace(m); m.addChildAtIndexInPlace(e, 1, 1); e.shallowReduce(context, complexFormat, angleUnit, target); diff --git a/poincare/src/undefined.cpp b/poincare/src/undefined.cpp index 7031aec61..0615d830e 100644 --- a/poincare/src/undefined.cpp +++ b/poincare/src/undefined.cpp @@ -34,6 +34,13 @@ template Evaluation UndefinedNode::templatedApproximate() const { return Complex::Undefined(); } +Undefined Undefined::Builder() { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(UndefinedNode)); + UndefinedNode * node = new (bufferNode) UndefinedNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); +} + template Evaluation UndefinedNode::templatedApproximate() const; template Evaluation UndefinedNode::templatedApproximate() const; } diff --git a/poincare/src/unreal.cpp b/poincare/src/unreal.cpp index 6180455ac..d8d45a25e 100644 --- a/poincare/src/unreal.cpp +++ b/poincare/src/unreal.cpp @@ -20,5 +20,11 @@ int UnrealNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloat return min(Unreal::NameSize(), bufferSize) - 1; } +Unreal Unreal::Builder() { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(UnrealNode)); + UnrealNode * node = new (bufferNode) UnrealNode(); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); } +} diff --git a/poincare/src/variable_context.cpp b/poincare/src/variable_context.cpp index b0ebbbcde..fb36c9fc2 100644 --- a/poincare/src/variable_context.cpp +++ b/poincare/src/variable_context.cpp @@ -15,7 +15,7 @@ VariableContext::VariableContext(const char * name, Context * parentContext) : template void VariableContext::setApproximationForVariable(T value) { - m_value = Float(value); + m_value = Float::Builder(value); } void VariableContext::setExpressionForSymbol(const Expression & expression, const SymbolAbstract & symbol, Context & context) { diff --git a/poincare/src/vertical_offset_layout.cpp b/poincare/src/vertical_offset_layout.cpp index 69feb1557..5686e6f16 100644 --- a/poincare/src/vertical_offset_layout.cpp +++ b/poincare/src/vertical_offset_layout.cpp @@ -266,4 +266,11 @@ LayoutNode * VerticalOffsetLayoutNode::baseLayout() { return parentNode->childAtIndex(idxInParent - 1); } +VerticalOffsetLayout VerticalOffsetLayout::Builder(Layout l, VerticalOffsetLayoutNode::Type type) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(VerticalOffsetLayoutNode)); + VerticalOffsetLayoutNode * node = new (bufferNode) VerticalOffsetLayoutNode(type); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &l, 1); + return static_cast(h); +} + } diff --git a/poincare/test/addition.cpp b/poincare/test/addition.cpp index 49803abba..f7588f627 100644 --- a/poincare/test/addition.cpp +++ b/poincare/test/addition.cpp @@ -22,8 +22,8 @@ static inline void assert_parsed_expression_is_equal_to(const char * exp, Expres } QUIZ_CASE(poincare_addition_cast_does_not_copy) { - Rational i1(1); - Rational i2(2); + Rational i1 = Rational::Builder(1); + Rational i2 = Rational::Builder(2); Addition j = Addition::Builder(i1, i2); Expression k = j; quiz_assert(k.identifier() == (static_cast(k)).identifier()); @@ -32,15 +32,15 @@ QUIZ_CASE(poincare_addition_cast_does_not_copy) { } QUIZ_CASE(poincare_addition_without_parsing) { - Rational i1(1); - Rational i2(2); + Rational i1 = Rational::Builder(1); + Rational i2 = Rational::Builder(2); Addition j = Addition::Builder(i1, i2); assert_approximation_equals(j, 3.0f); } QUIZ_CASE(poincare_addition_parsing) { - Rational i1(1); - Rational i2(2); + Rational i1 = Rational::Builder(1); + Rational i2 = Rational::Builder(2); Addition j1 = Addition::Builder(i1, i2); assert_parsed_expression_is_equal_to("1+2", j1); } diff --git a/poincare/test/convert_expression_to_text.cpp b/poincare/test/convert_expression_to_text.cpp index 7656bd7b1..85d81c602 100644 --- a/poincare/test/convert_expression_to_text.cpp +++ b/poincare/test/convert_expression_to_text.cpp @@ -189,100 +189,100 @@ QUIZ_CASE(assert_float_prints_to) { } QUIZ_CASE(poincare_rational_to_text) { - assert_expression_prints_to(Rational(2,3), "2/3"); - assert_expression_prints_to(Rational("12345678910111213","123456789101112131"), "12345678910111213/123456789101112131"); - assert_expression_prints_to(Rational("123456789112345678921234567893123456789412345678951234567896123456789612345678971234567898123456789912345678901234567891123456789212345678931234567894123456789512345678961234567896123456789712345678981234567899123456789","1"), "123456789112345678921234567893123456789412345678951234567896123456789612345678971234567898123456789912345678901234567891123456789212345678931234567894123456789512345678961234567896123456789712345678981234567899123456789"); + assert_expression_prints_to(Rational::Builder(2,3), "2/3"); + assert_expression_prints_to(Rational::Builder("12345678910111213","123456789101112131"), "12345678910111213/123456789101112131"); + assert_expression_prints_to(Rational::Builder("123456789112345678921234567893123456789412345678951234567896123456789612345678971234567898123456789912345678901234567891123456789212345678931234567894123456789512345678961234567896123456789712345678981234567899123456789","1"), "123456789112345678921234567893123456789412345678951234567896123456789612345678971234567898123456789912345678901234567891123456789212345678931234567894123456789512345678961234567896123456789712345678981234567899123456789"); } QUIZ_CASE(poincare_decimal_to_text) { - Decimal d0(Integer("-123456789"),30); + Decimal d0 = Decimal::Builder(Integer("-123456789"),30); assert_expression_prints_to(d0, "-1.23456789E30", ScientificMode, 14); assert_expression_prints_to(d0, "-1.234568E30", DecimalMode, 7); - Decimal d1(Integer("123456789"),30); + Decimal d1 = Decimal::Builder(Integer("123456789"),30); assert_expression_prints_to(d1, "1.23456789E30", ScientificMode, 14); assert_expression_prints_to(d1, "1.235E30", DecimalMode, 4); - Decimal d2(Integer("-123456789"),-30); + Decimal d2 = Decimal::Builder(Integer("-123456789"),-30); assert_expression_prints_to(d2, "-1.23456789E-30", DecimalMode, 14); assert_expression_prints_to(d2, "-1.235E-30", ScientificMode, 4); - Decimal d3(Integer("-12345"),-3); + Decimal d3 = Decimal::Builder(Integer("-12345"),-3); assert_expression_prints_to(d3, "-0.0012345", DecimalMode, 7); assert_expression_prints_to(d3, "-0.00123", DecimalMode, 3); assert_expression_prints_to(d3, "-0.001235", DecimalMode, 4); assert_expression_prints_to(d3, "-1.23E-3", ScientificMode, 3); - Decimal d4(Integer("12345"),-3); + Decimal d4 = Decimal::Builder(Integer("12345"),-3); assert_expression_prints_to(d4, "0.0012345", DecimalMode, 7); assert_expression_prints_to(d4, "1.2E-3", ScientificMode, 2); - Decimal d5(Integer("12345"),3); + Decimal d5 = Decimal::Builder(Integer("12345"),3); assert_expression_prints_to(d5, "1234.5", DecimalMode, 7); assert_expression_prints_to(d5, "1.23E3", DecimalMode, 3); assert_expression_prints_to(d5, "1235", DecimalMode, 4); assert_expression_prints_to(d5, "1.235E3", ScientificMode, 4); - Decimal d6(Integer("-12345"),3); + Decimal d6 = Decimal::Builder(Integer("-12345"),3); assert_expression_prints_to(d6, "-1234.5", DecimalMode, 7); assert_expression_prints_to(d6, "-1.2345E3", ScientificMode, 10); - Decimal d7(Integer("12345"),6); + Decimal d7 = Decimal::Builder(Integer("12345"),6); assert_expression_prints_to(d7, "1234500", DecimalMode, 7); assert_expression_prints_to(d7, "1.2345E6", DecimalMode, 6); assert_expression_prints_to(d7, "1.2345E6", ScientificMode); - Decimal d8(Integer("-12345"),6); + Decimal d8 = Decimal::Builder(Integer("-12345"),6); assert_expression_prints_to(d8, "-1234500", DecimalMode, 7); assert_expression_prints_to(d8, "-1.2345E6", DecimalMode, 5); assert_expression_prints_to(d7, "1.235E6", ScientificMode, 4); - Decimal d9(Integer("-12345"),-1); + Decimal d9 = Decimal::Builder(Integer("-12345"),-1); assert_expression_prints_to(d9, "-0.12345", DecimalMode, 7); assert_expression_prints_to(d9, "-0.1235", DecimalMode, 4); assert_expression_prints_to(d9, "-1.235E-1", ScientificMode, 4); - Decimal d10(Integer("12345"),-1); + Decimal d10 = Decimal::Builder(Integer("12345"),-1); assert_expression_prints_to(d10, "1.2345E-1"); assert_expression_prints_to(d10, "0.12345", DecimalMode, 7); assert_expression_prints_to(d10, "0.1235", DecimalMode, 4); assert_expression_prints_to(d10, "1.235E-1", ScientificMode, 4); - assert_expression_prints_to(Decimal(-1.23456789E30), "-1.23456789E30", ScientificMode, 14); - assert_expression_prints_to(Decimal(1.23456789E30), "1.23456789E30", ScientificMode, 14); - assert_expression_prints_to(Decimal(-1.23456789E-30), "-1.23456789E-30", ScientificMode, 14); - assert_expression_prints_to(Decimal(-1.2345E-3), "-0.0012345", DecimalMode); - assert_expression_prints_to(Decimal(1.2345E-3), "0.0012345", DecimalMode); - assert_expression_prints_to(Decimal(1.2345E3), "1234.5", DecimalMode); - assert_expression_prints_to(Decimal(-1.2345E3), "-1234.5", DecimalMode); - assert_expression_prints_to(Decimal(1.2345E6), "1234500", DecimalMode); - assert_expression_prints_to(Decimal(-1.2345E6), "-1234500", DecimalMode); - assert_expression_prints_to(Decimal(-1.2345E-1), "-0.12345", DecimalMode); - assert_expression_prints_to(Decimal(1.2345E-1), "0.12345", DecimalMode); - assert_expression_prints_to(Decimal(1.0), "1"); - assert_expression_prints_to(Decimal(0.9999999999999996), "1"); - assert_expression_prints_to(Decimal(0.99999999999995), "9.9999999999995E-1", ScientificMode, 14); - assert_expression_prints_to(Decimal(0.00000099999999999995), "9.9999999999995E-7", ScientificMode, 14); - assert_expression_prints_to(Decimal(0.000000999999999999995), "0.000001", DecimalMode); - assert_expression_prints_to(Decimal(0.000000999999999901200121020102010201201201021099995), "9.999999999012E-7", DecimalMode, 14); - assert_expression_prints_to(Decimal(9999999999999.54), "9999999999999.5", DecimalMode, 14); - assert_expression_prints_to(Decimal(99999999999999.54), "1E14", DecimalMode, 14); - assert_expression_prints_to(Decimal(999999999999999.54), "1E15", DecimalMode, 14); - assert_expression_prints_to(Decimal(9999999999999999.54), "1E16", DecimalMode, 14); - assert_expression_prints_to(Decimal(-9.702365051313E-297), "-9.702365051313E-297", DecimalMode, 14); + assert_expression_prints_to(Decimal::Builder(-1.23456789E30), "-1.23456789E30", ScientificMode, 14); + assert_expression_prints_to(Decimal::Builder(1.23456789E30), "1.23456789E30", ScientificMode, 14); + assert_expression_prints_to(Decimal::Builder(-1.23456789E-30), "-1.23456789E-30", ScientificMode, 14); + assert_expression_prints_to(Decimal::Builder(-1.2345E-3), "-0.0012345", DecimalMode); + assert_expression_prints_to(Decimal::Builder(1.2345E-3), "0.0012345", DecimalMode); + assert_expression_prints_to(Decimal::Builder(1.2345E3), "1234.5", DecimalMode); + assert_expression_prints_to(Decimal::Builder(-1.2345E3), "-1234.5", DecimalMode); + assert_expression_prints_to(Decimal::Builder(1.2345E6), "1234500", DecimalMode); + assert_expression_prints_to(Decimal::Builder(-1.2345E6), "-1234500", DecimalMode); + assert_expression_prints_to(Decimal::Builder(-1.2345E-1), "-0.12345", DecimalMode); + assert_expression_prints_to(Decimal::Builder(1.2345E-1), "0.12345", DecimalMode); + assert_expression_prints_to(Decimal::Builder(1.0), "1"); + assert_expression_prints_to(Decimal::Builder(0.9999999999999996), "1"); + assert_expression_prints_to(Decimal::Builder(0.99999999999995), "9.9999999999995E-1", ScientificMode, 14); + assert_expression_prints_to(Decimal::Builder(0.00000099999999999995), "9.9999999999995E-7", ScientificMode, 14); + assert_expression_prints_to(Decimal::Builder(0.000000999999999999995), "0.000001", DecimalMode); + assert_expression_prints_to(Decimal::Builder(0.000000999999999901200121020102010201201201021099995), "9.999999999012E-7", DecimalMode, 14); + assert_expression_prints_to(Decimal::Builder(9999999999999.54), "9999999999999.5", DecimalMode, 14); + assert_expression_prints_to(Decimal::Builder(99999999999999.54), "1E14", DecimalMode, 14); + assert_expression_prints_to(Decimal::Builder(999999999999999.54), "1E15", DecimalMode, 14); + assert_expression_prints_to(Decimal::Builder(9999999999999999.54), "1E16", DecimalMode, 14); + assert_expression_prints_to(Decimal::Builder(-9.702365051313E-297), "-9.702365051313E-297", DecimalMode, 14); } QUIZ_CASE(poincare_approximation_to_text) { - assert_expression_prints_to(Float(-1.23456789E30), "-1.23456789E30", DecimalMode, 14); - assert_expression_prints_to(Float(1.23456789E30), "1.23456789E30", DecimalMode, 14); - assert_expression_prints_to(Float(-1.23456789E-30), "-1.23456789E-30", DecimalMode, 14); - assert_expression_prints_to(Float(-1.2345E-3), "-0.0012345", DecimalMode); - assert_expression_prints_to(Float(1.2345E-3), "0.0012345", DecimalMode); - assert_expression_prints_to(Float(1.2345E3), "1234.5", DecimalMode); - assert_expression_prints_to(Float(-1.2345E3), "-1234.5", DecimalMode); - assert_expression_prints_to(Float(0.99999999999995), "9.9999999999995E-1", ScientificMode, 14); - assert_expression_prints_to(Float(0.00000099999999999995), "9.9999999999995E-7", DecimalMode, 14); - assert_expression_prints_to(Float(0.0000009999999999901200121020102010201201201021099995), "9.9999999999012E-7", DecimalMode, 14); - assert_expression_prints_to(Float(1.2345E-1), "0.12345", DecimalMode); - assert_expression_prints_to(Float(1), "1", DecimalMode); - assert_expression_prints_to(Float(0.9999999999999995), "1", DecimalMode); - assert_expression_prints_to(Float(1.2345E6), "1234500", DecimalMode); - assert_expression_prints_to(Float(-1.2345E6), "-1234500", DecimalMode); - assert_expression_prints_to(Float(0.0000009999999999999995), "0.000001", DecimalMode); - assert_expression_prints_to(Float(-1.2345E-1), "-0.12345", DecimalMode); + assert_expression_prints_to(Float::Builder(-1.23456789E30), "-1.23456789E30", DecimalMode, 14); + assert_expression_prints_to(Float::Builder(1.23456789E30), "1.23456789E30", DecimalMode, 14); + assert_expression_prints_to(Float::Builder(-1.23456789E-30), "-1.23456789E-30", DecimalMode, 14); + assert_expression_prints_to(Float::Builder(-1.2345E-3), "-0.0012345", DecimalMode); + assert_expression_prints_to(Float::Builder(1.2345E-3), "0.0012345", DecimalMode); + assert_expression_prints_to(Float::Builder(1.2345E3), "1234.5", DecimalMode); + assert_expression_prints_to(Float::Builder(-1.2345E3), "-1234.5", DecimalMode); + assert_expression_prints_to(Float::Builder(0.99999999999995), "9.9999999999995E-1", ScientificMode, 14); + assert_expression_prints_to(Float::Builder(0.00000099999999999995), "9.9999999999995E-7", DecimalMode, 14); + assert_expression_prints_to(Float::Builder(0.0000009999999999901200121020102010201201201021099995), "9.9999999999012E-7", DecimalMode, 14); + assert_expression_prints_to(Float::Builder(1.2345E-1), "0.12345", DecimalMode); + assert_expression_prints_to(Float::Builder(1), "1", DecimalMode); + assert_expression_prints_to(Float::Builder(0.9999999999999995), "1", DecimalMode); + assert_expression_prints_to(Float::Builder(1.2345E6), "1234500", DecimalMode); + assert_expression_prints_to(Float::Builder(-1.2345E6), "-1234500", DecimalMode); + assert_expression_prints_to(Float::Builder(0.0000009999999999999995), "0.000001", DecimalMode); + assert_expression_prints_to(Float::Builder(-1.2345E-1), "-0.12345", DecimalMode); - assert_expression_prints_to(Float(INFINITY), Infinity::Name(), DecimalMode); - assert_expression_prints_to(Float(0.0f), "0", DecimalMode); - assert_expression_prints_to(Float(NAN), Undefined::Name(), DecimalMode); + assert_expression_prints_to(Float::Builder(INFINITY), Infinity::Name(), DecimalMode); + assert_expression_prints_to(Float::Builder(0.0f), "0", DecimalMode); + assert_expression_prints_to(Float::Builder(NAN), Undefined::Name(), DecimalMode); } diff --git a/poincare/test/decimal.cpp b/poincare/test/decimal.cpp index 50a4c1e48..bb91c0114 100644 --- a/poincare/test/decimal.cpp +++ b/poincare/test/decimal.cpp @@ -8,10 +8,10 @@ using namespace Poincare; QUIZ_CASE(poincare_decimal_constructor) { int initialPoolSize = pool_size(); - Decimal a("123",2); - Decimal b("3456", -4); - Decimal c(2.34f); - Decimal d(2322.34); + Decimal a = Decimal::Builder("123",2); + Decimal b = Decimal::Builder("3456", -4); + Decimal c = Decimal::Builder(2.34f); + Decimal d = Decimal::Builder(2322.34); assert_pool_size(initialPoolSize+4); } @@ -24,23 +24,23 @@ static inline void assert_not_equal(const Decimal i, const Decimal j) { } QUIZ_CASE(poincare_decimal_compare) { - assert_equal(Decimal("25", 3), Decimal("25", 3)); - assert_equal(Decimal("1000", -3), Decimal("1", -3)); - assert_equal(Decimal("1000", 3), Decimal("1", 3)); - assert_not_equal(Decimal(123,234), Decimal(42, 108)); - assert_not_equal(Decimal(12,2), Decimal(123, 2)); - assert_not_equal(Decimal(1234,2), Decimal(1234,3)); - assert_not_equal(Decimal(12345,2), Decimal(1235,2)); - assert_not_equal(Decimal(123456, -2),Decimal(1234567, -3)); - assert_not_equal(Decimal(12345678, -2),Decimal(1234567, -2)); + assert_equal(Decimal::Builder("25", 3), Decimal::Builder("25", 3)); + assert_equal(Decimal::Builder("1000", -3), Decimal::Builder("1", -3)); + assert_equal(Decimal::Builder("1000", 3), Decimal::Builder("1", 3)); + assert_not_equal(Decimal::Builder(123,234), Decimal::Builder(42, 108)); + assert_not_equal(Decimal::Builder(12,2), Decimal::Builder(123, 2)); + assert_not_equal(Decimal::Builder(1234,2), Decimal::Builder(1234,3)); + assert_not_equal(Decimal::Builder(12345,2), Decimal::Builder(1235,2)); + assert_not_equal(Decimal::Builder(123456, -2),Decimal::Builder(1234567, -3)); + assert_not_equal(Decimal::Builder(12345678, -2),Decimal::Builder(1234567, -2)); } QUIZ_CASE(poincare_decimal_properties) { - quiz_assert(Decimal(-2, 3).sign() == ExpressionNode::Sign::Negative); - quiz_assert(Decimal(-2, -3).sign() == ExpressionNode::Sign::Negative); - quiz_assert(Decimal(2, -3).sign() == ExpressionNode::Sign::Positive); - quiz_assert(Decimal(2, 3).sign() == ExpressionNode::Sign::Positive); - quiz_assert(Decimal(0, 1).sign() == ExpressionNode::Sign::Positive); + quiz_assert(Decimal::Builder(-2, 3).sign() == ExpressionNode::Sign::Negative); + quiz_assert(Decimal::Builder(-2, -3).sign() == ExpressionNode::Sign::Negative); + quiz_assert(Decimal::Builder(2, -3).sign() == ExpressionNode::Sign::Positive); + quiz_assert(Decimal::Builder(2, 3).sign() == ExpressionNode::Sign::Positive); + quiz_assert(Decimal::Builder(0, 1).sign() == ExpressionNode::Sign::Positive); } // Simplify diff --git a/poincare/test/expression.cpp b/poincare/test/expression.cpp index 0f80f49fc..3881823bb 100644 --- a/poincare/test/expression.cpp +++ b/poincare/test/expression.cpp @@ -7,7 +7,7 @@ using namespace Poincare; QUIZ_CASE(expression_can_start_uninitialized) { Expression e; { - Rational i(1); + Rational i = Rational::Builder(1); e = i; } } diff --git a/poincare/test/expression_order.cpp b/poincare/test/expression_order.cpp index 2b2ca3408..3e90aa0c6 100644 --- a/poincare/test/expression_order.cpp +++ b/poincare/test/expression_order.cpp @@ -23,24 +23,24 @@ void assert_multiplication_or_addition_is_ordered_as(Expression e1, Expression e QUIZ_CASE(poincare_expression_order) { { // 2 * 5 - Expression e1 = Multiplication::Builder(Rational(5), Rational(2)); - Expression e2 = Multiplication::Builder(Rational(2), Rational(5)); + Expression e1 = Multiplication::Builder(Rational::Builder(5), Rational::Builder(2)); + Expression e2 = Multiplication::Builder(Rational::Builder(2), Rational::Builder(5)); assert_multiplication_or_addition_is_ordered_as(e1, e2); } { // 2 + 1 + 0 constexpr int numberOfChildren = 3; - Expression children[numberOfChildren] = {Rational(1), Rational(2), Rational(0)}; - Expression childrenSorted[numberOfChildren] = {Rational(2), Rational(1), Rational(0)}; + Expression children[numberOfChildren] = {Rational::Builder(1), Rational::Builder(2), Rational::Builder(0)}; + Expression childrenSorted[numberOfChildren] = {Rational::Builder(2), Rational::Builder(1), Rational::Builder(0)}; Expression e1 = Addition::Builder(children, numberOfChildren); Expression e2 = Addition::Builder(childrenSorted, numberOfChildren); assert_multiplication_or_addition_is_ordered_as(e1, e2); } { // e + pi + i - Expression pi = Constant(Ion::Charset::SmallPi); - Expression i = Constant(Ion::Charset::IComplex); - Expression e = Constant(Ion::Charset::Exponential); + Expression pi = Constant::Builder(Ion::Charset::SmallPi); + Expression i = Constant::Builder(Ion::Charset::IComplex); + Expression e = Constant::Builder(Ion::Charset::Exponential); constexpr int numberOfChildren = 3; Expression children[numberOfChildren] = {pi.clone(), i.clone(), e.clone()}; Expression childrenSorted[numberOfChildren] = {e, pi, i}; @@ -50,23 +50,23 @@ QUIZ_CASE(poincare_expression_order) { } { // 2 * root(3) - Expression e1 = Multiplication::Builder(SquareRoot::Builder(Rational(3)), Rational(2)); - Expression e2 = Multiplication::Builder(Rational(2), SquareRoot::Builder(Rational(3))); + Expression e1 = Multiplication::Builder(SquareRoot::Builder(Rational::Builder(3)), Rational::Builder(2)); + Expression e2 = Multiplication::Builder(Rational::Builder(2), SquareRoot::Builder(Rational::Builder(3))); assert_multiplication_or_addition_is_ordered_as(e1, e2); } { constexpr int numberOfChildren = 4; Expression children[numberOfChildren] = { - Symbol('c'), - Power::Builder(Symbol('b'), Rational(2)), - Power::Builder(Symbol('a'), Rational(2)), - Symbol('a') + Symbol::Builder('c'), + Power::Builder(Symbol::Builder('b'), Rational::Builder(2)), + Power::Builder(Symbol::Builder('a'), Rational::Builder(2)), + Symbol::Builder('a') }; Expression childrenSorted[numberOfChildren] = { - Power::Builder(Symbol('a'), Rational(2)), - Symbol('a'), - Power::Builder(Symbol('b'), Rational(2)), - Symbol('c') + Power::Builder(Symbol::Builder('a'), Rational::Builder(2)), + Symbol::Builder('a'), + Power::Builder(Symbol::Builder('b'), Rational::Builder(2)), + Symbol::Builder('c') }; // a^2 + a + b^2 + c Expression e1 = Addition::Builder(children, numberOfChildren); @@ -75,32 +75,32 @@ QUIZ_CASE(poincare_expression_order) { } { // 2*x^3 + 3*x^2 - Expression child1 = Multiplication::Builder(Rational(2), Power::Builder(Symbol('x'), Rational(3))); - Expression child2 = Multiplication::Builder(Rational(3), Power::Builder(Symbol('x'), Rational(2))); + Expression child1 = Multiplication::Builder(Rational::Builder(2), Power::Builder(Symbol::Builder('x'), Rational::Builder(3))); + Expression child2 = Multiplication::Builder(Rational::Builder(3), Power::Builder(Symbol::Builder('x'), Rational::Builder(2))); Expression e1 = Addition::Builder(child2.clone(), child1.clone()); Expression e2 = Addition::Builder(child1, child2); assert_multiplication_or_addition_is_ordered_as(e1, e2); } { // 3*x + 2*x - Expression child1 = Multiplication::Builder(Rational(3), Symbol('x')); - Expression child2 = Multiplication::Builder(Rational(2), Symbol('x')); + Expression child1 = Multiplication::Builder(Rational::Builder(3), Symbol::Builder('x')); + Expression child2 = Multiplication::Builder(Rational::Builder(2), Symbol::Builder('x')); Expression e1 = Addition::Builder(child2.clone(), child1.clone()); Expression e2 = Addition::Builder(child1, child2); assert_multiplication_or_addition_is_ordered_as(e1, e2); } { // pi^a * pi^b - Expression child1 = Power::Builder(Constant(Ion::Charset::SmallPi), Symbol('a')); - Expression child2 = Power::Builder(Constant(Ion::Charset::SmallPi), Symbol('b')); + Expression child1 = Power::Builder(Constant::Builder(Ion::Charset::SmallPi), Symbol::Builder('a')); + Expression child2 = Power::Builder(Constant::Builder(Ion::Charset::SmallPi), Symbol::Builder('b')); Expression e1 = Multiplication::Builder(child2.clone(), child1.clone()); Expression e2 = Multiplication::Builder(child1, child2); assert_multiplication_or_addition_is_ordered_as(e1, e2); } { // pi^2 * pi^3 - Expression child1 = Power::Builder(Constant(Ion::Charset::SmallPi), Rational(2)); - Expression child2 = Power::Builder(Constant(Ion::Charset::SmallPi), Rational(3)); + Expression child1 = Power::Builder(Constant::Builder(Ion::Charset::SmallPi), Rational::Builder(2)); + Expression child2 = Power::Builder(Constant::Builder(Ion::Charset::SmallPi), Rational::Builder(3)); Expression e1 = Multiplication::Builder(child2.clone(), child1.clone()); Expression e2 = Multiplication::Builder(child1, child2); assert_multiplication_or_addition_is_ordered_as(e1, e2); diff --git a/poincare/test/float.cpp b/poincare/test/float.cpp index d605cf819..1a17527a3 100644 --- a/poincare/test/float.cpp +++ b/poincare/test/float.cpp @@ -22,26 +22,26 @@ void assert_float_evaluates_to(Float f, const char * result) { } QUIZ_CASE(poincare_float_evaluate) { - assert_float_evaluates_to(Float(-1.23456789E30), "-1.23456789E30"); - assert_float_evaluates_to(Float(1.23456789E30), "1.23456789E30"); - assert_float_evaluates_to(Float(-1.23456789E-30), "-1.23456789E-30"); - assert_float_evaluates_to(Float(-1.2345E-3), "-0.0012345"); - assert_float_evaluates_to(Float(1.2345E-3), "0.0012345"); - assert_float_evaluates_to(Float(1.2345E3), "1234.5"); - assert_float_evaluates_to(Float(-1.2345E3), "-1234.5"); - assert_float_evaluates_to(Float(0.99999999999995), "9.9999999999995E-1"); - assert_float_evaluates_to(Float(0.00000099999999999995), "9.9999999999995E-7"); - assert_float_evaluates_to(Float(0.0000009999999999901200121020102010201201201021099995), "9.9999999999012E-7"); - assert_float_evaluates_to(Float(1.2345E-1), "0.12345"); - assert_float_evaluates_to(Float(1), "1"); - assert_float_evaluates_to(Float(0.9999999999999995), "1"); - assert_float_evaluates_to(Float(1.2345E6), "1234500"); - assert_float_evaluates_to(Float(-1.2345E6), "-1234500"); - assert_float_evaluates_to(Float(0.0000009999999999999995), "0.000001"); - assert_float_evaluates_to(Float(-1.2345E-1), "-0.12345"); + assert_float_evaluates_to(Float::Builder(-1.23456789E30), "-1.23456789E30"); + assert_float_evaluates_to(Float::Builder(1.23456789E30), "1.23456789E30"); + assert_float_evaluates_to(Float::Builder(-1.23456789E-30), "-1.23456789E-30"); + assert_float_evaluates_to(Float::Builder(-1.2345E-3), "-0.0012345"); + assert_float_evaluates_to(Float::Builder(1.2345E-3), "0.0012345"); + assert_float_evaluates_to(Float::Builder(1.2345E3), "1234.5"); + assert_float_evaluates_to(Float::Builder(-1.2345E3), "-1234.5"); + assert_float_evaluates_to(Float::Builder(0.99999999999995), "9.9999999999995E-1"); + assert_float_evaluates_to(Float::Builder(0.00000099999999999995), "9.9999999999995E-7"); + assert_float_evaluates_to(Float::Builder(0.0000009999999999901200121020102010201201201021099995), "9.9999999999012E-7"); + assert_float_evaluates_to(Float::Builder(1.2345E-1), "0.12345"); + assert_float_evaluates_to(Float::Builder(1), "1"); + assert_float_evaluates_to(Float::Builder(0.9999999999999995), "1"); + assert_float_evaluates_to(Float::Builder(1.2345E6), "1234500"); + assert_float_evaluates_to(Float::Builder(-1.2345E6), "-1234500"); + assert_float_evaluates_to(Float::Builder(0.0000009999999999999995), "0.000001"); + assert_float_evaluates_to(Float::Builder(-1.2345E-1), "-0.12345"); - assert_float_evaluates_to(Float(INFINITY), Infinity::Name()); - assert_float_evaluates_to(Float(0.0f), "0"); - assert_float_evaluates_to(Float(NAN), Undefined::Name()); + assert_float_evaluates_to(Float::Builder(INFINITY), Infinity::Name()); + assert_float_evaluates_to(Float::Builder(0.0f), "0"); + assert_float_evaluates_to(Float::Builder(NAN), Undefined::Name()); } diff --git a/poincare/test/fraction_layout.cpp b/poincare/test/fraction_layout.cpp index 9d38c8691..51417ed3f 100644 --- a/poincare/test/fraction_layout.cpp +++ b/poincare/test/fraction_layout.cpp @@ -41,11 +41,11 @@ QUIZ_CASE(poincare_fraction_layout_delete) { * |3 * */ HorizontalLayout layout2 = HorizontalLayout::Builder( - CharLayout('1'), - CharLayout('+'), + CharLayout::Builder('1'), + CharLayout::Builder('+'), FractionLayout::Builder( - EmptyLayout(), - CharLayout('3') + EmptyLayout::Builder(), + CharLayout::Builder('3') ) ); LayoutCursor cursor2(layout2.childAtIndex(2).childAtIndex(1), LayoutCursor::Position::Left); @@ -56,7 +56,7 @@ QUIZ_CASE(poincare_fraction_layout_delete) { QUIZ_CASE(poincare_fraction_layout_serialize) { FractionLayout layout = FractionLayout::Builder( - CharLayout('1'), + CharLayout::Builder('1'), LayoutHelper::String("2+3", 3) ); assert_expression_layout_serialize_to(layout, "(1)/(2+3)"); diff --git a/poincare/test/layouts.cpp b/poincare/test/layouts.cpp index a69665b59..c8ee32a97 100644 --- a/poincare/test/layouts.cpp +++ b/poincare/test/layouts.cpp @@ -42,9 +42,9 @@ void assert_parsed_layout_is(Layout l, Poincare::Expression r) { } QUIZ_CASE(poincare_create_all_layouts) { - EmptyLayout e0; + EmptyLayout e0 = EmptyLayout::Builder(); AbsoluteValueLayout e1 = AbsoluteValueLayout::Builder(e0); - CharLayout e2('a'); + CharLayout e2 = CharLayout::Builder('a'); BinomialCoefficientLayout e3 = BinomialCoefficientLayout::Builder(e1, e2); CeilingLayout e4 = CeilingLayout::Builder(e3); RightParenthesisLayout e5 = RightParenthesisLayout::Builder(); @@ -59,13 +59,13 @@ QUIZ_CASE(poincare_create_all_layouts) { IntegralLayout e15 = IntegralLayout::Builder(e11, e12, e13, e14); NthRootLayout e16 = NthRootLayout::Builder(e15); MatrixLayout e17 = MatrixLayout::Builder(); - EmptyLayout e18; - EmptyLayout e19; - EmptyLayout e20; + EmptyLayout e18 = EmptyLayout::Builder(); + EmptyLayout e19 = EmptyLayout::Builder(); + EmptyLayout e20 = EmptyLayout::Builder(); ProductLayout e21 = ProductLayout::Builder(e17, e18, e19, e20); - EmptyLayout e22; - EmptyLayout e23; - EmptyLayout e24; + EmptyLayout e22 = EmptyLayout::Builder(); + EmptyLayout e23 = EmptyLayout::Builder(); + EmptyLayout e24 = EmptyLayout::Builder(); SumLayout e25 = SumLayout::Builder(e21, e22, e23, e24); VerticalOffsetLayout e26 = VerticalOffsetLayout::Builder(e25, VerticalOffsetLayoutNode::Type::Superscript); } @@ -82,194 +82,194 @@ QUIZ_CASE(poincare_parse_layouts) { // 1+2 l = HorizontalLayout::Builder( - CharLayout('1'), - CharLayout('+'), - CharLayout('2')); - e = Addition::Builder(Rational(1), Rational(2)); + CharLayout::Builder('1'), + CharLayout::Builder('+'), + CharLayout::Builder('2')); + e = Addition::Builder(Rational::Builder(1), Rational::Builder(2)); assert_parsed_layout_is(l, e); // |3+3/6| l = AbsoluteValueLayout:: Builder( HorizontalLayout::Builder( - CharLayout('3'), - CharLayout('+'), + CharLayout::Builder('3'), + CharLayout::Builder('+'), FractionLayout::Builder( - CharLayout('3'), - CharLayout('6')))); + CharLayout::Builder('3'), + CharLayout::Builder('6')))); e = AbsoluteValue::Builder( Addition::Builder( - Rational(3), + Rational::Builder(3), Division::Builder( - Rational(3), - Rational(6)))); + Rational::Builder(3), + Rational::Builder(6)))); assert_parsed_layout_is(l, e); // binCoef(4,5) l = BinomialCoefficientLayout::Builder( - CharLayout('4'), - CharLayout('5')); + CharLayout::Builder('4'), + CharLayout::Builder('5')); e = BinomialCoefficient::Builder( - Rational(4), - Rational(5)); + Rational::Builder(4), + Rational::Builder(5)); assert_parsed_layout_is(l, e); // ceil(4.6) l = CeilingLayout::Builder( HorizontalLayout::Builder( - CharLayout('4'), - CharLayout('.'), - CharLayout('6'))); + CharLayout::Builder('4'), + CharLayout::Builder('.'), + CharLayout::Builder('6'))); e = Ceiling::Builder( - Decimal(4.6)); + Decimal::Builder(4.6)); assert_parsed_layout_is(l, e); // floor(7.2) l = FloorLayout::Builder( HorizontalLayout::Builder( - CharLayout('7'), - CharLayout('.'), - CharLayout('2'))); + CharLayout::Builder('7'), + CharLayout::Builder('.'), + CharLayout::Builder('2'))); e = Floor::Builder( - Decimal(7.2)); + Decimal::Builder(7.2)); assert_parsed_layout_is(l, e); // 2^(3+4) l = HorizontalLayout::Builder( - CharLayout('2'), + CharLayout::Builder('2'), VerticalOffsetLayout::Builder( HorizontalLayout::Builder( - CharLayout('3'), - CharLayout('+'), - CharLayout('4')), + CharLayout::Builder('3'), + CharLayout::Builder('+'), + CharLayout::Builder('4')), VerticalOffsetLayoutNode::Type::Superscript)); e = Power::Builder( - Rational(2), + Rational::Builder(2), Addition::Builder( - Rational(3), - Rational(4))); + Rational::Builder(3), + Rational::Builder(4))); assert_parsed_layout_is(l, e); // log_3(2) HorizontalLayout l1 = HorizontalLayout::Builder(); - l1.addChildAtIndex(CharLayout('l'), l1.numberOfChildren(), l1.numberOfChildren(), nullptr); - l1.addChildAtIndex(CharLayout('o'), l1.numberOfChildren(), l1.numberOfChildren(), nullptr); - l1.addChildAtIndex(CharLayout('g'), l1.numberOfChildren(), l1.numberOfChildren(), nullptr); - l1.addChildAtIndex(VerticalOffsetLayout::Builder(CharLayout('3'), VerticalOffsetLayoutNode::Type::Subscript), l1.numberOfChildren(), l1.numberOfChildren(), nullptr); + l1.addChildAtIndex(CharLayout::Builder('l'), l1.numberOfChildren(), l1.numberOfChildren(), nullptr); + l1.addChildAtIndex(CharLayout::Builder('o'), l1.numberOfChildren(), l1.numberOfChildren(), nullptr); + l1.addChildAtIndex(CharLayout::Builder('g'), l1.numberOfChildren(), l1.numberOfChildren(), nullptr); + l1.addChildAtIndex(VerticalOffsetLayout::Builder(CharLayout::Builder('3'), VerticalOffsetLayoutNode::Type::Subscript), l1.numberOfChildren(), l1.numberOfChildren(), nullptr); l1.addChildAtIndex(LeftParenthesisLayout::Builder(), l1.numberOfChildren(), l1.numberOfChildren(), nullptr); - l1.addChildAtIndex(CharLayout('2'), l1.numberOfChildren(), l1.numberOfChildren(), nullptr); + l1.addChildAtIndex(CharLayout::Builder('2'), l1.numberOfChildren(), l1.numberOfChildren(), nullptr); l1.addChildAtIndex(RightParenthesisLayout::Builder(), l1.numberOfChildren(), l1.numberOfChildren(), nullptr); l = l1; e = Logarithm::Builder( - Rational(2), - Rational(3)); + Rational::Builder(2), + Rational::Builder(3)); assert_parsed_layout_is(l, e); // root(5,3) l = NthRootLayout::Builder( - CharLayout('5'), - CharLayout('3')); - e = NthRoot::Builder(Rational(5), Rational(3)); + CharLayout::Builder('5'), + CharLayout::Builder('3')); + e = NthRoot::Builder(Rational::Builder(5), Rational::Builder(3)); assert_parsed_layout_is(l, e); // int(7, x, 4, 5) l = IntegralLayout::Builder( - CharLayout('7'), - CharLayout('x'), - CharLayout('4'), - CharLayout('5')); + CharLayout::Builder('7'), + CharLayout::Builder('x'), + CharLayout::Builder('4'), + CharLayout::Builder('5')); e = Integral::Builder( - Rational(7), - Symbol('x'), - Rational(4), - Rational(5)); + Rational::Builder(7), + Symbol::Builder('x'), + Rational::Builder(4), + Rational::Builder(5)); assert_parsed_layout_is(l, e); // 2^2 ! l = HorizontalLayout::Builder( - CharLayout('2'), + CharLayout::Builder('2'), VerticalOffsetLayout::Builder( - CharLayout('2'), + CharLayout::Builder('2'), VerticalOffsetLayoutNode::Type::Superscript), - CharLayout('!')); + CharLayout::Builder('!')); e = Factorial::Builder( Power::Builder( - Rational(2), - Rational(2))); + Rational::Builder(2), + Rational::Builder(2))); assert_parsed_layout_is(l, e); // 5* 6/(7+5) *3 l = HorizontalLayout::Builder( - CharLayout('5'), + CharLayout::Builder('5'), FractionLayout::Builder( - CharLayout('6'), + CharLayout::Builder('6'), HorizontalLayout::Builder( - CharLayout('7'), - CharLayout('+'), - CharLayout('5'))), - CharLayout('3')); + CharLayout::Builder('7'), + CharLayout::Builder('+'), + CharLayout::Builder('5'))), + CharLayout::Builder('3')); e = Multiplication::Builder( - Rational(5), + Rational::Builder(5), Division::Builder( - Rational(6), + Rational::Builder(6), Addition::Builder( - Rational(7), - Rational(5))), - Rational(3)); + Rational::Builder(7), + Rational::Builder(5))), + Rational::Builder(3)); assert_parsed_layout_is(l, e); // [[3^2!, 7][4,5] l = MatrixLayout::Builder( HorizontalLayout::Builder( - CharLayout('3'), + CharLayout::Builder('3'), VerticalOffsetLayout::Builder( - CharLayout('2'), + CharLayout::Builder('2'), VerticalOffsetLayoutNode::Type::Superscript), - CharLayout('!')), - CharLayout('7'), - CharLayout('4'), - CharLayout('5')); + CharLayout::Builder('!')), + CharLayout::Builder('7'), + CharLayout::Builder('4'), + CharLayout::Builder('5')); Matrix m = BuildOneChildMatrix( Factorial::Builder( Power::Builder( - Rational(3), - Rational(2)))); - m.addChildAtIndexInPlace(Rational(7), 1, 1); - m.addChildAtIndexInPlace(Rational(4), 2, 2); - m.addChildAtIndexInPlace(Rational(5), 3, 3); + Rational::Builder(3), + Rational::Builder(2)))); + m.addChildAtIndexInPlace(Rational::Builder(7), 1, 1); + m.addChildAtIndexInPlace(Rational::Builder(4), 2, 2); + m.addChildAtIndexInPlace(Rational::Builder(5), 3, 3); m.setDimensions(2,2); e = m; assert_parsed_layout_is(l, e); // 2^det([[3!, 7][4,5]) l = HorizontalLayout::Builder( - CharLayout('2'), + CharLayout::Builder('2'), VerticalOffsetLayout::Builder( MatrixLayout::Builder( HorizontalLayout::Builder( - CharLayout('3'), - CharLayout('!')), - CharLayout('7'), - CharLayout('4'), - CharLayout('5')), + CharLayout::Builder('3'), + CharLayout::Builder('!')), + CharLayout::Builder('7'), + CharLayout::Builder('4'), + CharLayout::Builder('5')), VerticalOffsetLayoutNode::Type::Superscript)); m = BuildOneChildMatrix( Factorial::Builder( - Rational(3))); - m.addChildAtIndexInPlace(Rational(7), 1, 1); - m.addChildAtIndexInPlace(Rational(4), 2, 2); - m.addChildAtIndexInPlace(Rational(5), 3, 3); + Rational::Builder(3))); + m.addChildAtIndexInPlace(Rational::Builder(7), 1, 1); + m.addChildAtIndexInPlace(Rational::Builder(4), 2, 2); + m.addChildAtIndexInPlace(Rational::Builder(5), 3, 3); m.setDimensions(2,2); - e = Power::Builder(Rational(2), m); + e = Power::Builder(Rational::Builder(2), m); assert_parsed_layout_is(l, e); // 2e^3 l = HorizontalLayout::Builder( - CharLayout('2'), - CharLayout(Ion::Charset::Exponential), + CharLayout::Builder('2'), + CharLayout::Builder(Ion::Charset::Exponential), VerticalOffsetLayout::Builder( - CharLayout('3'), + CharLayout::Builder('3'), VerticalOffsetLayoutNode::Type::Superscript)); - e = Multiplication::Builder(Rational(2),Power::Builder(Constant(Ion::Charset::Exponential),Parenthesis::Builder(Rational(3)))); - assert_parsed_expression_is("2X^(3)", Multiplication::Builder(Rational(2),Power::Builder(Constant(Ion::Charset::Exponential),Parenthesis::Builder(Rational(3))))); + e = Multiplication::Builder(Rational::Builder(2),Power::Builder(Constant::Builder(Ion::Charset::Exponential),Parenthesis::Builder(Rational::Builder(3)))); + assert_parsed_expression_is("2X^(3)", Multiplication::Builder(Rational::Builder(2),Power::Builder(Constant::Builder(Ion::Charset::Exponential),Parenthesis::Builder(Rational::Builder(3))))); assert_parsed_layout_is(l, e); } diff --git a/poincare/test/number.cpp b/poincare/test/number.cpp index 5bdcb2316..078ced52d 100644 --- a/poincare/test/number.cpp +++ b/poincare/test/number.cpp @@ -12,27 +12,27 @@ using namespace Poincare; QUIZ_CASE(poincare_number_parser) { // Integer - assert_parsed_expression_is("123456789012345678765434567", Rational("123456789012345678765434567")); - assert_parsed_expression_is(MaxIntegerString(), Rational(MaxIntegerString())); + assert_parsed_expression_is("123456789012345678765434567", Rational::Builder("123456789012345678765434567")); + assert_parsed_expression_is(MaxIntegerString(), Rational::Builder(MaxIntegerString())); // Integer parsed in Decimal because they overflow Integer - assert_parsed_expression_is(OverflowedIntegerString(), Decimal(Integer("17976931348623"), 308)); - assert_parsed_expression_is("179769313486235590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216", Decimal(Integer("17976931348624"), 308)); + assert_parsed_expression_is(OverflowedIntegerString(), Decimal::Builder(Integer("17976931348623"), 308)); + assert_parsed_expression_is("179769313486235590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216", Decimal::Builder(Integer("17976931348624"), 308)); // Decimal with rounding when digits are above 14 - assert_parsed_expression_is("0.0000012345678901234", Decimal(Integer("12345678901234"), -6)); - assert_parsed_expression_is("0.00000123456789012345", Decimal(Integer("12345678901235"), -6)); - assert_parsed_expression_is("0.00000123456789012341", Decimal(Integer("12345678901234"), -6)); - assert_parsed_expression_is("1234567890123.4", Decimal(Integer("12345678901234"), 12)); - assert_parsed_expression_is("123456789012345.2", Decimal(Integer("12345678901235"), 14)); - assert_parsed_expression_is("123456789012341.2", Decimal(Integer("12345678901234"), 14)); - assert_parsed_expression_is("12.34567", Decimal(Integer("1234567"), 1)); + assert_parsed_expression_is("0.0000012345678901234", Decimal::Builder(Integer("12345678901234"), -6)); + assert_parsed_expression_is("0.00000123456789012345", Decimal::Builder(Integer("12345678901235"), -6)); + assert_parsed_expression_is("0.00000123456789012341", Decimal::Builder(Integer("12345678901234"), -6)); + assert_parsed_expression_is("1234567890123.4", Decimal::Builder(Integer("12345678901234"), 12)); + assert_parsed_expression_is("123456789012345.2", Decimal::Builder(Integer("12345678901235"), 14)); + assert_parsed_expression_is("123456789012341.2", Decimal::Builder(Integer("12345678901234"), 14)); + assert_parsed_expression_is("12.34567", Decimal::Builder(Integer("1234567"), 1)); // Infinity - assert_parsed_expression_is("23E1000", Infinity(false)); - assert_parsed_expression_is("2.3E1000", Decimal(Integer(23), 1000)); + assert_parsed_expression_is("23E1000", Infinity::Builder(false)); + assert_parsed_expression_is("2.3E1000", Decimal::Builder(Integer(23), 1000)); // Zero - assert_parsed_expression_is("0.23E-1000", Decimal(Integer(0), 0)); - assert_parsed_expression_is("0.23E-999", Decimal(Integer(23), -1000)); + assert_parsed_expression_is("0.23E-1000", Decimal::Builder(Integer(0), 0)); + assert_parsed_expression_is("0.23E-999", Decimal::Builder(Integer(23), -1000)); } diff --git a/poincare/test/parentheses_layout.cpp b/poincare/test/parentheses_layout.cpp index 31cb61069..1cb82c0d3 100644 --- a/poincare/test/parentheses_layout.cpp +++ b/poincare/test/parentheses_layout.cpp @@ -16,16 +16,16 @@ QUIZ_CASE(poincare_parenthesis_layout_size) { LeftParenthesisLayout leftPar = LeftParenthesisLayout::Builder(); RightParenthesisLayout rightPar = RightParenthesisLayout::Builder(); layout.addChildAtIndex(leftPar, 0, 0, nullptr); - layout.addChildAtIndex(CharLayout('2'), 1, 1, nullptr); - layout.addChildAtIndex(CharLayout('+'), 2, 2, nullptr); + layout.addChildAtIndex(CharLayout::Builder('2'), 1, 1, nullptr); + layout.addChildAtIndex(CharLayout::Builder('+'), 2, 2, nullptr); layout.addChildAtIndex(LeftParenthesisLayout::Builder(), 3, 3, nullptr); layout.addChildAtIndex(FractionLayout::Builder( - CharLayout('3'), - CharLayout('4')), + CharLayout::Builder('3'), + CharLayout::Builder('4')), 4, 4, nullptr); layout.addChildAtIndex(RightParenthesisLayout::Builder(), 4, 4, nullptr); - layout.addChildAtIndex(CharLayout('6'), 5, 5, nullptr); + layout.addChildAtIndex(CharLayout::Builder('6'), 5, 5, nullptr); layout.addChildAtIndex(rightPar, 7, 7, nullptr); - layout.addChildAtIndex(CharLayout('1'), 8, 8, nullptr); + layout.addChildAtIndex(CharLayout::Builder('1'), 8, 8, nullptr); quiz_assert(leftPar.layoutSize().height() == rightPar.layoutSize().height()); } diff --git a/poincare/test/parser.cpp b/poincare/test/parser.cpp index f8f9cff22..2c50972f9 100644 --- a/poincare/test/parser.cpp +++ b/poincare/test/parser.cpp @@ -84,18 +84,18 @@ QUIZ_CASE(poincare_parser_parse_numbers) { assert_pool_size(initialPoolSize); // Parse digits - assert_parsed_expression_is("0", Rational(0)); - assert_parsed_expression_is("0.1", Decimal(0.1)); - assert_parsed_expression_is("1.", Rational(1)); - assert_parsed_expression_is(".1", Decimal(0.1)); - assert_parsed_expression_is("0E2", Decimal(0.0)); - assert_parsed_expression_is("0.1E2", Decimal(10.0)); - assert_parsed_expression_is("1.E2", Decimal(100.0)); - assert_parsed_expression_is(".1E2", Decimal(10.0)); - assert_parsed_expression_is("0E-2", Decimal(0.0)); - assert_parsed_expression_is("0.1E-2", Decimal(0.001)); - assert_parsed_expression_is("1.E-2", Decimal(0.01)); - assert_parsed_expression_is(".1E-2", Decimal(0.001)); + assert_parsed_expression_is("0", Rational::Builder(0)); + assert_parsed_expression_is("0.1", Decimal::Builder(0.1)); + assert_parsed_expression_is("1.", Rational::Builder(1)); + assert_parsed_expression_is(".1", Decimal::Builder(0.1)); + assert_parsed_expression_is("0E2", Decimal::Builder(0.0)); + assert_parsed_expression_is("0.1E2", Decimal::Builder(10.0)); + assert_parsed_expression_is("1.E2", Decimal::Builder(100.0)); + assert_parsed_expression_is(".1E2", Decimal::Builder(10.0)); + assert_parsed_expression_is("0E-2", Decimal::Builder(0.0)); + assert_parsed_expression_is("0.1E-2", Decimal::Builder(0.001)); + assert_parsed_expression_is("1.E-2", Decimal::Builder(0.01)); + assert_parsed_expression_is(".1E-2", Decimal::Builder(0.001)); } QUIZ_CASE(poincare_parser_memory_exhaustion) { @@ -123,66 +123,66 @@ QUIZ_CASE(poincare_parser_memory_exhaustion) { } QUIZ_CASE(poincare_parser_parse) { - assert_parsed_expression_is("1", Rational(1)); - assert_parsed_expression_is("(1)", Parenthesis::Builder(Rational(1))); - assert_parsed_expression_is("((1))", Parenthesis::Builder((Expression)Parenthesis::Builder(Rational(1)))); - assert_parsed_expression_is("1+2", Addition::Builder(Rational(1),Rational(2))); - assert_parsed_expression_is("(1)+2", Addition::Builder(Parenthesis::Builder(Rational(1)),Rational(2))); - assert_parsed_expression_is("(1+2)", Parenthesis::Builder(Addition::Builder(Rational(1),Rational(2)))); - assert_parsed_expression_is("1+2+3", Addition::Builder(Addition::Builder(Rational(1),Rational(2)),Rational(3))); - assert_parsed_expression_is("1+2+(3+4)", Addition::Builder(Addition::Builder(Rational(1),Rational(2)),Parenthesis::Builder(Addition::Builder(Rational(3),Rational(4))))); - assert_parsed_expression_is("1*2", Multiplication::Builder(Rational(1),Rational(2))); - assert_parsed_expression_is("1*2*3", Multiplication::Builder(Multiplication::Builder(Rational(1),Rational(2)),Rational(3))); - assert_parsed_expression_is("1+2*3", Addition::Builder(Rational(1), Multiplication::Builder(Rational(2), Rational(3)))); - assert_parsed_expression_is("1/2", Division::Builder(Rational(1),Rational(2))); - assert_parsed_expression_is("(1/2)", Parenthesis::Builder(Division::Builder(Rational(1),Rational(2)))); - assert_parsed_expression_is("1/2/3", Division::Builder(Division::Builder(Rational(1),Rational(2)),Rational(3))); - assert_parsed_expression_is("1/2*3", Multiplication::Builder(Division::Builder(Rational(1),Rational(2)),Rational(3))); - assert_parsed_expression_is("(1/2*3)", Parenthesis::Builder(Multiplication::Builder(Division::Builder(Rational(1),Rational(2)),Rational(3)))); - assert_parsed_expression_is("1*2/3", Multiplication::Builder(Rational(1),Division::Builder(Rational(2),Rational(3)))); - assert_parsed_expression_is("(1*2/3)", Parenthesis::Builder(Multiplication::Builder(Rational(1),Division::Builder(Rational(2),Rational(3))))); - assert_parsed_expression_is("(1/2/3)", Parenthesis::Builder(Division::Builder(Division::Builder(Rational(1),Rational(2)),Rational(3)))); - assert_parsed_expression_is("1^2", Power::Builder(Rational(1),Rational(2))); - assert_parsed_expression_is("1^2^3", Power::Builder(Rational(1),Power::Builder(Rational(2),Rational(3)))); - assert_parsed_expression_is("1=2", Equal(Rational(1),Rational(2))); + assert_parsed_expression_is("1", Rational::Builder(1)); + assert_parsed_expression_is("(1)", Parenthesis::Builder(Rational::Builder(1))); + assert_parsed_expression_is("((1))", Parenthesis::Builder((Expression)Parenthesis::Builder(Rational::Builder(1)))); + assert_parsed_expression_is("1+2", Addition::Builder(Rational::Builder(1),Rational::Builder(2))); + assert_parsed_expression_is("(1)+2", Addition::Builder(Parenthesis::Builder(Rational::Builder(1)),Rational::Builder(2))); + assert_parsed_expression_is("(1+2)", Parenthesis::Builder(Addition::Builder(Rational::Builder(1),Rational::Builder(2)))); + assert_parsed_expression_is("1+2+3", Addition::Builder(Addition::Builder(Rational::Builder(1),Rational::Builder(2)),Rational::Builder(3))); + assert_parsed_expression_is("1+2+(3+4)", Addition::Builder(Addition::Builder(Rational::Builder(1),Rational::Builder(2)),Parenthesis::Builder(Addition::Builder(Rational::Builder(3),Rational::Builder(4))))); + assert_parsed_expression_is("1*2", Multiplication::Builder(Rational::Builder(1),Rational::Builder(2))); + assert_parsed_expression_is("1*2*3", Multiplication::Builder(Multiplication::Builder(Rational::Builder(1),Rational::Builder(2)),Rational::Builder(3))); + assert_parsed_expression_is("1+2*3", Addition::Builder(Rational::Builder(1), Multiplication::Builder(Rational::Builder(2), Rational::Builder(3)))); + assert_parsed_expression_is("1/2", Division::Builder(Rational::Builder(1),Rational::Builder(2))); + assert_parsed_expression_is("(1/2)", Parenthesis::Builder(Division::Builder(Rational::Builder(1),Rational::Builder(2)))); + assert_parsed_expression_is("1/2/3", Division::Builder(Division::Builder(Rational::Builder(1),Rational::Builder(2)),Rational::Builder(3))); + assert_parsed_expression_is("1/2*3", Multiplication::Builder(Division::Builder(Rational::Builder(1),Rational::Builder(2)),Rational::Builder(3))); + assert_parsed_expression_is("(1/2*3)", Parenthesis::Builder(Multiplication::Builder(Division::Builder(Rational::Builder(1),Rational::Builder(2)),Rational::Builder(3)))); + assert_parsed_expression_is("1*2/3", Multiplication::Builder(Rational::Builder(1),Division::Builder(Rational::Builder(2),Rational::Builder(3)))); + assert_parsed_expression_is("(1*2/3)", Parenthesis::Builder(Multiplication::Builder(Rational::Builder(1),Division::Builder(Rational::Builder(2),Rational::Builder(3))))); + assert_parsed_expression_is("(1/2/3)", Parenthesis::Builder(Division::Builder(Division::Builder(Rational::Builder(1),Rational::Builder(2)),Rational::Builder(3)))); + assert_parsed_expression_is("1^2", Power::Builder(Rational::Builder(1),Rational::Builder(2))); + assert_parsed_expression_is("1^2^3", Power::Builder(Rational::Builder(1),Power::Builder(Rational::Builder(2),Rational::Builder(3)))); + assert_parsed_expression_is("1=2", Equal::Builder(Rational::Builder(1),Rational::Builder(2))); assert_raises_parsing_error("=5"); assert_raises_parsing_error("1=2=3"); - assert_parsed_expression_is("-1", Opposite::Builder(Rational(1))); - assert_parsed_expression_is("(-1)", Parenthesis::Builder(Opposite::Builder(Rational(1)))); - assert_parsed_expression_is("1-2", Subtraction::Builder(Rational(1),Rational(2))); - assert_parsed_expression_is("-1-2", Subtraction::Builder(Opposite::Builder(Rational(1)),Rational(2))); - assert_parsed_expression_is("1-2-3", Subtraction::Builder(Subtraction::Builder(Rational(1),Rational(2)),Rational(3))); - assert_parsed_expression_is("(1-2)", Parenthesis::Builder(Subtraction::Builder(Rational(1),Rational(2)))); - assert_parsed_expression_is("1+-2", Addition::Builder(Rational(1),Opposite::Builder(Rational(2)))); - assert_parsed_expression_is("--1", Opposite::Builder((Expression)Opposite::Builder(Rational(1)))); - assert_parsed_expression_is("(1+2)-3", Subtraction::Builder(Parenthesis::Builder(Addition::Builder(Rational(1),Rational(2))),Rational(3))); - assert_parsed_expression_is("(2*-3)", Parenthesis::Builder(Multiplication::Builder(Rational(2),Opposite::Builder(Rational(3))))); - assert_parsed_expression_is("1^(2)-3", Subtraction::Builder(Power::Builder(Rational(1),Parenthesis::Builder(Rational(2))),Rational(3))); - assert_parsed_expression_is("1^2-3", Subtraction::Builder(Power::Builder(Rational(1),Rational(2)),Rational(3))); - assert_parsed_expression_is("2^-3", Power::Builder(Rational(2),Opposite::Builder(Rational(3)))); - assert_parsed_expression_is("2--2+-1", Addition::Builder(Subtraction::Builder(Rational(2),Opposite::Builder(Rational(2))),Opposite::Builder(Rational(1)))); - assert_parsed_expression_is("2--2*-1", Subtraction::Builder(Rational(2),Opposite::Builder(Multiplication::Builder(Rational(2),Opposite::Builder(Rational(1)))))); - assert_parsed_expression_is("-1^2", Opposite::Builder(Power::Builder(Rational(1),Rational(2)))); - assert_parsed_expression_is("2/-3/-4", Division::Builder(Division::Builder(Rational(2),Opposite::Builder(Rational(3))),Opposite::Builder(Rational(4)))); - assert_parsed_expression_is("1*2-3*4", Subtraction::Builder(Multiplication::Builder(Rational(1),Rational(2)),Multiplication::Builder(Rational(3),Rational(4)))); - assert_parsed_expression_is("-1*2", Opposite::Builder(Multiplication::Builder(Rational(1), Rational(2)))); - assert_parsed_expression_is("1!", Factorial::Builder(Rational(1))); - assert_parsed_expression_is("1+2!", Addition::Builder(Rational(1),Factorial::Builder(Rational(2)))); - assert_parsed_expression_is("1!+2", Addition::Builder(Factorial::Builder(Rational(1)),Rational(2))); - assert_parsed_expression_is("1!+2!", Addition::Builder(Factorial::Builder(Rational(1)),Factorial::Builder(Rational(2)))); - assert_parsed_expression_is("1*2!", Multiplication::Builder(Rational(1),Factorial::Builder(Rational(2)))); - assert_parsed_expression_is("1!*2", Multiplication::Builder(Factorial::Builder(Rational(1)),Rational(2))); - assert_parsed_expression_is("1!*2!", Multiplication::Builder(Factorial::Builder(Rational(1)),Factorial::Builder(Rational(2)))); - assert_parsed_expression_is("1-2!", Subtraction::Builder(Rational(1),Factorial::Builder(Rational(2)))); - assert_parsed_expression_is("1!-2", Subtraction::Builder(Factorial::Builder(Rational(1)),Rational(2))); - assert_parsed_expression_is("1!-2!", Subtraction::Builder(Factorial::Builder(Rational(1)),Factorial::Builder(Rational(2)))); - assert_parsed_expression_is("1/2!", Division::Builder(Rational(1),Factorial::Builder(Rational(2)))); - assert_parsed_expression_is("1!/2", Division::Builder(Factorial::Builder(Rational(1)),Rational(2))); - assert_parsed_expression_is("1!/2!", Division::Builder(Factorial::Builder(Rational(1)),Factorial::Builder(Rational(2)))); - assert_parsed_expression_is("1^2!", Power::Builder(Rational(1),Factorial::Builder(Rational(2)))); - assert_parsed_expression_is("1!^2", Power::Builder(Factorial::Builder(Rational(1)),Rational(2))); - assert_parsed_expression_is("1!^2!", Power::Builder(Factorial::Builder(Rational(1)),Factorial::Builder(Rational(2)))); - assert_parsed_expression_is("(1)!", Factorial::Builder(Parenthesis::Builder(Rational(1)))); + assert_parsed_expression_is("-1", Opposite::Builder(Rational::Builder(1))); + assert_parsed_expression_is("(-1)", Parenthesis::Builder(Opposite::Builder(Rational::Builder(1)))); + assert_parsed_expression_is("1-2", Subtraction::Builder(Rational::Builder(1),Rational::Builder(2))); + assert_parsed_expression_is("-1-2", Subtraction::Builder(Opposite::Builder(Rational::Builder(1)),Rational::Builder(2))); + assert_parsed_expression_is("1-2-3", Subtraction::Builder(Subtraction::Builder(Rational::Builder(1),Rational::Builder(2)),Rational::Builder(3))); + assert_parsed_expression_is("(1-2)", Parenthesis::Builder(Subtraction::Builder(Rational::Builder(1),Rational::Builder(2)))); + assert_parsed_expression_is("1+-2", Addition::Builder(Rational::Builder(1),Opposite::Builder(Rational::Builder(2)))); + assert_parsed_expression_is("--1", Opposite::Builder((Expression)Opposite::Builder(Rational::Builder(1)))); + assert_parsed_expression_is("(1+2)-3", Subtraction::Builder(Parenthesis::Builder(Addition::Builder(Rational::Builder(1),Rational::Builder(2))),Rational::Builder(3))); + assert_parsed_expression_is("(2*-3)", Parenthesis::Builder(Multiplication::Builder(Rational::Builder(2),Opposite::Builder(Rational::Builder(3))))); + assert_parsed_expression_is("1^(2)-3", Subtraction::Builder(Power::Builder(Rational::Builder(1),Parenthesis::Builder(Rational::Builder(2))),Rational::Builder(3))); + assert_parsed_expression_is("1^2-3", Subtraction::Builder(Power::Builder(Rational::Builder(1),Rational::Builder(2)),Rational::Builder(3))); + assert_parsed_expression_is("2^-3", Power::Builder(Rational::Builder(2),Opposite::Builder(Rational::Builder(3)))); + assert_parsed_expression_is("2--2+-1", Addition::Builder(Subtraction::Builder(Rational::Builder(2),Opposite::Builder(Rational::Builder(2))),Opposite::Builder(Rational::Builder(1)))); + assert_parsed_expression_is("2--2*-1", Subtraction::Builder(Rational::Builder(2),Opposite::Builder(Multiplication::Builder(Rational::Builder(2),Opposite::Builder(Rational::Builder(1)))))); + assert_parsed_expression_is("-1^2", Opposite::Builder(Power::Builder(Rational::Builder(1),Rational::Builder(2)))); + assert_parsed_expression_is("2/-3/-4", Division::Builder(Division::Builder(Rational::Builder(2),Opposite::Builder(Rational::Builder(3))),Opposite::Builder(Rational::Builder(4)))); + assert_parsed_expression_is("1*2-3*4", Subtraction::Builder(Multiplication::Builder(Rational::Builder(1),Rational::Builder(2)),Multiplication::Builder(Rational::Builder(3),Rational::Builder(4)))); + assert_parsed_expression_is("-1*2", Opposite::Builder(Multiplication::Builder(Rational::Builder(1), Rational::Builder(2)))); + assert_parsed_expression_is("1!", Factorial::Builder(Rational::Builder(1))); + assert_parsed_expression_is("1+2!", Addition::Builder(Rational::Builder(1),Factorial::Builder(Rational::Builder(2)))); + assert_parsed_expression_is("1!+2", Addition::Builder(Factorial::Builder(Rational::Builder(1)),Rational::Builder(2))); + assert_parsed_expression_is("1!+2!", Addition::Builder(Factorial::Builder(Rational::Builder(1)),Factorial::Builder(Rational::Builder(2)))); + assert_parsed_expression_is("1*2!", Multiplication::Builder(Rational::Builder(1),Factorial::Builder(Rational::Builder(2)))); + assert_parsed_expression_is("1!*2", Multiplication::Builder(Factorial::Builder(Rational::Builder(1)),Rational::Builder(2))); + assert_parsed_expression_is("1!*2!", Multiplication::Builder(Factorial::Builder(Rational::Builder(1)),Factorial::Builder(Rational::Builder(2)))); + assert_parsed_expression_is("1-2!", Subtraction::Builder(Rational::Builder(1),Factorial::Builder(Rational::Builder(2)))); + assert_parsed_expression_is("1!-2", Subtraction::Builder(Factorial::Builder(Rational::Builder(1)),Rational::Builder(2))); + assert_parsed_expression_is("1!-2!", Subtraction::Builder(Factorial::Builder(Rational::Builder(1)),Factorial::Builder(Rational::Builder(2)))); + assert_parsed_expression_is("1/2!", Division::Builder(Rational::Builder(1),Factorial::Builder(Rational::Builder(2)))); + assert_parsed_expression_is("1!/2", Division::Builder(Factorial::Builder(Rational::Builder(1)),Rational::Builder(2))); + assert_parsed_expression_is("1!/2!", Division::Builder(Factorial::Builder(Rational::Builder(1)),Factorial::Builder(Rational::Builder(2)))); + assert_parsed_expression_is("1^2!", Power::Builder(Rational::Builder(1),Factorial::Builder(Rational::Builder(2)))); + assert_parsed_expression_is("1!^2", Power::Builder(Factorial::Builder(Rational::Builder(1)),Rational::Builder(2))); + assert_parsed_expression_is("1!^2!", Power::Builder(Factorial::Builder(Rational::Builder(1)),Factorial::Builder(Rational::Builder(2)))); + assert_parsed_expression_is("(1)!", Factorial::Builder(Parenthesis::Builder(Rational::Builder(1)))); assert_raises_parsing_error("1+"); assert_raises_parsing_error(")"); assert_raises_parsing_error(")("); @@ -215,13 +215,13 @@ Matrix BuildMatrix(int rows, int columns, Expression entries[]) { } QUIZ_CASE(poincare_parser_matrices) { - Expression m1[] = {Rational(1)}; + Expression m1[] = {Rational::Builder(1)}; assert_parsed_expression_is("[[1]]", BuildMatrix(1,1,m1)); - Expression m2[] = {Rational(1),Rational(2),Rational(3)}; + Expression m2[] = {Rational::Builder(1),Rational::Builder(2),Rational::Builder(3)}; assert_parsed_expression_is("[[1,2,3]]", BuildMatrix(1,3,m2)); - Expression m3[] = {Rational(1),Rational(2),Rational(3),Rational(4),Rational(5),Rational(6)}; + Expression m3[] = {Rational::Builder(1),Rational::Builder(2),Rational::Builder(3),Rational::Builder(4),Rational::Builder(5),Rational::Builder(6)}; assert_parsed_expression_is("[[1,2,3][4,5,6]]", BuildMatrix(2,3,m3)); - Expression m4[] = {Rational(1), BuildMatrix(1,1,m1)}; + Expression m4[] = {Rational::Builder(1), BuildMatrix(1,1,m1)}; assert_parsed_expression_is("[[1,[[1]]]]", BuildMatrix(1,2,m4)); assert_raises_parsing_error("["); assert_raises_parsing_error("]"); @@ -241,105 +241,105 @@ QUIZ_CASE(poincare_parser_matrices) { QUIZ_CASE(poincare_parser_symbols_and_functions) { // User-defined symbols - assert_parsed_expression_is("a", Symbol("a", 1)); - assert_parsed_expression_is("x", Symbol("x", 1)); - assert_parsed_expression_is("toot", Symbol("toot", 4)); - assert_parsed_expression_is("toto_", Symbol("toto_", 5)); - assert_parsed_expression_is("t_toto", Symbol("t_toto", 6)); - assert_parsed_expression_is("tot12", Symbol("tot12", 5)); - assert_parsed_expression_is("TOto", Symbol("TOto", 4)); - assert_parsed_expression_is("TO12_Or", Symbol("TO12_Or", 7)); + assert_parsed_expression_is("a", Symbol::Builder("a", 1)); + assert_parsed_expression_is("x", Symbol::Builder("x", 1)); + assert_parsed_expression_is("toot", Symbol::Builder("toot", 4)); + assert_parsed_expression_is("toto_", Symbol::Builder("toto_", 5)); + assert_parsed_expression_is("t_toto", Symbol::Builder("t_toto", 6)); + assert_parsed_expression_is("tot12", Symbol::Builder("tot12", 5)); + assert_parsed_expression_is("TOto", Symbol::Builder("TOto", 4)); + assert_parsed_expression_is("TO12_Or", Symbol::Builder("TO12_Or", 7)); assert_raises_parsing_error("_a"); assert_raises_parsing_error("abcdefgh"); // User-defined functions - assert_parsed_expression_is("f(x)", Function("f", 1, Symbol("x",1))); - assert_parsed_expression_is("f(1)", Function("f", 1, Rational(1))); - assert_parsed_expression_is("ab12AB_(x)", Function("ab12AB_", 7, Symbol("x",1))); - assert_parsed_expression_is("ab12AB_(1)", Function("ab12AB_", 7, Rational(1))); - assert_parsed_expression_is("f(g(x))", Function("f", 1, Function("g", 1, Symbol("x",1)))); - assert_parsed_expression_is("f(g(1))", Function("f", 1, Function("g", 1, Rational(1)))); - assert_parsed_expression_is("f((1))", Function("f", 1, Parenthesis::Builder(Rational(1)))); + assert_parsed_expression_is("f(x)", Function::Builder("f", 1, Symbol::Builder("x",1))); + assert_parsed_expression_is("f(1)", Function::Builder("f", 1, Rational::Builder(1))); + assert_parsed_expression_is("ab12AB_(x)", Function::Builder("ab12AB_", 7, Symbol::Builder("x",1))); + assert_parsed_expression_is("ab12AB_(1)", Function::Builder("ab12AB_", 7, Rational::Builder(1))); + assert_parsed_expression_is("f(g(x))", Function::Builder("f", 1, Function::Builder("g", 1, Symbol::Builder("x",1)))); + assert_parsed_expression_is("f(g(1))", Function::Builder("f", 1, Function::Builder("g", 1, Rational::Builder(1)))); + assert_parsed_expression_is("f((1))", Function::Builder("f", 1, Parenthesis::Builder(Rational::Builder(1)))); assert_raises_parsing_error("f(1,2)"); assert_raises_parsing_error("f(f)"); assert_raises_parsing_error("abcdefgh(1)"); // Reserved symbols - assert_parsed_expression_is("ans", Symbol("ans", 3)); - assert_parsed_expression_is("I", Constant(Ion::Charset::IComplex)); - assert_parsed_expression_is("P", Constant(Ion::Charset::SmallPi)); - assert_parsed_expression_is("X", Constant(Ion::Charset::Exponential)); - assert_parsed_expression_is(Infinity::Name(), Infinity(false)); - assert_parsed_expression_is(Undefined::Name(), Undefined()); + assert_parsed_expression_is("ans", Symbol::Builder("ans", 3)); + assert_parsed_expression_is("I", Constant::Builder(Ion::Charset::IComplex)); + assert_parsed_expression_is("P", Constant::Builder(Ion::Charset::SmallPi)); + assert_parsed_expression_is("X", Constant::Builder(Ion::Charset::Exponential)); + assert_parsed_expression_is(Infinity::Name(), Infinity::Builder(false)); + assert_parsed_expression_is(Undefined::Name(), Undefined::Builder()); assert_raises_parsing_error("u"); assert_raises_parsing_error("v"); // Reserved functions - assert_parsed_expression_is("acos(1)", ArcCosine::Builder(Rational(1))); - assert_parsed_expression_is("acosh(1)", HyperbolicArcCosine::Builder(Rational(1))); - assert_parsed_expression_is("abs(1)", AbsoluteValue::Builder(Rational(1))); - assert_parsed_expression_is("arg(1)", ComplexArgument::Builder(Rational(1))); - assert_parsed_expression_is("asin(1)", ArcSine::Builder(Rational(1))); - assert_parsed_expression_is("asinh(1)", HyperbolicArcSine::Builder(Rational(1))); - assert_parsed_expression_is("atan(1)", ArcTangent::Builder(Rational(1))); - assert_parsed_expression_is("atanh(1)", HyperbolicArcTangent::Builder(Rational(1))); - assert_parsed_expression_is("binomial(2,1)", BinomialCoefficient::Builder(Rational(2),Rational(1))); - assert_parsed_expression_is("ceil(1)", Ceiling::Builder(Rational(1))); - assert_parsed_expression_is("confidence(1,2)", ConfidenceInterval::Builder(Rational(1),Rational(2))); + assert_parsed_expression_is("acos(1)", ArcCosine::Builder(Rational::Builder(1))); + assert_parsed_expression_is("acosh(1)", HyperbolicArcCosine::Builder(Rational::Builder(1))); + assert_parsed_expression_is("abs(1)", AbsoluteValue::Builder(Rational::Builder(1))); + assert_parsed_expression_is("arg(1)", ComplexArgument::Builder(Rational::Builder(1))); + assert_parsed_expression_is("asin(1)", ArcSine::Builder(Rational::Builder(1))); + assert_parsed_expression_is("asinh(1)", HyperbolicArcSine::Builder(Rational::Builder(1))); + assert_parsed_expression_is("atan(1)", ArcTangent::Builder(Rational::Builder(1))); + assert_parsed_expression_is("atanh(1)", HyperbolicArcTangent::Builder(Rational::Builder(1))); + assert_parsed_expression_is("binomial(2,1)", BinomialCoefficient::Builder(Rational::Builder(2),Rational::Builder(1))); + assert_parsed_expression_is("ceil(1)", Ceiling::Builder(Rational::Builder(1))); + assert_parsed_expression_is("confidence(1,2)", ConfidenceInterval::Builder(Rational::Builder(1),Rational::Builder(2))); assert_raises_parsing_error("diff(1,2,3)"); - assert_parsed_expression_is("diff(1,x,3)", Derivative::Builder(Rational(1),Symbol("x",1),Rational(3))); - assert_parsed_expression_is("dim(1)", MatrixDimension::Builder(Rational(1))); - assert_parsed_expression_is("conj(1)", Conjugate::Builder(Rational(1))); - assert_parsed_expression_is("det(1)", Determinant::Builder(Rational(1))); - assert_parsed_expression_is("cos(1)", Cosine::Builder(Rational(1))); - assert_parsed_expression_is("cosh(1)", HyperbolicCosine::Builder(Rational(1))); - assert_parsed_expression_is("factor(1)", Factor::Builder(Rational(1))); - assert_parsed_expression_is("floor(1)", Floor::Builder(Rational(1))); - assert_parsed_expression_is("frac(1)", FracPart::Builder(Rational(1))); - assert_parsed_expression_is("gcd(1,2)", GreatCommonDivisor::Builder(Rational(1),Rational(2))); - assert_parsed_expression_is("im(1)", ImaginaryPart::Builder(Rational(1))); - assert_parsed_expression_is("int(1,x,2,3)", Integral::Builder(Rational(1),Symbol("x",1),Rational(2),Rational(3))); + assert_parsed_expression_is("diff(1,x,3)", Derivative::Builder(Rational::Builder(1),Symbol::Builder("x",1),Rational::Builder(3))); + assert_parsed_expression_is("dim(1)", MatrixDimension::Builder(Rational::Builder(1))); + assert_parsed_expression_is("conj(1)", Conjugate::Builder(Rational::Builder(1))); + assert_parsed_expression_is("det(1)", Determinant::Builder(Rational::Builder(1))); + assert_parsed_expression_is("cos(1)", Cosine::Builder(Rational::Builder(1))); + assert_parsed_expression_is("cosh(1)", HyperbolicCosine::Builder(Rational::Builder(1))); + assert_parsed_expression_is("factor(1)", Factor::Builder(Rational::Builder(1))); + assert_parsed_expression_is("floor(1)", Floor::Builder(Rational::Builder(1))); + assert_parsed_expression_is("frac(1)", FracPart::Builder(Rational::Builder(1))); + assert_parsed_expression_is("gcd(1,2)", GreatCommonDivisor::Builder(Rational::Builder(1),Rational::Builder(2))); + assert_parsed_expression_is("im(1)", ImaginaryPart::Builder(Rational::Builder(1))); + assert_parsed_expression_is("int(1,x,2,3)", Integral::Builder(Rational::Builder(1),Symbol::Builder("x",1),Rational::Builder(2),Rational::Builder(3))); assert_raises_parsing_error("int(1,2,3,4)"); - assert_parsed_expression_is("inverse(1)", MatrixInverse::Builder(Rational(1))); - assert_parsed_expression_is("lcm(1,2)", LeastCommonMultiple::Builder(Rational(1),Rational(2))); - assert_parsed_expression_is("ln(1)", NaperianLogarithm::Builder(Rational(1))); - assert_parsed_expression_is("log(1)", CommonLogarithm::Builder(Rational(1))); - assert_parsed_expression_is("log(1,2)", Logarithm::Builder(Rational(1),Rational(2))); - assert_parsed_expression_is("log_{2}(1)", Logarithm::Builder(Rational(1),Rational(2))); - assert_parsed_expression_is("permute(2,1)", PermuteCoefficient::Builder(Rational(2),Rational(1))); - assert_parsed_expression_is("prediction95(1,2)", PredictionInterval::Builder(Rational(1),Rational(2))); - assert_parsed_expression_is("prediction(1,2)", SimplePredictionInterval::Builder(Rational(1),Rational(2))); - assert_parsed_expression_is("product(1,n,2,3)", Product::Builder(Rational(1),Symbol("n",1),Rational(2),Rational(3))); + assert_parsed_expression_is("inverse(1)", MatrixInverse::Builder(Rational::Builder(1))); + assert_parsed_expression_is("lcm(1,2)", LeastCommonMultiple::Builder(Rational::Builder(1),Rational::Builder(2))); + assert_parsed_expression_is("ln(1)", NaperianLogarithm::Builder(Rational::Builder(1))); + assert_parsed_expression_is("log(1)", CommonLogarithm::Builder(Rational::Builder(1))); + assert_parsed_expression_is("log(1,2)", Logarithm::Builder(Rational::Builder(1),Rational::Builder(2))); + assert_parsed_expression_is("log_{2}(1)", Logarithm::Builder(Rational::Builder(1),Rational::Builder(2))); + assert_parsed_expression_is("permute(2,1)", PermuteCoefficient::Builder(Rational::Builder(2),Rational::Builder(1))); + assert_parsed_expression_is("prediction95(1,2)", PredictionInterval::Builder(Rational::Builder(1),Rational::Builder(2))); + assert_parsed_expression_is("prediction(1,2)", SimplePredictionInterval::Builder(Rational::Builder(1),Rational::Builder(2))); + assert_parsed_expression_is("product(1,n,2,3)", Product::Builder(Rational::Builder(1),Symbol::Builder("n",1),Rational::Builder(2),Rational::Builder(3))); assert_raises_parsing_error("product(1,2,3,4)"); - assert_parsed_expression_is("quo(1,2)", DivisionQuotient::Builder(Rational(1),Rational(2))); + assert_parsed_expression_is("quo(1,2)", DivisionQuotient::Builder(Rational::Builder(1),Rational::Builder(2))); assert_parsed_expression_is("random()", Random::Builder()); - assert_parsed_expression_is("randint(1,2)", Randint::Builder(Rational(1),Rational(2))); - assert_parsed_expression_is("re(1)", RealPart::Builder(Rational(1))); - assert_parsed_expression_is("rem(1,2)", DivisionRemainder::Builder(Rational(1),Rational(2))); - assert_parsed_expression_is("root(1,2)", NthRoot::Builder(Rational(1),Rational(2))); - assert_parsed_expression_is("round(1,2)", Round::Builder(Rational(1),Rational(2))); - assert_parsed_expression_is("sin(1)", Sine::Builder(Rational(1))); - assert_parsed_expression_is("sinh(1)", HyperbolicSine::Builder(Rational(1))); - assert_parsed_expression_is("sum(1,n,2,3)", Sum::Builder(Rational(1),Symbol("n",1),Rational(2),Rational(3))); + assert_parsed_expression_is("randint(1,2)", Randint::Builder(Rational::Builder(1),Rational::Builder(2))); + assert_parsed_expression_is("re(1)", RealPart::Builder(Rational::Builder(1))); + assert_parsed_expression_is("rem(1,2)", DivisionRemainder::Builder(Rational::Builder(1),Rational::Builder(2))); + assert_parsed_expression_is("root(1,2)", NthRoot::Builder(Rational::Builder(1),Rational::Builder(2))); + assert_parsed_expression_is("round(1,2)", Round::Builder(Rational::Builder(1),Rational::Builder(2))); + assert_parsed_expression_is("sin(1)", Sine::Builder(Rational::Builder(1))); + assert_parsed_expression_is("sinh(1)", HyperbolicSine::Builder(Rational::Builder(1))); + assert_parsed_expression_is("sum(1,n,2,3)", Sum::Builder(Rational::Builder(1),Symbol::Builder("n",1),Rational::Builder(2),Rational::Builder(3))); assert_raises_parsing_error("sum(1,2,3,4)"); - assert_parsed_expression_is("tan(1)", Tangent::Builder(Rational(1))); - assert_parsed_expression_is("tanh(1)", HyperbolicTangent::Builder(Rational(1))); - assert_parsed_expression_is("trace(1)", MatrixTrace::Builder(Rational(1))); - assert_parsed_expression_is("transpose(1)", MatrixTranspose::Builder(Rational(1))); - assert_parsed_expression_is("\x91(1)", SquareRoot::Builder(Rational(1))); + assert_parsed_expression_is("tan(1)", Tangent::Builder(Rational::Builder(1))); + assert_parsed_expression_is("tanh(1)", HyperbolicTangent::Builder(Rational::Builder(1))); + assert_parsed_expression_is("trace(1)", MatrixTrace::Builder(Rational::Builder(1))); + assert_parsed_expression_is("transpose(1)", MatrixTranspose::Builder(Rational::Builder(1))); + assert_parsed_expression_is("\x91(1)", SquareRoot::Builder(Rational::Builder(1))); assert_raises_parsing_error("cos(1,2)"); assert_raises_parsing_error("log(1,2,3)"); } QUIZ_CASE(poincare_parser_parse_store) { - assert_parsed_expression_is("1>a", Store::Builder(Rational(1),Symbol("a",1))); - assert_parsed_expression_is("1>e", Store::Builder(Rational(1),Symbol("e",1))); - assert_parsed_expression_is("1>f(x)", Store::Builder(Rational(1),Function("f",1,Symbol("x",1)))); - assert_parsed_expression_is("x>f(x)", Store::Builder(Symbol("x",1),Function("f",1,Symbol("x",1)))); - assert_parsed_expression_is("n>f(x)", Store::Builder(Symbol("n",1),Function("f",1,Symbol("x",1)))); - Expression m0[] = {Symbol('x')}; - assert_parsed_expression_is("[[x]]>f(x)", Store::Builder(BuildMatrix(1,1,m0), Function("f", 1, Symbol('x')))); + assert_parsed_expression_is("1>a", Store::Builder(Rational::Builder(1),Symbol::Builder("a",1))); + assert_parsed_expression_is("1>e", Store::Builder(Rational::Builder(1),Symbol::Builder("e",1))); + assert_parsed_expression_is("1>f(x)", Store::Builder(Rational::Builder(1),Function::Builder("f",1,Symbol::Builder("x",1)))); + assert_parsed_expression_is("x>f(x)", Store::Builder(Symbol::Builder("x",1),Function::Builder("f",1,Symbol::Builder("x",1)))); + assert_parsed_expression_is("n>f(x)", Store::Builder(Symbol::Builder("n",1),Function::Builder("f",1,Symbol::Builder("x",1)))); + Expression m0[] = {Symbol::Builder('x')}; + assert_parsed_expression_is("[[x]]>f(x)", Store::Builder(BuildMatrix(1,1,m0), Function::Builder("f", 1, Symbol::Builder('x')))); assert_raises_parsing_error("a>b>c"); assert_raises_parsing_error("1>2"); assert_raises_parsing_error("1>"); @@ -369,26 +369,26 @@ QUIZ_CASE(poincare_parser_parse_store) { QUIZ_CASE(poincare_parser_implicit_multiplication) { assert_raises_parsing_error(".1.2"); assert_raises_parsing_error("1 2"); - assert_parsed_expression_is("1x", Multiplication::Builder(Rational(1),Symbol("x", 1))); - assert_parsed_expression_is("1ans", Multiplication::Builder(Rational(1),Symbol("ans", 3))); - assert_parsed_expression_is("x1", Symbol("x1", 2)); - assert_parsed_expression_is("1x+2", Addition::Builder(Multiplication::Builder(Rational(1),Symbol("x", 1)),Rational(2))); - assert_parsed_expression_is("1P", Multiplication::Builder(Rational(1),Constant(Ion::Charset::SmallPi))); - assert_parsed_expression_is("1x-2", Subtraction::Builder(Multiplication::Builder(Rational(1),Symbol("x", 1)),Rational(2))); - assert_parsed_expression_is("-1x", Opposite::Builder(Multiplication::Builder(Rational(1),Symbol("x", 1)))); - assert_parsed_expression_is("2*1x", Multiplication::Builder(Rational(2),Multiplication::Builder(Rational(1),Symbol("x", 1)))); - assert_parsed_expression_is("2^1x", Multiplication::Builder(Power::Builder(Rational(2),Rational(1)),Symbol("x", 1))); - assert_parsed_expression_is("1x^2", Multiplication::Builder(Rational(1),Power::Builder(Symbol("x", 1),Rational(2)))); - assert_parsed_expression_is("2/1x", Division::Builder(Rational(2),Multiplication::Builder(Rational(1),Symbol("x", 1)))); - assert_parsed_expression_is("1x/2", Division::Builder(Multiplication::Builder(Rational(1),Symbol("x", 1)),Rational(2))); - assert_parsed_expression_is("(1)2", Multiplication::Builder(Parenthesis::Builder(Rational(1)),Rational(2))); - assert_parsed_expression_is("1(2)", Multiplication::Builder(Rational(1),Parenthesis::Builder(Rational(2)))); - assert_parsed_expression_is("sin(1)2", Multiplication::Builder(Sine::Builder(Rational(1)),Rational(2))); - assert_parsed_expression_is("1cos(2)", Multiplication::Builder(Rational(1),Cosine::Builder(Rational(2)))); - assert_parsed_expression_is("1!2", Multiplication::Builder(Factorial::Builder(Rational(1)),Rational(2))); - assert_parsed_expression_is("2X^(3)", Multiplication::Builder(Rational(2),Power::Builder(Constant(Ion::Charset::Exponential),Parenthesis::Builder(Rational(3))))); - Expression m1[] = {Rational(1)}; Matrix M1 = BuildMatrix(1,1,m1); - Expression m2[] = {Rational(2)}; Matrix M2 = BuildMatrix(1,1,m2); + assert_parsed_expression_is("1x", Multiplication::Builder(Rational::Builder(1),Symbol::Builder("x", 1))); + assert_parsed_expression_is("1ans", Multiplication::Builder(Rational::Builder(1),Symbol::Builder("ans", 3))); + assert_parsed_expression_is("x1", Symbol::Builder("x1", 2)); + assert_parsed_expression_is("1x+2", Addition::Builder(Multiplication::Builder(Rational::Builder(1),Symbol::Builder("x", 1)),Rational::Builder(2))); + assert_parsed_expression_is("1P", Multiplication::Builder(Rational::Builder(1),Constant::Builder(Ion::Charset::SmallPi))); + assert_parsed_expression_is("1x-2", Subtraction::Builder(Multiplication::Builder(Rational::Builder(1),Symbol::Builder("x", 1)),Rational::Builder(2))); + assert_parsed_expression_is("-1x", Opposite::Builder(Multiplication::Builder(Rational::Builder(1),Symbol::Builder("x", 1)))); + assert_parsed_expression_is("2*1x", Multiplication::Builder(Rational::Builder(2),Multiplication::Builder(Rational::Builder(1),Symbol::Builder("x", 1)))); + assert_parsed_expression_is("2^1x", Multiplication::Builder(Power::Builder(Rational::Builder(2),Rational::Builder(1)),Symbol::Builder("x", 1))); + assert_parsed_expression_is("1x^2", Multiplication::Builder(Rational::Builder(1),Power::Builder(Symbol::Builder("x", 1),Rational::Builder(2)))); + assert_parsed_expression_is("2/1x", Division::Builder(Rational::Builder(2),Multiplication::Builder(Rational::Builder(1),Symbol::Builder("x", 1)))); + assert_parsed_expression_is("1x/2", Division::Builder(Multiplication::Builder(Rational::Builder(1),Symbol::Builder("x", 1)),Rational::Builder(2))); + assert_parsed_expression_is("(1)2", Multiplication::Builder(Parenthesis::Builder(Rational::Builder(1)),Rational::Builder(2))); + assert_parsed_expression_is("1(2)", Multiplication::Builder(Rational::Builder(1),Parenthesis::Builder(Rational::Builder(2)))); + assert_parsed_expression_is("sin(1)2", Multiplication::Builder(Sine::Builder(Rational::Builder(1)),Rational::Builder(2))); + assert_parsed_expression_is("1cos(2)", Multiplication::Builder(Rational::Builder(1),Cosine::Builder(Rational::Builder(2)))); + assert_parsed_expression_is("1!2", Multiplication::Builder(Factorial::Builder(Rational::Builder(1)),Rational::Builder(2))); + assert_parsed_expression_is("2X^(3)", Multiplication::Builder(Rational::Builder(2),Power::Builder(Constant::Builder(Ion::Charset::Exponential),Parenthesis::Builder(Rational::Builder(3))))); + Expression m1[] = {Rational::Builder(1)}; Matrix M1 = BuildMatrix(1,1,m1); + Expression m2[] = {Rational::Builder(2)}; Matrix M2 = BuildMatrix(1,1,m2); assert_parsed_expression_is("[[1]][[2]]", Multiplication::Builder(M1,M2)); } diff --git a/poincare/test/properties.cpp b/poincare/test/properties.cpp index 685aea2b1..e36b93fb2 100644 --- a/poincare/test/properties.cpp +++ b/poincare/test/properties.cpp @@ -76,19 +76,19 @@ void assert_expression_has_characteristic_range(Expression e, float range, Prefe } QUIZ_CASE(poincare_characteristic_range) { - assert_expression_has_characteristic_range(Cosine::Builder(Symbol(Poincare::Symbol::SpecialSymbols::UnknownX)), 360.0f); - assert_expression_has_characteristic_range(Cosine::Builder(Opposite::Builder(Symbol(Poincare::Symbol::SpecialSymbols::UnknownX))), 360.0f); - assert_expression_has_characteristic_range(Cosine::Builder(Symbol(Poincare::Symbol::SpecialSymbols::UnknownX)), 2.0f*M_PI, Preferences::AngleUnit::Radian); - assert_expression_has_characteristic_range(Cosine::Builder(Opposite::Builder(Symbol(Poincare::Symbol::SpecialSymbols::UnknownX))), 2.0f*M_PI, Preferences::AngleUnit::Radian); - assert_expression_has_characteristic_range(Sine::Builder(Addition::Builder(Multiplication::Builder(Rational(9),Symbol(Poincare::Symbol::SpecialSymbols::UnknownX)),Rational(10))), 40.0f); - assert_expression_has_characteristic_range(Addition::Builder(Sine::Builder(Addition::Builder(Multiplication::Builder(Rational(9),Symbol(Poincare::Symbol::SpecialSymbols::UnknownX)),Rational(10))),Cosine::Builder(Division::Builder(Symbol(Poincare::Symbol::SpecialSymbols::UnknownX),Rational(2)))), 720.0f); - assert_expression_has_characteristic_range(Addition::Builder(Sine::Builder(Addition::Builder(Multiplication::Builder(Rational(9),Symbol(Poincare::Symbol::SpecialSymbols::UnknownX)),Rational(10))),Cosine::Builder(Division::Builder(Symbol(Poincare::Symbol::SpecialSymbols::UnknownX),Rational(2)))), 4.0f*M_PI, Preferences::AngleUnit::Radian); - assert_expression_has_characteristic_range(Symbol(Poincare::Symbol::SpecialSymbols::UnknownX), NAN); - assert_expression_has_characteristic_range(Addition::Builder(Cosine::Builder(Rational(3)),Rational(2)), 0.0f); - assert_expression_has_characteristic_range(CommonLogarithm::Builder(Cosine::Builder(Multiplication::Builder(Rational(40),Symbol(Poincare::Symbol::SpecialSymbols::UnknownX)))), 9.0f); - assert_expression_has_characteristic_range(Cosine::Builder((Expression)Cosine::Builder(Symbol(Poincare::Symbol::SpecialSymbols::UnknownX))), 360.0f); + assert_expression_has_characteristic_range(Cosine::Builder(Symbol::Builder(Poincare::Symbol::SpecialSymbols::UnknownX)), 360.0f); + assert_expression_has_characteristic_range(Cosine::Builder(Opposite::Builder(Symbol::Builder(Poincare::Symbol::SpecialSymbols::UnknownX))), 360.0f); + assert_expression_has_characteristic_range(Cosine::Builder(Symbol::Builder(Poincare::Symbol::SpecialSymbols::UnknownX)), 2.0f*M_PI, Preferences::AngleUnit::Radian); + assert_expression_has_characteristic_range(Cosine::Builder(Opposite::Builder(Symbol::Builder(Poincare::Symbol::SpecialSymbols::UnknownX))), 2.0f*M_PI, Preferences::AngleUnit::Radian); + assert_expression_has_characteristic_range(Sine::Builder(Addition::Builder(Multiplication::Builder(Rational::Builder(9),Symbol::Builder(Poincare::Symbol::SpecialSymbols::UnknownX)),Rational::Builder(10))), 40.0f); + assert_expression_has_characteristic_range(Addition::Builder(Sine::Builder(Addition::Builder(Multiplication::Builder(Rational::Builder(9),Symbol::Builder(Poincare::Symbol::SpecialSymbols::UnknownX)),Rational::Builder(10))),Cosine::Builder(Division::Builder(Symbol::Builder(Poincare::Symbol::SpecialSymbols::UnknownX),Rational::Builder(2)))), 720.0f); + assert_expression_has_characteristic_range(Addition::Builder(Sine::Builder(Addition::Builder(Multiplication::Builder(Rational::Builder(9),Symbol::Builder(Poincare::Symbol::SpecialSymbols::UnknownX)),Rational::Builder(10))),Cosine::Builder(Division::Builder(Symbol::Builder(Poincare::Symbol::SpecialSymbols::UnknownX),Rational::Builder(2)))), 4.0f*M_PI, Preferences::AngleUnit::Radian); + assert_expression_has_characteristic_range(Symbol::Builder(Poincare::Symbol::SpecialSymbols::UnknownX), NAN); + assert_expression_has_characteristic_range(Addition::Builder(Cosine::Builder(Rational::Builder(3)),Rational::Builder(2)), 0.0f); + assert_expression_has_characteristic_range(CommonLogarithm::Builder(Cosine::Builder(Multiplication::Builder(Rational::Builder(40),Symbol::Builder(Poincare::Symbol::SpecialSymbols::UnknownX)))), 9.0f); + assert_expression_has_characteristic_range(Cosine::Builder((Expression)Cosine::Builder(Symbol::Builder(Poincare::Symbol::SpecialSymbols::UnknownX))), 360.0f); assert_simplify("cos(x)>f(x)"); - assert_expression_has_characteristic_range(Function("f",1,Symbol(Poincare::Symbol::SpecialSymbols::UnknownX)), 360.0f); + assert_expression_has_characteristic_range(Function::Builder("f",1,Symbol::Builder(Poincare::Symbol::SpecialSymbols::UnknownX)), 360.0f); } void assert_parsed_expression_has_variables(const char * expression, const char * variables[], int trueNumberOfVariables) { diff --git a/poincare/test/rational.cpp b/poincare/test/rational.cpp index 4b090db03..66d42daaf 100644 --- a/poincare/test/rational.cpp +++ b/poincare/test/rational.cpp @@ -9,13 +9,13 @@ using namespace Poincare; QUIZ_CASE(poincare_rational_constructor) { int initialPoolSize = pool_size(); - Rational a("123","324"); - Rational b("3456"); - Rational c(123,324); - Rational d(3456789); + Rational a = Rational::Builder("123","324"); + Rational b = Rational::Builder("3456"); + Rational c = Rational::Builder(123,324); + Rational d = Rational::Builder(3456789); Integer overflow = Integer::Overflow(false); - Rational e(overflow); - Rational f(overflow, overflow); + Rational e = Rational::Builder(overflow); + Rational f = Rational::Builder(overflow, overflow); assert_pool_size(initialPoolSize+6); } @@ -35,31 +35,31 @@ static inline void assert_greater(const Rational i, const Rational j) { } QUIZ_CASE(poincare_rational_compare) { - assert_equal(Rational(123,324), Rational(41,108)); - assert_not_equal(Rational(123,234), Rational(42, 108)); - assert_lower(Rational(123,234), Rational(456,567)); - assert_lower(Rational(-123, 234),Rational(456, 567)); - assert_greater(Rational(123, 234),Rational(-456, 567)); - assert_greater(Rational(123, 234),Rational("123456789123456789", "12345678912345678910")); + assert_equal(Rational::Builder(123,324), Rational::Builder(41,108)); + assert_not_equal(Rational::Builder(123,234), Rational::Builder(42, 108)); + assert_lower(Rational::Builder(123,234), Rational::Builder(456,567)); + assert_lower(Rational::Builder(-123, 234),Rational::Builder(456, 567)); + assert_greater(Rational::Builder(123, 234),Rational::Builder(-456, 567)); + assert_greater(Rational::Builder(123, 234),Rational::Builder("123456789123456789", "12345678912345678910")); } QUIZ_CASE(poincare_rational_properties) { - quiz_assert(Rational(-2).sign() == ExpressionNode::Sign::Negative); - quiz_assert(Rational(-2, 3).sign() == ExpressionNode::Sign::Negative); - quiz_assert(Rational(2, 3).sign() == ExpressionNode::Sign::Positive); - quiz_assert(Rational(0, 3).sign() == ExpressionNode::Sign::Positive); - quiz_assert(Rational(0).isZero()); - quiz_assert(!Rational(231).isZero()); - quiz_assert(Rational(1).isOne()); - quiz_assert(!Rational(-1).isOne()); - quiz_assert(!Rational(1).isMinusOne()); - quiz_assert(Rational(-1).isMinusOne()); - quiz_assert(Rational(1,2).isHalf()); - quiz_assert(!Rational(-1).isHalf()); - quiz_assert(Rational(-1,2).isMinusHalf()); - quiz_assert(!Rational(3,2).isMinusHalf()); - quiz_assert(Rational(10).isTen()); - quiz_assert(!Rational(-1).isTen()); + quiz_assert(Rational::Builder(-2).sign() == ExpressionNode::Sign::Negative); + quiz_assert(Rational::Builder(-2, 3).sign() == ExpressionNode::Sign::Negative); + quiz_assert(Rational::Builder(2, 3).sign() == ExpressionNode::Sign::Positive); + quiz_assert(Rational::Builder(0, 3).sign() == ExpressionNode::Sign::Positive); + quiz_assert(Rational::Builder(0).isZero()); + quiz_assert(!Rational::Builder(231).isZero()); + quiz_assert(Rational::Builder(1).isOne()); + quiz_assert(!Rational::Builder(-1).isOne()); + quiz_assert(!Rational::Builder(1).isMinusOne()); + quiz_assert(Rational::Builder(-1).isMinusOne()); + quiz_assert(Rational::Builder(1,2).isHalf()); + quiz_assert(!Rational::Builder(-1).isHalf()); + quiz_assert(Rational::Builder(-1,2).isMinusHalf()); + quiz_assert(!Rational::Builder(3,2).isMinusHalf()); + quiz_assert(Rational::Builder(10).isTen()); + quiz_assert(!Rational::Builder(-1).isTen()); } static inline void assert_add_to(const Rational i, const Rational j, const Rational k) { @@ -67,9 +67,9 @@ static inline void assert_add_to(const Rational i, const Rational j, const Ratio } QUIZ_CASE(poincare_rational_addition) { - assert_add_to(Rational(1,2), Rational(1), Rational(3,2)); - assert_add_to(Rational("18446744073709551616","4294967296"), Rational(8,9), Rational("38654705672","9")); - assert_add_to(Rational("18446744073709551616","4294967296"), Rational(-8,9), Rational("38654705656","9")); + assert_add_to(Rational::Builder(1,2), Rational::Builder(1), Rational::Builder(3,2)); + assert_add_to(Rational::Builder("18446744073709551616","4294967296"), Rational::Builder(8,9), Rational::Builder("38654705672","9")); + assert_add_to(Rational::Builder("18446744073709551616","4294967296"), Rational::Builder(-8,9), Rational::Builder("38654705656","9")); } static inline void assert_pow_to(const Rational i,const Integer j, const Rational k) { @@ -77,8 +77,8 @@ static inline void assert_pow_to(const Rational i,const Integer j, const Rationa } QUIZ_CASE(poincare_rational_power) { - assert_pow_to(Rational(4,5), Rational(3).signedIntegerNumerator(), Rational(64,125)); - assert_pow_to(Rational(4,5), Rational(-3).signedIntegerNumerator(), Rational(125,64)); + assert_pow_to(Rational::Builder(4,5), Rational::Builder(3).signedIntegerNumerator(), Rational::Builder(64,125)); + assert_pow_to(Rational::Builder(4,5), Rational::Builder(-3).signedIntegerNumerator(), Rational::Builder(125,64)); } // Simplify @@ -137,12 +137,12 @@ QUIZ_CASE(poincare_rational_approximate) { //Serialize QUIZ_CASE(poincare_rational_serialize) { - assert_parsed_expression_serialize_to(Rational(-2, 3), "-2/3"); - assert_parsed_expression_serialize_to(Rational("2345678909876"), "2345678909876"); - assert_parsed_expression_serialize_to(Rational("-2345678909876", "5"), "-2345678909876/5"); - assert_parsed_expression_serialize_to(Rational(MaxIntegerString()), MaxIntegerString()); + assert_parsed_expression_serialize_to(Rational::Builder(-2, 3), "-2/3"); + assert_parsed_expression_serialize_to(Rational::Builder("2345678909876"), "2345678909876"); + assert_parsed_expression_serialize_to(Rational::Builder("-2345678909876", "5"), "-2345678909876/5"); + assert_parsed_expression_serialize_to(Rational::Builder(MaxIntegerString()), MaxIntegerString()); Integer one(1); Integer overflow = Integer::Overflow(false); - assert_parsed_expression_serialize_to(Rational(one, overflow), "1/inf"); - assert_parsed_expression_serialize_to(Rational(overflow), Infinity::Name()); + assert_parsed_expression_serialize_to(Rational::Builder(one, overflow), "1/inf"); + assert_parsed_expression_serialize_to(Rational::Builder(overflow), Infinity::Name()); } diff --git a/poincare/test/tree/blob_node.h b/poincare/test/tree/blob_node.h index 598fbbdb7..e2a0c907d 100644 --- a/poincare/test/tree/blob_node.h +++ b/poincare/test/tree/blob_node.h @@ -8,9 +8,9 @@ namespace Poincare { class BlobNode : public TreeNode { public: + BlobNode(int data) : m_data(data) {} virtual size_t size() const override { return sizeof(BlobNode); } int data() { return m_data; } - void setData(int data) { m_data = data; } virtual int numberOfChildren() const override { return 0; } #if POINCARE_TREE_LOG virtual void logNodeName(std::ostream & stream) const override { @@ -23,9 +23,13 @@ private: class BlobByReference : public TreeHandle { public: - BlobByReference(int data = 0) : TreeHandle(TreePool::sharedPool()->createTreeNode()) { - node()->setData(data); + static BlobByReference Builder(int data = 0) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(BlobNode)); + BlobNode * node = new (bufferNode) BlobNode(data); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); } + BlobByReference() = delete; int data() { return node()->data(); } private: BlobNode * node() const { return static_cast(TreeHandle::node()); } diff --git a/poincare/test/tree/pair_node.h b/poincare/test/tree/pair_node.h index 2618aa0b0..c041e186b 100644 --- a/poincare/test/tree/pair_node.h +++ b/poincare/test/tree/pair_node.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -19,10 +20,14 @@ public: class PairByReference : public TreeHandle { public: - PairByReference(TreeHandle t1, TreeHandle t2) : TreeHandle(TreePool::sharedPool()->createTreeNode()) { - replaceChildAtIndexInPlace(0, t1); - replaceChildAtIndexInPlace(1, t2); + static PairByReference Builder(TreeHandle t1, TreeHandle t2) { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(PairNode)); + PairNode * node = new (bufferNode) PairNode(); + TreeHandle children[2] = {t1, t2}; + TreeHandle h = TreeHandle::BuildWithBasicChildren(node, children, 2); + return static_cast(h); } + PairByReference() = delete; }; } diff --git a/poincare/test/tree/tree_handle.cpp b/poincare/test/tree/tree_handle.cpp index 44c380ca0..ff66ba727 100644 --- a/poincare/test/tree/tree_handle.cpp +++ b/poincare/test/tree/tree_handle.cpp @@ -13,14 +13,14 @@ using namespace Poincare; QUIZ_CASE(tree_handle_are_discared_after_block) { int initialPoolSize = pool_size(); { - BlobByReference b(0); + BlobByReference b = BlobByReference::Builder(0); assert_pool_size(initialPoolSize+1); } assert_pool_size(initialPoolSize); } static void make_temp_blob() { - BlobByReference b(5); + BlobByReference b = BlobByReference::Builder(5); } QUIZ_CASE(tree_handle_are_discared_after_function_call) { int initialPoolSize = pool_size(); @@ -31,7 +31,7 @@ QUIZ_CASE(tree_handle_are_discared_after_function_call) { QUIZ_CASE(tree_handle_can_be_copied) { int initialPoolSize = pool_size(); { - BlobByReference b(123); + BlobByReference b = BlobByReference::Builder(123); assert_pool_size(initialPoolSize+1); TreeHandle t = b; assert_pool_size(initialPoolSize+1); @@ -42,19 +42,19 @@ QUIZ_CASE(tree_handle_can_be_copied) { QUIZ_CASE(tree_handle_can_be_moved) { int initialPoolSize = pool_size(); { - TreeHandle t = BlobByReference(123); + TreeHandle t = BlobByReference::Builder(123); assert_pool_size(initialPoolSize+1); } { - TreeHandle t = BlobByReference(123); - t = BlobByReference(456); + TreeHandle t = BlobByReference::Builder(123); + t = BlobByReference::Builder(456); assert_pool_size(initialPoolSize+1); } assert_pool_size(initialPoolSize); } static TreeHandle blob_with_data_3() { - return BlobByReference(3); + return BlobByReference::Builder(3); } QUIZ_CASE(tree_handle_can_be_returned) { @@ -68,9 +68,9 @@ QUIZ_CASE(tree_handle_memory_failure) { int memoryFailureHasBeenHandled = false; Poincare::ExceptionCheckpoint ecp; if (ExceptionRun(ecp)) { - TreeHandle tree = BlobByReference(1); + TreeHandle tree = BlobByReference::Builder(1); while (true) { - tree = PairByReference(tree, BlobByReference(1)); + tree = PairByReference::Builder(tree, BlobByReference::Builder(1)); } } else { Poincare::Tidy(); @@ -82,10 +82,10 @@ QUIZ_CASE(tree_handle_memory_failure) { QUIZ_CASE(tree_handle_does_not_copy) { int initialPoolSize = pool_size(); - BlobByReference b1(1); - BlobByReference b2(2); + BlobByReference b1 = BlobByReference::Builder(1); + BlobByReference b2 = BlobByReference::Builder(2); assert_pool_size(initialPoolSize+2); - PairByReference p(b1, b2); + PairByReference p = PairByReference::Builder(b1, b2); assert_pool_size(initialPoolSize+3); PairByReference p2 = p; assert_pool_size(initialPoolSize+3); diff --git a/poincare/test/user_variable.cpp b/poincare/test/user_variable.cpp index eb4290428..8e336d245 100644 --- a/poincare/test/user_variable.cpp +++ b/poincare/test/user_variable.cpp @@ -157,9 +157,9 @@ QUIZ_CASE(poincare_user_variable_functions_with_context) { assert_simplify("x^2>f(x)"); // Approximate f(?-2) with ? = 5 const char x[] = {Symbol::SpecialSymbols::UnknownX, 0}; - assert_parsed_expression_approximates_with_value_for_symbol(Function("f", 1, Subtraction::Builder(Symbol(Symbol::SpecialSymbols::UnknownX), Rational(2))), x, 5.0, 9.0); + assert_parsed_expression_approximates_with_value_for_symbol(Function::Builder("f", 1, Subtraction::Builder(Symbol::Builder(Symbol::SpecialSymbols::UnknownX), Rational::Builder(2))), x, 5.0, 9.0); // Approximate f(?-1)+f(?+1) with ? = 3 - assert_parsed_expression_approximates_with_value_for_symbol(Addition::Builder(Function("f", 1, Subtraction::Builder(Symbol(Symbol::SpecialSymbols::UnknownX), Rational(1))), Function("f", 1, Addition::Builder(Symbol(Symbol::SpecialSymbols::UnknownX), Rational(1)))), x, 3.0, 20.0); + assert_parsed_expression_approximates_with_value_for_symbol(Addition::Builder(Function::Builder("f", 1, Subtraction::Builder(Symbol::Builder(Symbol::SpecialSymbols::UnknownX), Rational::Builder(1))), Function::Builder("f", 1, Addition::Builder(Symbol::Builder(Symbol::SpecialSymbols::UnknownX), Rational::Builder(1)))), x, 3.0, 20.0); // Clean the storage for other tests Ion::Storage::sharedStorage()->recordNamed("f.func").destroy(); @@ -168,9 +168,9 @@ QUIZ_CASE(poincare_user_variable_functions_with_context) { assert_simplify("R(-1)*R(-1)>f(x)"); // Approximate f(?) with ? = 5 // Cartesian - assert_parsed_expression_approximates_with_value_for_symbol(Function("f", 1, Symbol(Symbol::SpecialSymbols::UnknownX)), x, 1.0, -1.0); + assert_parsed_expression_approximates_with_value_for_symbol(Function::Builder("f", 1, Symbol::Builder(Symbol::SpecialSymbols::UnknownX)), x, 1.0, -1.0); // Real - assert_parsed_expression_approximates_with_value_for_symbol(Function("f", 1, Symbol(Symbol::SpecialSymbols::UnknownX)), x, 1.0, (double)NAN, Real); + assert_parsed_expression_approximates_with_value_for_symbol(Function::Builder("f", 1, Symbol::Builder(Symbol::SpecialSymbols::UnknownX)), x, 1.0, (double)NAN, Real); // Clean the storage for other tests Ion::Storage::sharedStorage()->recordNamed("f.func").destroy(); @@ -180,15 +180,15 @@ QUIZ_CASE(poincare_user_variable_properties) { Shared::GlobalContext context; assert_parsed_expression_evaluates_to("[[1]]>a", "[[1]]"); - quiz_assert(Symbol('a').isApproximate(context)); - quiz_assert(Poincare::Expression::IsMatrix(Symbol('a'), context, true)); + quiz_assert(Symbol::Builder('a').isApproximate(context)); + quiz_assert(Poincare::Expression::IsMatrix(Symbol::Builder('a'), context, true)); /* [[x]]->f(x) expression contains a matrix, so its simplification is going * to be interrupted. We thus rather approximate it instead of simplifying it. * TODO: use parse_and_simplify when matrix are simplified. */ assert_parsed_expression_evaluates_to("[[x]]>f(x)", "[[undef]]"); - quiz_assert(Function("f", 1, Rational(2)).isApproximate(context)); - quiz_assert(Poincare::Expression::IsMatrix(Function("f", 1, Symbol('x')), context, true)); + quiz_assert(Function::Builder("f", 1, Rational::Builder(2)).isApproximate(context)); + quiz_assert(Poincare::Expression::IsMatrix(Function::Builder("f", 1, Symbol::Builder('x')), context, true)); // Clean the storage for other tests Ion::Storage::sharedStorage()->recordNamed("a.exp").destroy(); diff --git a/poincare/test/vertical_offset_layout.cpp b/poincare/test/vertical_offset_layout.cpp index 7379abfa7..4c4e71750 100644 --- a/poincare/test/vertical_offset_layout.cpp +++ b/poincare/test/vertical_offset_layout.cpp @@ -8,7 +8,7 @@ using namespace Poincare; QUIZ_CASE(poincare_vertical_offset_layout_serialize) { HorizontalLayout layout = HorizontalLayout::Builder( - CharLayout('2'), + CharLayout::Builder('2'), VerticalOffsetLayout::Builder( LayoutHelper::String("x+5", 3), VerticalOffsetLayoutNode::Type::Superscript From 359fc3a599dc7c008228833e33e6a7b5019fb699 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 19 Feb 2019 12:20:07 +0100 Subject: [PATCH 339/373] [poincare] Create templated methods instead of defining UntypedBuilder on every expression --- poincare/include/poincare/absolute_value.h | 4 ++-- poincare/include/poincare/arc_cosine.h | 4 ++-- poincare/include/poincare/arc_sine.h | 4 ++-- poincare/include/poincare/arc_tangent.h | 4 ++-- poincare/include/poincare/binomial_coefficient.h | 3 +-- poincare/include/poincare/ceiling.h | 4 ++-- poincare/include/poincare/complex_argument.h | 4 ++-- poincare/include/poincare/confidence_interval.h | 6 ++---- poincare/include/poincare/conjugate.h | 4 ++-- poincare/include/poincare/cosine.h | 4 ++-- poincare/include/poincare/derivative.h | 1 + poincare/include/poincare/determinant.h | 4 ++-- poincare/include/poincare/division_quotient.h | 3 +-- poincare/include/poincare/division_remainder.h | 3 +-- poincare/include/poincare/expression.h | 11 +++++++++++ poincare/include/poincare/factor.h | 4 ++-- poincare/include/poincare/floor.h | 4 ++-- poincare/include/poincare/frac_part.h | 4 ++-- poincare/include/poincare/great_common_divisor.h | 3 +-- poincare/include/poincare/hyperbolic_arc_cosine.h | 4 ++-- poincare/include/poincare/hyperbolic_arc_sine.h | 4 ++-- poincare/include/poincare/hyperbolic_arc_tangent.h | 4 ++-- poincare/include/poincare/hyperbolic_cosine.h | 4 ++-- poincare/include/poincare/hyperbolic_sine.h | 4 ++-- poincare/include/poincare/hyperbolic_tangent.h | 4 ++-- poincare/include/poincare/imaginary_part.h | 4 ++-- poincare/include/poincare/integral.h | 1 + poincare/include/poincare/least_common_multiple.h | 3 +-- poincare/include/poincare/logarithm.h | 7 +++---- poincare/include/poincare/matrix_dimension.h | 4 ++-- poincare/include/poincare/matrix_inverse.h | 4 ++-- poincare/include/poincare/matrix_trace.h | 4 ++-- poincare/include/poincare/matrix_transpose.h | 4 ++-- poincare/include/poincare/naperian_logarithm.h | 4 ++-- poincare/include/poincare/nth_root.h | 3 +-- poincare/include/poincare/permute_coefficient.h | 3 +-- poincare/include/poincare/prediction_interval.h | 3 +-- poincare/include/poincare/product.h | 1 + poincare/include/poincare/randint.h | 3 +-- poincare/include/poincare/random.h | 2 +- poincare/include/poincare/real_part.h | 4 ++-- poincare/include/poincare/round.h | 3 +-- poincare/include/poincare/sign_function.h | 4 ++-- poincare/include/poincare/sine.h | 4 ++-- poincare/include/poincare/square_root.h | 4 ++-- poincare/include/poincare/sum.h | 1 + poincare/include/poincare/tangent.h | 4 ++-- 47 files changed, 89 insertions(+), 87 deletions(-) diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index d0eec68d2..66d4b8d4c 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -50,8 +50,8 @@ friend class AbsoluteValueNode; public: AbsoluteValue(const AbsoluteValueNode * n) : Expression(n) {} static AbsoluteValue Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("abs", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("abs", 1, &UntypedBuilderOneChild); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: diff --git a/poincare/include/poincare/arc_cosine.h b/poincare/include/poincare/arc_cosine.h index e15d9a685..ee29beacb 100644 --- a/poincare/include/poincare/arc_cosine.h +++ b/poincare/include/poincare/arc_cosine.h @@ -42,8 +42,8 @@ class ArcCosine final : public Expression { public: ArcCosine(const ArcCosineNode * n) : Expression(n) {} static ArcCosine Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("acos", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("acos", 1, &UntypedBuilderOneChild); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); diff --git a/poincare/include/poincare/arc_sine.h b/poincare/include/poincare/arc_sine.h index 230e39475..7ae261b42 100644 --- a/poincare/include/poincare/arc_sine.h +++ b/poincare/include/poincare/arc_sine.h @@ -41,8 +41,8 @@ class ArcSine final : public Expression { public: ArcSine(const ArcSineNode * n) : Expression(n) {} static ArcSine Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("asin", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("asin", 1, &UntypedBuilderOneChild); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); }; diff --git a/poincare/include/poincare/arc_tangent.h b/poincare/include/poincare/arc_tangent.h index 5262fc692..a0d6218f4 100644 --- a/poincare/include/poincare/arc_tangent.h +++ b/poincare/include/poincare/arc_tangent.h @@ -45,8 +45,8 @@ class ArcTangent final : public Expression { public: ArcTangent(const ArcTangentNode * n) : Expression(n) {} static ArcTangent Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("atan", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("atan", 1, &UntypedBuilderOneChild); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); }; diff --git a/poincare/include/poincare/binomial_coefficient.h b/poincare/include/poincare/binomial_coefficient.h index f6102a879..3c3315fff 100644 --- a/poincare/include/poincare/binomial_coefficient.h +++ b/poincare/include/poincare/binomial_coefficient.h @@ -40,8 +40,7 @@ class BinomialCoefficient final : public Expression { public: BinomialCoefficient(const BinomialCoefficientNode * n) : Expression(n) {} static BinomialCoefficient Builder(Expression child0, Expression child1); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("binomial", 2, &UntypedBuilder); + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("binomial", 2, &UntypedBuilderTwoChildren); // Expression Expression shallowReduce(); diff --git a/poincare/include/poincare/ceiling.h b/poincare/include/poincare/ceiling.h index 0a202947c..f8b75112c 100644 --- a/poincare/include/poincare/ceiling.h +++ b/poincare/include/poincare/ceiling.h @@ -43,8 +43,8 @@ class Ceiling final : public Expression { public: Ceiling(const CeilingNode * n) : Expression(n) {} static Ceiling Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("ceil", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("ceil", 1, &UntypedBuilderOneChild); Expression shallowReduce(); }; diff --git a/poincare/include/poincare/complex_argument.h b/poincare/include/poincare/complex_argument.h index 9ec2bec09..bdbcb3c72 100644 --- a/poincare/include/poincare/complex_argument.h +++ b/poincare/include/poincare/complex_argument.h @@ -42,8 +42,8 @@ class ComplexArgument final : public Expression { public: ComplexArgument(const ComplexArgumentNode * n) : Expression(n) {} static ComplexArgument Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("arg", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("arg", 1, &UntypedBuilderOneChild); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); }; diff --git a/poincare/include/poincare/confidence_interval.h b/poincare/include/poincare/confidence_interval.h index 88c82fc79..a030d0998 100644 --- a/poincare/include/poincare/confidence_interval.h +++ b/poincare/include/poincare/confidence_interval.h @@ -46,8 +46,7 @@ class ConfidenceInterval : public Expression { public: ConfidenceInterval(const ConfidenceIntervalNode * n) : Expression(n) {} static ConfidenceInterval Builder(Expression child0, Expression child1); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("confidence", 2, &UntypedBuilder); + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("confidence", 2, &UntypedBuilderTwoChildren); // Expression Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); @@ -59,8 +58,7 @@ class SimplePredictionInterval final : public ConfidenceInterval { public: SimplePredictionInterval(const SimplePredictionIntervalNode * n) : ConfidenceInterval(n) {} static SimplePredictionInterval Builder(Expression child0, Expression child1); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("prediction", 2, &UntypedBuilder); + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("prediction", 2, &UntypedBuilderTwoChildren); }; } diff --git a/poincare/include/poincare/conjugate.h b/poincare/include/poincare/conjugate.h index f6a0a1cb4..af45d709b 100644 --- a/poincare/include/poincare/conjugate.h +++ b/poincare/include/poincare/conjugate.h @@ -42,8 +42,8 @@ class Conjugate final : public Expression { public: Conjugate(const ConjugateNode * n) : Expression(n) {} static Conjugate Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("conj", 1, &UntypedBuilder);; + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("conj", 1, &UntypedBuilderOneChild);; Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); }; diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index 3e0524a65..532abf06f 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -47,8 +47,8 @@ class Cosine final : public Expression { public: Cosine(const CosineNode * n) : Expression(n) {} static Cosine Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("cos", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("cos", 1, &UntypedBuilderOneChild); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); }; diff --git a/poincare/include/poincare/derivative.h b/poincare/include/poincare/derivative.h index 70dc0973a..e2bd29ad1 100644 --- a/poincare/include/poincare/derivative.h +++ b/poincare/include/poincare/derivative.h @@ -53,6 +53,7 @@ public: Derivative(const DerivativeNode * n) : Expression(n) {} static Derivative Builder(Expression child0, Symbol child1, Expression child2); static Expression UntypedBuilder(Expression children) { + assert(children.type() == ExpressionNode::Type::Matrix); if (children.childAtIndex(1).type() != ExpressionNode::Type::Symbol) { // Second parameter must be a Symbol. return Expression(); diff --git a/poincare/include/poincare/determinant.h b/poincare/include/poincare/determinant.h index ff350e1fd..d4a392d76 100644 --- a/poincare/include/poincare/determinant.h +++ b/poincare/include/poincare/determinant.h @@ -36,8 +36,8 @@ class Determinant final : public Expression { public: Determinant(const DeterminantNode * n) : Expression(n) {} static Determinant Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("det", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("det", 1, &UntypedBuilderOneChild); Expression shallowReduce(Context & context); }; diff --git a/poincare/include/poincare/division_quotient.h b/poincare/include/poincare/division_quotient.h index d6f358a73..e74f8c8a3 100644 --- a/poincare/include/poincare/division_quotient.h +++ b/poincare/include/poincare/division_quotient.h @@ -39,8 +39,7 @@ class DivisionQuotient final : public Expression { public: DivisionQuotient(const DivisionQuotientNode * n) : Expression(n) {} static DivisionQuotient Builder(Expression child0, Expression child1); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("quo", 2, &UntypedBuilder); + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("quo", 2, &UntypedBuilderTwoChildren); // Expression Expression shallowReduce(); diff --git a/poincare/include/poincare/division_remainder.h b/poincare/include/poincare/division_remainder.h index b7a3e1273..9a4033005 100644 --- a/poincare/include/poincare/division_remainder.h +++ b/poincare/include/poincare/division_remainder.h @@ -40,8 +40,7 @@ class DivisionRemainder final : public Expression { public: DivisionRemainder(const DivisionRemainderNode * n) : Expression(n) {} static DivisionRemainder Builder(Expression child0, Expression child1); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("rem", 2, &UntypedBuilder); + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("rem", 2, &UntypedBuilderTwoChildren); // Expression Expression shallowReduce(); diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 72c860f7a..f87d66aa1 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -248,6 +248,17 @@ public: protected: static bool SimplificationHasBeenInterrupted(); Expression(const ExpressionNode * n) : TreeHandle(n) {} + template + static Expression UntypedBuilderOneChild(Expression children) { + assert(children.type() == ExpressionNode::Type::Matrix); + return U::Builder(children.childAtIndex(0)); + } + template + static Expression UntypedBuilderTwoChildren(Expression children) { + assert(children.type() == ExpressionNode::Type::Matrix); + return U::Builder(children.childAtIndex(0), children.childAtIndex(1)); + } + template T convert() const { /* This function allows to convert Expression to derived Expressions. diff --git a/poincare/include/poincare/factor.h b/poincare/include/poincare/factor.h index 09ebcbf6a..84d300a5d 100644 --- a/poincare/include/poincare/factor.h +++ b/poincare/include/poincare/factor.h @@ -38,8 +38,8 @@ class Factor final : public Expression { public: Factor(const FactorNode * n) : Expression(n) {} static Factor Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("factor", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("factor", 1, &UntypedBuilderOneChild); Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); Multiplication createMultiplicationOfIntegerPrimeDecomposition(Integer i, Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; diff --git a/poincare/include/poincare/floor.h b/poincare/include/poincare/floor.h index 507ecb541..c1c7736ee 100644 --- a/poincare/include/poincare/floor.h +++ b/poincare/include/poincare/floor.h @@ -45,8 +45,8 @@ class Floor final : public Expression { public: Floor(const FloorNode * n) : Expression(n) {} static Floor Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("floor", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("floor", 1, &UntypedBuilderOneChild); Expression shallowReduce(); }; diff --git a/poincare/include/poincare/frac_part.h b/poincare/include/poincare/frac_part.h index f6551e063..3858deeec 100644 --- a/poincare/include/poincare/frac_part.h +++ b/poincare/include/poincare/frac_part.h @@ -45,8 +45,8 @@ class FracPart final : public Expression { public: FracPart(const FracPartNode * n) : Expression(n) {} static FracPart Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("frac", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("frac", 1, &UntypedBuilderOneChild); Expression shallowReduce(); }; diff --git a/poincare/include/poincare/great_common_divisor.h b/poincare/include/poincare/great_common_divisor.h index 019867025..318b78d93 100644 --- a/poincare/include/poincare/great_common_divisor.h +++ b/poincare/include/poincare/great_common_divisor.h @@ -38,8 +38,7 @@ class GreatCommonDivisor final : public Expression { public: GreatCommonDivisor(const GreatCommonDivisorNode * n) : Expression(n) {} static GreatCommonDivisor Builder(Expression child0, Expression child1); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("gcd", 2, &UntypedBuilder); + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("gcd", 2, &UntypedBuilderTwoChildren); // Expression Expression shallowReduce(); diff --git a/poincare/include/poincare/hyperbolic_arc_cosine.h b/poincare/include/poincare/hyperbolic_arc_cosine.h index 8f8a8272f..3ebeccbd8 100644 --- a/poincare/include/poincare/hyperbolic_arc_cosine.h +++ b/poincare/include/poincare/hyperbolic_arc_cosine.h @@ -37,8 +37,8 @@ class HyperbolicArcCosine final : public HyperbolicTrigonometricFunction { public: HyperbolicArcCosine(const HyperbolicArcCosineNode * n) : HyperbolicTrigonometricFunction(n) {} static HyperbolicArcCosine Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("acosh", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("acosh", 1, &UntypedBuilderOneChild); }; } diff --git a/poincare/include/poincare/hyperbolic_arc_sine.h b/poincare/include/poincare/hyperbolic_arc_sine.h index 0569275c2..464235abe 100644 --- a/poincare/include/poincare/hyperbolic_arc_sine.h +++ b/poincare/include/poincare/hyperbolic_arc_sine.h @@ -37,8 +37,8 @@ class HyperbolicArcSine final : public HyperbolicTrigonometricFunction { public: HyperbolicArcSine(const HyperbolicArcSineNode * n) : HyperbolicTrigonometricFunction(n) {} static HyperbolicArcSine Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("asinh", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("asinh", 1, &UntypedBuilderOneChild); }; } diff --git a/poincare/include/poincare/hyperbolic_arc_tangent.h b/poincare/include/poincare/hyperbolic_arc_tangent.h index 565fcb42f..16b08b342 100644 --- a/poincare/include/poincare/hyperbolic_arc_tangent.h +++ b/poincare/include/poincare/hyperbolic_arc_tangent.h @@ -37,8 +37,8 @@ class HyperbolicArcTangent final : public HyperbolicTrigonometricFunction { public: HyperbolicArcTangent(const HyperbolicArcTangentNode * n) : HyperbolicTrigonometricFunction(n) {} static HyperbolicArcTangent Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("atanh", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("atanh", 1, &UntypedBuilderOneChild); }; } diff --git a/poincare/include/poincare/hyperbolic_cosine.h b/poincare/include/poincare/hyperbolic_cosine.h index cbe78f7ba..2704a87a0 100644 --- a/poincare/include/poincare/hyperbolic_cosine.h +++ b/poincare/include/poincare/hyperbolic_cosine.h @@ -37,8 +37,8 @@ class HyperbolicCosine final : public HyperbolicTrigonometricFunction { public: HyperbolicCosine(const HyperbolicCosineNode * n) : HyperbolicTrigonometricFunction(n) {} static HyperbolicCosine Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("cosh", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("cosh", 1, &UntypedBuilderOneChild); }; } diff --git a/poincare/include/poincare/hyperbolic_sine.h b/poincare/include/poincare/hyperbolic_sine.h index 53cf3eb85..8aeadd16e 100644 --- a/poincare/include/poincare/hyperbolic_sine.h +++ b/poincare/include/poincare/hyperbolic_sine.h @@ -37,8 +37,8 @@ class HyperbolicSine final : public HyperbolicTrigonometricFunction { public: HyperbolicSine(const HyperbolicSineNode * n) : HyperbolicTrigonometricFunction(n) {} static HyperbolicSine Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("sinh", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("sinh", 1, &UntypedBuilderOneChild); }; } diff --git a/poincare/include/poincare/hyperbolic_tangent.h b/poincare/include/poincare/hyperbolic_tangent.h index cc43e572b..321f5581e 100644 --- a/poincare/include/poincare/hyperbolic_tangent.h +++ b/poincare/include/poincare/hyperbolic_tangent.h @@ -37,8 +37,8 @@ class HyperbolicTangent final : public HyperbolicTrigonometricFunction { public: HyperbolicTangent(const HyperbolicTangentNode * n) : HyperbolicTrigonometricFunction(n) {} static HyperbolicTangent Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("tanh", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("tanh", 1, &UntypedBuilderOneChild); }; } diff --git a/poincare/include/poincare/imaginary_part.h b/poincare/include/poincare/imaginary_part.h index 3fda87d4e..882d9ebfa 100644 --- a/poincare/include/poincare/imaginary_part.h +++ b/poincare/include/poincare/imaginary_part.h @@ -46,8 +46,8 @@ class ImaginaryPart final : public Expression { public: ImaginaryPart(const ImaginaryPartNode * n) : Expression(n) {} static ImaginaryPart Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("im", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("im", 1, &UntypedBuilderOneChild); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); }; diff --git a/poincare/include/poincare/integral.h b/poincare/include/poincare/integral.h index 403a41b13..1ebefe772 100644 --- a/poincare/include/poincare/integral.h +++ b/poincare/include/poincare/integral.h @@ -57,6 +57,7 @@ public: Integral(const IntegralNode * n) : Expression(n) {} static Integral Builder(Expression child0, Symbol child1, Expression child2, Expression child3); static Expression UntypedBuilder(Expression children) { + assert(children.type() == ExpressionNode::Type::Matrix); if (children.childAtIndex(1).type() != ExpressionNode::Type::Symbol) { // Second parameter must be a Symbol. return Expression(); diff --git a/poincare/include/poincare/least_common_multiple.h b/poincare/include/poincare/least_common_multiple.h index 4f2fcbe4f..0155895b5 100644 --- a/poincare/include/poincare/least_common_multiple.h +++ b/poincare/include/poincare/least_common_multiple.h @@ -38,8 +38,7 @@ class LeastCommonMultiple final : public Expression { public: LeastCommonMultiple(const LeastCommonMultipleNode * n) : Expression(n) {} static LeastCommonMultiple Builder(Expression child0, Expression child1); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("lcm", 2, &UntypedBuilder); + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("lcm", 2, &UntypedBuilderTwoChildren); // Expression Expression shallowReduce(); diff --git a/poincare/include/poincare/logarithm.h b/poincare/include/poincare/logarithm.h index c7c5e5902..eede67cea 100644 --- a/poincare/include/poincare/logarithm.h +++ b/poincare/include/poincare/logarithm.h @@ -45,8 +45,7 @@ class Logarithm final : public Expression { public: Logarithm(const LogarithmNode<2> * n) : Expression(n) {} static Logarithm Builder(Expression child0, Expression child1); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("log", 2, &UntypedBuilder); + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("log", 2, &UntypedBuilderTwoChildren); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); Expression shallowBeautify(); @@ -62,8 +61,8 @@ class CommonLogarithm : public Expression { public: CommonLogarithm(const LogarithmNode<1> * n) : Expression(n) {} static CommonLogarithm Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("log", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("log", 1, &UntypedBuilderOneChild); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); }; diff --git a/poincare/include/poincare/matrix_dimension.h b/poincare/include/poincare/matrix_dimension.h index 5fc51803f..99dab0e30 100644 --- a/poincare/include/poincare/matrix_dimension.h +++ b/poincare/include/poincare/matrix_dimension.h @@ -36,8 +36,8 @@ class MatrixDimension final : public Expression { public: MatrixDimension(const MatrixDimensionNode * n) : Expression(n) {} static MatrixDimension Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("dim", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("dim", 1, &UntypedBuilderOneChild); Expression shallowReduce(); }; diff --git a/poincare/include/poincare/matrix_inverse.h b/poincare/include/poincare/matrix_inverse.h index b03976fb4..ea3ca6ce2 100644 --- a/poincare/include/poincare/matrix_inverse.h +++ b/poincare/include/poincare/matrix_inverse.h @@ -35,8 +35,8 @@ class MatrixInverse final : public Expression { public: MatrixInverse(const MatrixInverseNode * n) : Expression(n) {} static MatrixInverse Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("inverse", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("inverse", 1, &UntypedBuilderOneChild); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); }; diff --git a/poincare/include/poincare/matrix_trace.h b/poincare/include/poincare/matrix_trace.h index ac281b937..9f729a09c 100644 --- a/poincare/include/poincare/matrix_trace.h +++ b/poincare/include/poincare/matrix_trace.h @@ -35,8 +35,8 @@ class MatrixTrace final : public Expression { public: MatrixTrace(const MatrixTraceNode * n) : Expression(n) {} static MatrixTrace Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("trace", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("trace", 1, &UntypedBuilderOneChild); Expression shallowReduce(); }; diff --git a/poincare/include/poincare/matrix_transpose.h b/poincare/include/poincare/matrix_transpose.h index bf6c1d7ec..9f5951d9d 100644 --- a/poincare/include/poincare/matrix_transpose.h +++ b/poincare/include/poincare/matrix_transpose.h @@ -35,8 +35,8 @@ class MatrixTranspose final : public Expression { public: MatrixTranspose(const MatrixTransposeNode * n) : Expression(n) {} static MatrixTranspose Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("transpose", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("transpose", 1, &UntypedBuilderOneChild); Expression shallowReduce(); }; diff --git a/poincare/include/poincare/naperian_logarithm.h b/poincare/include/poincare/naperian_logarithm.h index c880afe5a..712b85f27 100644 --- a/poincare/include/poincare/naperian_logarithm.h +++ b/poincare/include/poincare/naperian_logarithm.h @@ -45,8 +45,8 @@ class NaperianLogarithm final : public Expression { public: NaperianLogarithm(const NaperianLogarithmNode * n) : Expression(n) {} static NaperianLogarithm Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("ln", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("ln", 1, &UntypedBuilderOneChild); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); }; diff --git a/poincare/include/poincare/nth_root.h b/poincare/include/poincare/nth_root.h index 9612cf8a2..f0d637622 100644 --- a/poincare/include/poincare/nth_root.h +++ b/poincare/include/poincare/nth_root.h @@ -36,8 +36,7 @@ class NthRoot final : public Expression { public: NthRoot(const NthRootNode * n) : Expression(n) {} static NthRoot Builder(Expression child0, Expression child1); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("root", 2, &UntypedBuilder); + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("root", 2, &UntypedBuilderTwoChildren); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); }; diff --git a/poincare/include/poincare/permute_coefficient.h b/poincare/include/poincare/permute_coefficient.h index 45cd8f8ee..8ec9da24a 100644 --- a/poincare/include/poincare/permute_coefficient.h +++ b/poincare/include/poincare/permute_coefficient.h @@ -42,8 +42,7 @@ class PermuteCoefficient final : public Expression { public: PermuteCoefficient(const PermuteCoefficientNode * n) : Expression(n) {} static PermuteCoefficient Builder(Expression child0, Expression child1); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("permute", 2, &UntypedBuilder); + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("permute", 2, &UntypedBuilderTwoChildren); // Expression Expression shallowReduce(); diff --git a/poincare/include/poincare/prediction_interval.h b/poincare/include/poincare/prediction_interval.h index f21dc03e8..69da94c98 100644 --- a/poincare/include/poincare/prediction_interval.h +++ b/poincare/include/poincare/prediction_interval.h @@ -38,8 +38,7 @@ class PredictionInterval final : public Expression { public: PredictionInterval(const PredictionIntervalNode * n) : Expression(n) {} static PredictionInterval Builder(Expression child0, Expression child1); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("prediction95", 2, &UntypedBuilder); + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("prediction95", 2, &UntypedBuilderTwoChildren); // Expression Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); diff --git a/poincare/include/poincare/product.h b/poincare/include/poincare/product.h index e57525551..9a37e7868 100644 --- a/poincare/include/poincare/product.h +++ b/poincare/include/poincare/product.h @@ -37,6 +37,7 @@ public: Product(const ProductNode * n) : Expression(n) {} static Product Builder(Expression child0, Symbol child1, Expression child2, Expression child3); static Expression UntypedBuilder(Expression children) { + assert(children.type() == ExpressionNode::Type::Matrix); if (children.childAtIndex(1).type() != ExpressionNode::Type::Symbol) { // Second parameter must be a Symbol. return Expression(); diff --git a/poincare/include/poincare/randint.h b/poincare/include/poincare/randint.h index 469dc209a..292dc33cd 100644 --- a/poincare/include/poincare/randint.h +++ b/poincare/include/poincare/randint.h @@ -42,8 +42,7 @@ friend class RandintNode; public: Randint(const RandintNode * n) : Expression(n) {} static Randint Builder(Expression child0, Expression child1); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("randint", 2, &UntypedBuilder); + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("randint", 2, &UntypedBuilderTwoChildren); }; } diff --git a/poincare/include/poincare/random.h b/poincare/include/poincare/random.h index 8b74c5b56..0446a25f9 100644 --- a/poincare/include/poincare/random.h +++ b/poincare/include/poincare/random.h @@ -44,7 +44,7 @@ friend class RandomNode; public: Random(const RandomNode * n) : Expression(n) {} static Random Builder(); - static Expression UntypedBuilder(Expression children) { return Builder(); } + static Expression UntypedBuilder(Expression children) { assert(children.type() == ExpressionNode::Type::Matrix); return Builder(); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("random", 0, &UntypedBuilder); template static T random(); diff --git a/poincare/include/poincare/real_part.h b/poincare/include/poincare/real_part.h index ad7fba108..79b9cfd38 100644 --- a/poincare/include/poincare/real_part.h +++ b/poincare/include/poincare/real_part.h @@ -46,8 +46,8 @@ class RealPart final : public Expression { public: RealPart(const RealPartNode * n) : Expression(n) {} static RealPart Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("re", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("re", 1, &UntypedBuilderOneChild); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); }; diff --git a/poincare/include/poincare/round.h b/poincare/include/poincare/round.h index d397217cc..2fc0075b6 100644 --- a/poincare/include/poincare/round.h +++ b/poincare/include/poincare/round.h @@ -39,8 +39,7 @@ class Round final : public Expression { public: Round(const RoundNode * n) : Expression(n) {} static Round Builder(Expression child0, Expression child1); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0), children.childAtIndex(1)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("round", 2, &UntypedBuilder); + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("round", 2, &UntypedBuilderTwoChildren); Expression shallowReduce(); }; diff --git a/poincare/include/poincare/sign_function.h b/poincare/include/poincare/sign_function.h index 3205d8d7b..2a4889e45 100644 --- a/poincare/include/poincare/sign_function.h +++ b/poincare/include/poincare/sign_function.h @@ -46,8 +46,8 @@ class SignFunction final : public Expression { public: SignFunction(const SignFunctionNode * n) : Expression(n) {} static SignFunction Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("sign", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("sign", 1, &UntypedBuilderOneChild); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); }; diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index f53614b9e..75d65d604 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -49,8 +49,8 @@ class Sine final : public Expression { public: Sine(const SineNode * n) : Expression(n) {} static Sine Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("sin", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("sin", 1, &UntypedBuilderOneChild); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); }; diff --git a/poincare/include/poincare/square_root.h b/poincare/include/poincare/square_root.h index a47c17adb..bf9629e62 100644 --- a/poincare/include/poincare/square_root.h +++ b/poincare/include/poincare/square_root.h @@ -42,9 +42,9 @@ class SquareRoot final : public Expression { public: SquareRoot(const SquareRootNode * n) : Expression(n) {} static SquareRoot Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } + static_assert('\x91' == Ion::Charset::Root, "Charset error"); - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("\x91", 1, &UntypedBuilder); + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("\x91", 1, &UntypedBuilderOneChild); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: diff --git a/poincare/include/poincare/sum.h b/poincare/include/poincare/sum.h index 0d9cc6da2..503591c84 100644 --- a/poincare/include/poincare/sum.h +++ b/poincare/include/poincare/sum.h @@ -37,6 +37,7 @@ public: Sum(const SumNode * n) : Expression(n) {} static Sum Builder(Expression child0, Symbol child1, Expression child2, Expression child3); static Expression UntypedBuilder(Expression children) { + assert(children.type() == ExpressionNode::Type::Matrix); if (children.childAtIndex(1).type() != ExpressionNode::Type::Symbol) { // Second parameter must be a Symbol. return Expression(); diff --git a/poincare/include/poincare/tangent.h b/poincare/include/poincare/tangent.h index b37a99d35..ea04dd640 100644 --- a/poincare/include/poincare/tangent.h +++ b/poincare/include/poincare/tangent.h @@ -47,8 +47,8 @@ class Tangent final : public Expression { public: Tangent(const TangentNode * n) : Expression(n) {} static Tangent Builder(Expression child); - static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("tan", 1, &UntypedBuilder); + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("tan", 1, &UntypedBuilderOneChild); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); }; From 3fc32d7c74e06824cdd167a0917d9c531f0e2db3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 19 Feb 2019 12:20:59 +0100 Subject: [PATCH 340/373] [poincare] Clean warning --- poincare/src/addition.cpp | 2 +- poincare/src/multiplication.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 80361ed50..21a12a206 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -96,7 +96,7 @@ Addition Addition::Builder() { Addition Addition::Builder(Expression * children, size_t numberOfChildren) { Addition a = Addition::Builder(); - for (int i = 0; i < numberOfChildren; i++) { + for (size_t i = 0; i < numberOfChildren; i++) { a.addChildAtIndexInPlace(children[i], i, i); } return a; diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index f87398e91..52efbe73d 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -117,7 +117,7 @@ Multiplication Multiplication::Builder() { Multiplication Multiplication::Builder(Expression * children, size_t numberOfChildren) { Multiplication m = Multiplication::Builder(); - for (int i = 0; i < numberOfChildren; i++) { + for (size_t i = 0; i < numberOfChildren; i++) { m.addChildAtIndexInPlace(children[i], i, i); } return m; From 55704b4e65b70a943926fc050a3425dc418dd291 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 19 Feb 2019 14:00:58 +0100 Subject: [PATCH 341/373] [poincare] TreeHandle: the constructor from a identifier retains the node if it has one --- poincare/include/poincare/expression.h | 2 +- poincare/include/poincare/tree_handle.h | 6 +++++- poincare/src/integer.cpp | 4 +--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index f87d66aa1..b250a00cb 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -248,6 +248,7 @@ public: protected: static bool SimplificationHasBeenInterrupted(); Expression(const ExpressionNode * n) : TreeHandle(n) {} + Expression(int nodeIdentifier) : TreeHandle(nodeIdentifier) {} template static Expression UntypedBuilderOneChild(Expression children) { assert(children.type() == ExpressionNode::Type::Matrix); @@ -284,7 +285,6 @@ protected: } /* Hierarchy */ - Expression(int nodeIdentifier) : TreeHandle(nodeIdentifier) {} Expression parent() const; // TODO try to inline void defaultSetChildrenInPlace(Expression other); void addChildAtIndexInPlace(TreeHandle t, int index, int currentNumberOfChildren) = delete; diff --git a/poincare/include/poincare/tree_handle.h b/poincare/include/poincare/tree_handle.h index abd3008d6..881d95206 100644 --- a/poincare/include/poincare/tree_handle.h +++ b/poincare/include/poincare/tree_handle.h @@ -103,7 +103,11 @@ public: protected: /* Constructor */ TreeHandle(const TreeNode * node); - TreeHandle(int nodeIndentifier = TreeNode::NoNodeIdentifier) : m_identifier(nodeIndentifier) {} + TreeHandle(int nodeIndentifier = TreeNode::NoNodeIdentifier) : m_identifier(nodeIndentifier) { + if (hasNode(nodeIndentifier)) { + node()->retain(); + } + } // WARNING: if the children table is the result of a cast, the object downcasted has to be the same size as a TreeHandle. static TreeHandle BuildWithBasicChildren(TreeNode * node, TreeHandle * children = nullptr, int numberOfChildren = 0); diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 675bf0b44..67fd3e295 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -107,9 +107,7 @@ Integer::Integer(native_uint_t * digits, uint16_t numberOfDigits, bool negative) TreeHandle h = TreeHandle::BuildWithBasicChildren(node); /* Integer is a TreeHandle that keeps an extra integer. We cannot just cast * the TreeHandle in Integer, we have to build a new Integer. To do so, we - * pilfer the TreeHandle identifier. We thus have to increment the node - * reference counter to prevent its destruction when we leave this scope. */ - node->retain(); + * pilfer the TreeHandle identifier. */ new (this) Integer(h.identifier(), negative); } From fad3ad958d7cd0b2a8c43038195f3153685f5df9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 19 Feb 2019 14:26:30 +0100 Subject: [PATCH 342/373] [poincare] SymbolAbstract: the node alignment is handled by the TreePool and the TreeNode classes. SymbolAbstract and its children class don't need to watch the alignment. --- poincare/include/poincare/symbol_abstract.h | 1 - poincare/src/constant.cpp | 3 ++- poincare/src/function.cpp | 3 ++- poincare/src/symbol.cpp | 3 ++- poincare/src/symbol_abstract.cpp | 8 +------- 5 files changed, 7 insertions(+), 11 deletions(-) diff --git a/poincare/include/poincare/symbol_abstract.h b/poincare/include/poincare/symbol_abstract.h index c993ef2ad..f92732549 100644 --- a/poincare/include/poincare/symbol_abstract.h +++ b/poincare/include/poincare/symbol_abstract.h @@ -79,7 +79,6 @@ protected: private: static Expression Expand(const SymbolAbstract & symbol, Context & context, bool clone); static bool isReal(const SymbolAbstract & symbol, Context & context); - static size_t AlignedNodeSize(size_t nameLength, size_t nodeSize); }; } diff --git a/poincare/src/constant.cpp b/poincare/src/constant.cpp index cdc28aebb..d8b4ec7d9 100644 --- a/poincare/src/constant.cpp +++ b/poincare/src/constant.cpp @@ -77,7 +77,8 @@ Expression ConstantNode::shallowReduce(Context & context, Preferences::ComplexFo } Constant Constant::Builder(char name) { - void * bufferNode = TreePool::sharedPool()->alloc(SymbolAbstract::AlignedNodeSize(1, sizeof(ConstantNode))); + size_t size = sizeof(ConstantNode) + 1 + 1; + void * bufferNode = TreePool::sharedPool()->alloc(size); ConstantNode * node = new (bufferNode) ConstantNode(&name, 1); TreeHandle h = TreeHandle::BuildWithBasicChildren(node); return static_cast(h); diff --git a/poincare/src/function.cpp b/poincare/src/function.cpp index caae12cc4..d9ce48d2a 100644 --- a/poincare/src/function.cpp +++ b/poincare/src/function.cpp @@ -93,7 +93,8 @@ Evaluation FunctionNode::templatedApproximate(Context& context, Preferences:: } Function Function::Builder(const char * name, size_t length, Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(SymbolAbstract::AlignedNodeSize(length, sizeof(FunctionNode))); + size_t size = sizeof(FunctionNode) + length + 1; + void * bufferNode = TreePool::sharedPool()->alloc(size); FunctionNode * node = new (bufferNode) FunctionNode(name, length); Expression * childPointer = child.isUninitialized() ? nullptr : &child; int numberOfChild = child.isUninitialized() ? 0 : 1; diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 3e28c2ab7..3fcf7ff80 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -140,7 +140,8 @@ Evaluation SymbolNode::templatedApproximate(Context& context, Preferences::Co } Symbol Symbol::Builder(const char * name, int length) { - void * bufferNode = TreePool::sharedPool()->alloc(SymbolAbstract::AlignedNodeSize(length, sizeof(SymbolNode))); + size_t size = sizeof(SymbolNode) + length + 1; + void * bufferNode = TreePool::sharedPool()->alloc(size); SymbolNode * node = new (bufferNode) SymbolNode(name, length); TreeHandle h = TreeHandle::BuildWithBasicChildren(node); return static_cast(h); diff --git a/poincare/src/symbol_abstract.cpp b/poincare/src/symbol_abstract.cpp index 3ea31e3ab..8cd30ea73 100644 --- a/poincare/src/symbol_abstract.cpp +++ b/poincare/src/symbol_abstract.cpp @@ -9,7 +9,7 @@ namespace Poincare { size_t SymbolAbstractNode::size() const { - return SymbolAbstract::AlignedNodeSize(strlen(name()), nodeSize()); + return nodeSize() + strlen(name()) + 1; } ExpressionNode::Sign SymbolAbstractNode::sign(Context * context) const { @@ -71,10 +71,4 @@ bool SymbolAbstract::isReal(const SymbolAbstract & symbol, Context & context) { return e.isReal(context); } -/* TreePool uses adresses and sizes that are multiples of 4 in order to make - * node moves faster.*/ -size_t SymbolAbstract::AlignedNodeSize(size_t nameLength, size_t nodeSize) { - return Helpers::AlignedSize(nodeSize+nameLength+1, 4); -} - } From 3adbca88d834081e9cfed0ee0533bb33547ad461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 19 Feb 2019 14:31:02 +0100 Subject: [PATCH 343/373] [poincare] TreeHandle: Improve BuildWithBasicChildren When building ghost nodes to stand as temporary children, we do not need to move them are they are built sequentially after the built node. --- poincare/src/tree_handle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/tree_handle.cpp b/poincare/src/tree_handle.cpp index 7493b56b4..15dcbd51c 100644 --- a/poincare/src/tree_handle.cpp +++ b/poincare/src/tree_handle.cpp @@ -195,7 +195,7 @@ TreeHandle TreeHandle::BuildWithBasicChildren(TreeNode * node, TreeHandle * chil GhostNode * ghost = new (pool->alloc(sizeof(GhostNode))) GhostNode(); ghost->rename(pool->generateIdentifier(), false); ghost->retain(); - pool->move(node->next(), ghost, 0); + assert((char *)ghost == (char *)node->next() + i*sizeof(GhostNode)); } node->rename(pool->generateIdentifier(), false); TreeHandle h = TreeHandle(node); From d29885028b905cdfbf8345d83c91cba5eaae15bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 19 Feb 2019 14:51:33 +0100 Subject: [PATCH 344/373] [poincare] Factorize Builders of SymbolAbstract classes --- poincare/include/poincare/constant.h | 2 +- poincare/include/poincare/symbol.h | 4 ++-- poincare/include/poincare/symbol_abstract.h | 3 +++ poincare/src/constant.cpp | 8 -------- poincare/src/function.cpp | 14 ++++++-------- poincare/src/symbol.cpp | 10 ---------- poincare/src/symbol_abstract.cpp | 15 +++++++++++++++ 7 files changed, 27 insertions(+), 29 deletions(-) diff --git a/poincare/include/poincare/constant.h b/poincare/include/poincare/constant.h index c0754357c..9f09fbbe1 100644 --- a/poincare/include/poincare/constant.h +++ b/poincare/include/poincare/constant.h @@ -55,7 +55,7 @@ private: class Constant final : public SymbolAbstract { public: Constant(const ConstantNode * node) : SymbolAbstract(node) {} - static Constant Builder(char name); + static Constant Builder(char name) { return SymbolAbstract::Builder(&name, 1); } // Constant properties bool isPi() const { return node()->isPi(); } diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index 776498cac..fbe668d84 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -64,8 +64,8 @@ public: UnknownX = 1, }; Symbol(const SymbolNode * node) : SymbolAbstract(node) {} - static Symbol Builder(const char * name, int length); - static Symbol Builder(char name); + static Symbol Builder(const char * name, int length) { return SymbolAbstract::Builder(name, length); } + static Symbol Builder(char name) { return Symbol::Builder(&name, 1); } static Symbol Ans() { return Symbol::Builder(k_ans, k_ansLength); } static Expression UntypedBuilder(const char * name, size_t length, Context * context) { // create an expression only if it is not in the context or defined as a symbol diff --git a/poincare/include/poincare/symbol_abstract.h b/poincare/include/poincare/symbol_abstract.h index f92732549..2c2e10a13 100644 --- a/poincare/include/poincare/symbol_abstract.h +++ b/poincare/include/poincare/symbol_abstract.h @@ -75,6 +75,9 @@ public: protected: SymbolAbstract(const SymbolAbstractNode * node) : Expression(node) {} + template + static T Builder(const char * name, int length); + SymbolAbstractNode * node() const { return static_cast(Expression::node()); } private: static Expression Expand(const SymbolAbstract & symbol, Context & context, bool clone); diff --git a/poincare/src/constant.cpp b/poincare/src/constant.cpp index d8b4ec7d9..6c4039c03 100644 --- a/poincare/src/constant.cpp +++ b/poincare/src/constant.cpp @@ -76,14 +76,6 @@ Expression ConstantNode::shallowReduce(Context & context, Preferences::ComplexFo return Constant(this).shallowReduce(context, complexFormat, angleUnit, target); } -Constant Constant::Builder(char name) { - size_t size = sizeof(ConstantNode) + 1 + 1; - void * bufferNode = TreePool::sharedPool()->alloc(size); - ConstantNode * node = new (bufferNode) ConstantNode(&name, 1); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); - return static_cast(h); -} - Expression Constant::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { Expression result; if (complexFormat == Preferences::ComplexFormat::Real && isIComplex()) { diff --git a/poincare/src/function.cpp b/poincare/src/function.cpp index d9ce48d2a..ec7910c85 100644 --- a/poincare/src/function.cpp +++ b/poincare/src/function.cpp @@ -92,14 +92,12 @@ Evaluation FunctionNode::templatedApproximate(Context& context, Preferences:: return e.node()->approximate(T(), context, complexFormat, angleUnit); } -Function Function::Builder(const char * name, size_t length, Expression child) { - size_t size = sizeof(FunctionNode) + length + 1; - void * bufferNode = TreePool::sharedPool()->alloc(size); - FunctionNode * node = new (bufferNode) FunctionNode(name, length); - Expression * childPointer = child.isUninitialized() ? nullptr : &child; - int numberOfChild = child.isUninitialized() ? 0 : 1; - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, childPointer, numberOfChild); - return static_cast(h); +Function Function::Builder(const char * name, size_t length, Expression child) { + Function f = SymbolAbstract::Builder(name, length); + if (!child.isUninitialized()) { + f.replaceChildAtIndexInPlace(0, child); + } + return f; } Expression Function::replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression) { diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 3fcf7ff80..f4225c05a 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -139,16 +139,6 @@ Evaluation SymbolNode::templatedApproximate(Context& context, Preferences::Co return e.node()->approximate(T(), context, complexFormat, angleUnit); } -Symbol Symbol::Builder(const char * name, int length) { - size_t size = sizeof(SymbolNode) + length + 1; - void * bufferNode = TreePool::sharedPool()->alloc(size); - SymbolNode * node = new (bufferNode) SymbolNode(name, length); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); - return static_cast(h); -} - -Symbol Symbol::Builder(char name) { return Symbol::Builder(&name, 1); } - bool Symbol::isSeriesSymbol(const char * c) { // [NV][1-3] if (c[2] == 0 && (c[0] == 'N' || c[0] == 'V') && c[1] >= '1' && c[1] <= '3') { diff --git a/poincare/src/symbol_abstract.cpp b/poincare/src/symbol_abstract.cpp index 8cd30ea73..59bdf55f6 100644 --- a/poincare/src/symbol_abstract.cpp +++ b/poincare/src/symbol_abstract.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include #include #include #include @@ -34,6 +36,15 @@ int SymbolAbstractNode::simplificationOrderSameType(const ExpressionNode * e, bo return strcmp(name(), static_cast(e)->name()); } +template +T SymbolAbstract::Builder(const char * name, int length) { + size_t size = sizeof(U) + length + 1; + void * bufferNode = TreePool::sharedPool()->alloc(size); + U * node = new (bufferNode) U(name, length); + TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + return static_cast(h); +} + size_t SymbolAbstract::TruncateExtension(char * dst, const char * src, size_t len) { const char * cur = src; const char * end = src+len-1; @@ -71,4 +82,8 @@ bool SymbolAbstract::isReal(const SymbolAbstract & symbol, Context & context) { return e.isReal(context); } +template Constant SymbolAbstract::Builder(char const*, int); +template Function SymbolAbstract::Builder(char const*, int); +template Symbol SymbolAbstract::Builder(char const*, int); + } From 24c9617a8966d11f1e1ae5a0a984113f9dd024e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 21 Feb 2019 10:31:05 +0100 Subject: [PATCH 345/373] [poincare] Templatize TreeHandle Builders --- apps/regression/model/cubic_model.cpp | 2 +- apps/regression/model/exponential_model.cpp | 2 +- apps/regression/model/linear_model.cpp | 2 +- apps/regression/model/logarithmic_model.cpp | 2 +- apps/regression/model/logistic_model.cpp | 4 +- apps/regression/model/power_model.cpp | 2 +- apps/regression/model/quadratic_model.cpp | 2 +- apps/regression/model/quartic_model.cpp | 2 +- apps/regression/model/trigonometric_model.cpp | 2 +- poincare/Makefile | 3 - poincare/include/poincare/absolute_value.h | 2 +- .../include/poincare/absolute_value_layout.h | 2 +- poincare/include/poincare/addition.h | 5 +- poincare/include/poincare/arc_cosine.h | 2 +- poincare/include/poincare/arc_sine.h | 2 +- poincare/include/poincare/arc_tangent.h | 2 +- .../include/poincare/binomial_coefficient.h | 2 +- .../poincare/binomial_coefficient_layout.h | 2 +- poincare/include/poincare/ceiling.h | 2 +- poincare/include/poincare/ceiling_layout.h | 2 +- poincare/include/poincare/complex_argument.h | 2 +- poincare/include/poincare/complex_cartesian.h | 4 +- .../include/poincare/condensed_sum_layout.h | 2 +- .../include/poincare/confidence_interval.h | 4 +- poincare/include/poincare/conjugate.h | 2 +- poincare/include/poincare/conjugate_layout.h | 2 +- poincare/include/poincare/cosine.h | 2 +- poincare/include/poincare/derivative.h | 11 +- poincare/include/poincare/determinant.h | 2 +- poincare/include/poincare/division.h | 4 +- poincare/include/poincare/division_quotient.h | 2 +- .../include/poincare/division_remainder.h | 2 +- poincare/include/poincare/empty_expression.h | 2 +- poincare/include/poincare/equal.h | 2 +- poincare/include/poincare/expression.h | 1 + poincare/include/poincare/factor.h | 2 +- poincare/include/poincare/factorial.h | 3 +- poincare/include/poincare/floor.h | 2 +- poincare/include/poincare/floor_layout.h | 2 +- poincare/include/poincare/frac_part.h | 2 +- poincare/include/poincare/fraction_layout.h | 2 +- poincare/include/poincare/ghost.h | 7 +- .../include/poincare/great_common_divisor.h | 2 +- poincare/include/poincare/grid_layout.h | 3 +- poincare/include/poincare/horizontal_layout.h | 11 +- .../include/poincare/hyperbolic_arc_cosine.h | 2 +- .../include/poincare/hyperbolic_arc_sine.h | 2 +- .../include/poincare/hyperbolic_arc_tangent.h | 2 +- poincare/include/poincare/hyperbolic_cosine.h | 2 +- poincare/include/poincare/hyperbolic_sine.h | 2 +- .../include/poincare/hyperbolic_tangent.h | 2 +- poincare/include/poincare/imaginary_part.h | 2 +- poincare/include/poincare/integral.h | 12 +- poincare/include/poincare/integral_layout.h | 2 +- poincare/include/poincare/layout.h | 1 + .../include/poincare/least_common_multiple.h | 2 +- .../poincare/left_parenthesis_layout.h | 2 +- .../poincare/left_square_bracket_layout.h | 2 +- poincare/include/poincare/logarithm.h | 4 +- poincare/include/poincare/matrix.h | 2 +- poincare/include/poincare/matrix_complex.h | 2 +- poincare/include/poincare/matrix_dimension.h | 2 +- poincare/include/poincare/matrix_inverse.h | 2 +- poincare/include/poincare/matrix_layout.h | 12 +- poincare/include/poincare/matrix_trace.h | 2 +- poincare/include/poincare/matrix_transpose.h | 2 +- poincare/include/poincare/multiplication.h | 5 +- .../include/poincare/naperian_logarithm.h | 2 +- poincare/include/poincare/nth_root.h | 2 +- poincare/include/poincare/opposite.h | 4 +- poincare/include/poincare/parenthesis.h | 2 +- .../include/poincare/permute_coefficient.h | 2 +- poincare/include/poincare/power.h | 2 +- .../include/poincare/prediction_interval.h | 2 +- poincare/include/poincare/product.h | 12 +- poincare/include/poincare/product_layout.h | 2 +- poincare/include/poincare/randint.h | 2 +- poincare/include/poincare/random.h | 2 +- poincare/include/poincare/real_part.h | 2 +- .../poincare/right_parenthesis_layout.h | 2 +- .../poincare/right_square_bracket_layout.h | 2 +- poincare/include/poincare/round.h | 2 +- poincare/include/poincare/sign_function.h | 2 +- poincare/include/poincare/sine.h | 2 +- poincare/include/poincare/square_root.h | 2 +- poincare/include/poincare/store.h | 2 +- poincare/include/poincare/subtraction.h | 4 +- poincare/include/poincare/sum.h | 12 +- poincare/include/poincare/sum_layout.h | 2 +- poincare/include/poincare/tangent.h | 2 +- poincare/include/poincare/tree_handle.h | 13 +- poincare/include/poincare/undefined.h | 2 +- poincare/include/poincare/unreal.h | 2 +- poincare/src/absolute_value.cpp | 6 - poincare/src/absolute_value_layout.cpp | 12 -- poincare/src/addition.cpp | 15 --- poincare/src/arc_cosine.cpp | 6 - poincare/src/arc_sine.cpp | 6 - poincare/src/arc_tangent.cpp | 6 - poincare/src/binomial_coefficient.cpp | 7 - poincare/src/binomial_coefficient_layout.cpp | 10 +- poincare/src/ceiling.cpp | 6 - poincare/src/ceiling_layout.cpp | 12 -- poincare/src/char_layout.cpp | 2 +- poincare/src/complex.cpp | 2 +- poincare/src/complex_argument.cpp | 6 - poincare/src/complex_cartesian.cpp | 14 -- poincare/src/condensed_sum_layout.cpp | 7 - poincare/src/confidence_interval.cpp | 12 -- poincare/src/conjugate.cpp | 6 - poincare/src/conjugate_layout.cpp | 7 - poincare/src/cosine.cpp | 6 - poincare/src/decimal.cpp | 2 +- poincare/src/derivative.cpp | 12 +- poincare/src/determinant.cpp | 6 - poincare/src/division.cpp | 14 -- poincare/src/division_quotient.cpp | 6 - poincare/src/division_remainder.cpp | 6 - poincare/src/empty_expression.cpp | 7 - poincare/src/empty_layout.cpp | 2 +- poincare/src/equal.cpp | 6 - poincare/src/factor.cpp | 6 - poincare/src/factorial.cpp | 6 - poincare/src/float.cpp | 2 +- poincare/src/floor.cpp | 6 - poincare/src/floor_layout.cpp | 12 -- poincare/src/frac_part.cpp | 6 - poincare/src/fraction_layout.cpp | 9 +- poincare/src/great_common_divisor.cpp | 8 +- poincare/src/grid_layout.cpp | 9 +- poincare/src/horizontal_layout.cpp | 7 - poincare/src/hyperbolic_arc_cosine.cpp | 6 - poincare/src/hyperbolic_arc_sine.cpp | 6 - poincare/src/hyperbolic_arc_tangent.cpp | 6 - poincare/src/hyperbolic_cosine.cpp | 6 - poincare/src/hyperbolic_sine.cpp | 6 - poincare/src/hyperbolic_tangent.cpp | 6 - poincare/src/imaginary_part.cpp | 6 - poincare/src/infinity.cpp | 2 +- poincare/src/integer.cpp | 2 +- poincare/src/integral.cpp | 14 +- poincare/src/integral_layout.cpp | 7 - poincare/src/least_common_multiple.cpp | 6 - poincare/src/left_parenthesis_layout.cpp | 7 - poincare/src/left_square_bracket_layout.cpp | 7 - poincare/src/logarithm.cpp | 16 +-- poincare/src/matrix.cpp | 7 - poincare/src/matrix_complex.cpp | 8 -- poincare/src/matrix_dimension.cpp | 6 - poincare/src/matrix_inverse.cpp | 6 - poincare/src/matrix_layout.cpp | 9 +- poincare/src/matrix_trace.cpp | 6 - poincare/src/matrix_transpose.cpp | 6 - poincare/src/multiplication.cpp | 15 --- poincare/src/naperian_logarithm.cpp | 6 - poincare/src/nth_root.cpp | 6 - poincare/src/nth_root_layout.cpp | 7 +- poincare/src/opposite.cpp | 13 -- poincare/src/parenthesis.cpp | 6 - poincare/src/permute_coefficient.cpp | 6 - poincare/src/power.cpp | 7 - poincare/src/prediction_interval.cpp | 6 - poincare/src/product.cpp | 12 +- poincare/src/product_layout.cpp | 7 - poincare/src/randint.cpp | 6 - poincare/src/random.cpp | 7 - poincare/src/rational.cpp | 2 +- poincare/src/real_part.cpp | 6 - poincare/src/right_parenthesis_layout.cpp | 7 - poincare/src/right_square_bracket_layout.cpp | 7 - poincare/src/round.cpp | 6 - poincare/src/sign_function.cpp | 6 - poincare/src/sine.cpp | 6 - poincare/src/square_root.cpp | 6 - poincare/src/store.cpp | 7 - poincare/src/subtraction.cpp | 14 -- poincare/src/sum.cpp | 12 +- poincare/src/sum_layout.cpp | 7 - poincare/src/symbol_abstract.cpp | 2 +- poincare/src/tangent.cpp | 6 - poincare/src/tree_handle.cpp | 123 ++++++++++++++++-- poincare/src/undefined.cpp | 7 - poincare/src/unreal.cpp | 7 - poincare/src/vertical_offset_layout.cpp | 3 +- poincare/test/tree/blob_node.h | 2 +- poincare/test/tree/pair_node.h | 6 +- 186 files changed, 292 insertions(+), 766 deletions(-) delete mode 100644 poincare/src/absolute_value_layout.cpp delete mode 100644 poincare/src/ceiling_layout.cpp delete mode 100644 poincare/src/floor_layout.cpp diff --git a/apps/regression/model/cubic_model.cpp b/apps/regression/model/cubic_model.cpp index da7fc39c6..5147ff5f5 100644 --- a/apps/regression/model/cubic_model.cpp +++ b/apps/regression/model/cubic_model.cpp @@ -19,7 +19,7 @@ namespace Regression { Layout CubicModel::layout() { if (m_layout.isUninitialized()) { - const Layout layoutChildren[] = { + Layout layoutChildren[] = { CharLayout::Builder('a', KDFont::SmallFont), CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), CharLayout::Builder('X', KDFont::SmallFont), diff --git a/apps/regression/model/exponential_model.cpp b/apps/regression/model/exponential_model.cpp index 52492b4fe..320d99b45 100644 --- a/apps/regression/model/exponential_model.cpp +++ b/apps/regression/model/exponential_model.cpp @@ -11,7 +11,7 @@ namespace Regression { Layout ExponentialModel::layout() { if (m_layout.isUninitialized()) { - const Layout layoutChildren[] = { + Layout layoutChildren[] = { CharLayout::Builder('a', KDFont::SmallFont), CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), CharLayout::Builder('e', KDFont::SmallFont), diff --git a/apps/regression/model/linear_model.cpp b/apps/regression/model/linear_model.cpp index 272505f6c..92e03af93 100644 --- a/apps/regression/model/linear_model.cpp +++ b/apps/regression/model/linear_model.cpp @@ -11,7 +11,7 @@ namespace Regression { Layout LinearModel::layout() { if (m_layout.isUninitialized()) { - const Layout layoutChildren[] = { + Layout layoutChildren[] = { CharLayout::Builder('a', KDFont::SmallFont), CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), CharLayout::Builder('X', KDFont::SmallFont), diff --git a/apps/regression/model/logarithmic_model.cpp b/apps/regression/model/logarithmic_model.cpp index bb585ea59..fb7563928 100644 --- a/apps/regression/model/logarithmic_model.cpp +++ b/apps/regression/model/logarithmic_model.cpp @@ -11,7 +11,7 @@ namespace Regression { Layout LogarithmicModel::layout() { if (m_layout.isUninitialized()) { - const Layout layoutChildren[] = { + Layout layoutChildren[] = { CharLayout::Builder('a', KDFont::SmallFont), CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), CharLayout::Builder('l', KDFont::SmallFont), diff --git a/apps/regression/model/logistic_model.cpp b/apps/regression/model/logistic_model.cpp index c3f91bf95..ad0ea7503 100644 --- a/apps/regression/model/logistic_model.cpp +++ b/apps/regression/model/logistic_model.cpp @@ -12,13 +12,13 @@ namespace Regression { Layout LogisticModel::layout() { if (m_layout.isUninitialized()) { - const Layout exponentLayoutChildren[] = { + Layout exponentLayoutChildren[] = { CharLayout::Builder('-', KDFont::SmallFont), CharLayout::Builder('b', KDFont::SmallFont), CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), CharLayout::Builder('X', KDFont::SmallFont) }; - const Layout layoutChildren[] = { + Layout layoutChildren[] = { CharLayout::Builder('1', KDFont::SmallFont), CharLayout::Builder('+', KDFont::SmallFont), CharLayout::Builder('a', KDFont::SmallFont), diff --git a/apps/regression/model/power_model.cpp b/apps/regression/model/power_model.cpp index 4f341c4bf..bd790d815 100644 --- a/apps/regression/model/power_model.cpp +++ b/apps/regression/model/power_model.cpp @@ -12,7 +12,7 @@ namespace Regression { Layout PowerModel::layout() { if (m_layout.isUninitialized()) { - const Layout layoutChildren[] = { + Layout layoutChildren[] = { CharLayout::Builder('a', KDFont::SmallFont), CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), CharLayout::Builder('X', KDFont::SmallFont), diff --git a/apps/regression/model/quadratic_model.cpp b/apps/regression/model/quadratic_model.cpp index 0babfe9d6..0ee0b1764 100644 --- a/apps/regression/model/quadratic_model.cpp +++ b/apps/regression/model/quadratic_model.cpp @@ -19,7 +19,7 @@ namespace Regression { Layout QuadraticModel::layout() { if (m_layout.isUninitialized()) { - const Layout layoutChildren[] = { + Layout layoutChildren[] = { CharLayout::Builder('a', KDFont::SmallFont), CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), CharLayout::Builder('X', KDFont::SmallFont), diff --git a/apps/regression/model/quartic_model.cpp b/apps/regression/model/quartic_model.cpp index c1dbd87ca..3f7a4395a 100644 --- a/apps/regression/model/quartic_model.cpp +++ b/apps/regression/model/quartic_model.cpp @@ -19,7 +19,7 @@ namespace Regression { Layout QuarticModel::layout() { if (m_layout.isUninitialized()) { - const Layout layoutChildren[] = { + Layout layoutChildren[] = { CharLayout::Builder('a', KDFont::SmallFont), CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), CharLayout::Builder('X', KDFont::SmallFont), diff --git a/apps/regression/model/trigonometric_model.cpp b/apps/regression/model/trigonometric_model.cpp index ed919a59e..2a605cdde 100644 --- a/apps/regression/model/trigonometric_model.cpp +++ b/apps/regression/model/trigonometric_model.cpp @@ -20,7 +20,7 @@ namespace Regression { Layout TrigonometricModel::layout() { if (m_layout.isUninitialized()) { - const Layout layoutChildren[] = { + Layout layoutChildren[] = { CharLayout::Builder('a', KDFont::SmallFont), CharLayout::Builder(Ion::Charset::MiddleDot, KDFont::SmallFont), CharLayout::Builder('s', KDFont::SmallFont), diff --git a/poincare/Makefile b/poincare/Makefile index 7fbd144c1..28c3096e6 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -3,16 +3,13 @@ SFLAGS += -Ipoincare/include #include poincare/src/simplify/Makefile #include poincare/src/simplification/Makefile objs += $(addprefix poincare/src/,\ - absolute_value_layout.o\ binomial_coefficient_layout.o\ bracket_layout.o\ bracket_pair_layout.o\ - ceiling_layout.o\ char_layout.o\ condensed_sum_layout.o\ conjugate_layout.o\ empty_layout.o\ - floor_layout.o\ fraction_layout.o\ grid_layout.o\ horizontal_layout.o\ diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 66d4b8d4c..07c5f1bbf 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -49,7 +49,7 @@ class AbsoluteValue final : public Expression { friend class AbsoluteValueNode; public: AbsoluteValue(const AbsoluteValueNode * n) : Expression(n) {} - static AbsoluteValue Builder(Expression child); + static AbsoluteValue Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("abs", 1, &UntypedBuilderOneChild); diff --git a/poincare/include/poincare/absolute_value_layout.h b/poincare/include/poincare/absolute_value_layout.h index 42510c6b0..5a909f36d 100644 --- a/poincare/include/poincare/absolute_value_layout.h +++ b/poincare/include/poincare/absolute_value_layout.h @@ -33,7 +33,7 @@ private: class AbsoluteValueLayout final : public Layout { public: - static AbsoluteValueLayout Builder(Layout l); + static AbsoluteValueLayout Builder(Layout child) { return TreeHandle::FixedArityBuilder(&child, 1); } AbsoluteValueLayout() = delete; }; diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 07d482e46..6a0c3d44b 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -2,7 +2,6 @@ #define POINCARE_ADDITION_H #include -#include #include #include @@ -61,10 +60,10 @@ private: class Addition final : public NAryExpression { public: Addition(const AdditionNode * n) : NAryExpression(n) {} - static Addition Builder(); + static Addition Builder() { return TreeHandle::NAryBuilder(); } static Addition Builder(Expression e1) { return Addition::Builder(&e1, 1); } static Addition Builder(Expression e1, Expression e2) { return Addition::Builder(ArrayBuilder(e1, e2).array(), 2); } - static Addition Builder(Expression * children, size_t numberOfChildren); + static Addition Builder(Expression * children, size_t numberOfChildren) { return TreeHandle::NAryBuilder(children, numberOfChildren); } // Expression Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); Expression shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); diff --git a/poincare/include/poincare/arc_cosine.h b/poincare/include/poincare/arc_cosine.h index ee29beacb..89a976098 100644 --- a/poincare/include/poincare/arc_cosine.h +++ b/poincare/include/poincare/arc_cosine.h @@ -41,7 +41,7 @@ private: class ArcCosine final : public Expression { public: ArcCosine(const ArcCosineNode * n) : Expression(n) {} - static ArcCosine Builder(Expression child); + static ArcCosine Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("acos", 1, &UntypedBuilderOneChild); diff --git a/poincare/include/poincare/arc_sine.h b/poincare/include/poincare/arc_sine.h index 7ae261b42..2cdf8626f 100644 --- a/poincare/include/poincare/arc_sine.h +++ b/poincare/include/poincare/arc_sine.h @@ -40,7 +40,7 @@ private: class ArcSine final : public Expression { public: ArcSine(const ArcSineNode * n) : Expression(n) {} - static ArcSine Builder(Expression child); + static ArcSine Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("asin", 1, &UntypedBuilderOneChild); diff --git a/poincare/include/poincare/arc_tangent.h b/poincare/include/poincare/arc_tangent.h index a0d6218f4..b61438e64 100644 --- a/poincare/include/poincare/arc_tangent.h +++ b/poincare/include/poincare/arc_tangent.h @@ -44,7 +44,7 @@ private: class ArcTangent final : public Expression { public: ArcTangent(const ArcTangentNode * n) : Expression(n) {} - static ArcTangent Builder(Expression child); + static ArcTangent Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("atan", 1, &UntypedBuilderOneChild); diff --git a/poincare/include/poincare/binomial_coefficient.h b/poincare/include/poincare/binomial_coefficient.h index 3c3315fff..6eeb90dd4 100644 --- a/poincare/include/poincare/binomial_coefficient.h +++ b/poincare/include/poincare/binomial_coefficient.h @@ -39,7 +39,7 @@ private: class BinomialCoefficient final : public Expression { public: BinomialCoefficient(const BinomialCoefficientNode * n) : Expression(n) {} - static BinomialCoefficient Builder(Expression child0, Expression child1); + static BinomialCoefficient Builder(Expression child0, Expression child1) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1).array(), 2); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("binomial", 2, &UntypedBuilderTwoChildren); // Expression diff --git a/poincare/include/poincare/binomial_coefficient_layout.h b/poincare/include/poincare/binomial_coefficient_layout.h index b094b5b53..2187496ce 100644 --- a/poincare/include/poincare/binomial_coefficient_layout.h +++ b/poincare/include/poincare/binomial_coefficient_layout.h @@ -43,7 +43,7 @@ private: class BinomialCoefficientLayout final : public Layout { public: - static BinomialCoefficientLayout Builder(Layout n, Layout k); + static BinomialCoefficientLayout Builder(Layout child0, Layout child1) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1).array(), 2); } BinomialCoefficientLayout() = delete; }; diff --git a/poincare/include/poincare/ceiling.h b/poincare/include/poincare/ceiling.h index f8b75112c..a0f9cb615 100644 --- a/poincare/include/poincare/ceiling.h +++ b/poincare/include/poincare/ceiling.h @@ -42,7 +42,7 @@ private: class Ceiling final : public Expression { public: Ceiling(const CeilingNode * n) : Expression(n) {} - static Ceiling Builder(Expression child); + static Ceiling Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("ceil", 1, &UntypedBuilderOneChild); diff --git a/poincare/include/poincare/ceiling_layout.h b/poincare/include/poincare/ceiling_layout.h index 8b06304e7..6a3755175 100644 --- a/poincare/include/poincare/ceiling_layout.h +++ b/poincare/include/poincare/ceiling_layout.h @@ -30,7 +30,7 @@ protected: class CeilingLayout final : public Layout { public: - static CeilingLayout Builder(Layout l); + static CeilingLayout Builder(Layout child) { return TreeHandle::FixedArityBuilder(&child, 1); } CeilingLayout() = delete; }; diff --git a/poincare/include/poincare/complex_argument.h b/poincare/include/poincare/complex_argument.h index bdbcb3c72..b6a9b9fad 100644 --- a/poincare/include/poincare/complex_argument.h +++ b/poincare/include/poincare/complex_argument.h @@ -41,7 +41,7 @@ private: class ComplexArgument final : public Expression { public: ComplexArgument(const ComplexArgumentNode * n) : Expression(n) {} - static ComplexArgument Builder(Expression child); + static ComplexArgument Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("arg", 1, &UntypedBuilderOneChild); diff --git a/poincare/include/poincare/complex_cartesian.h b/poincare/include/poincare/complex_cartesian.h index 4a6db764f..2ac6e865f 100644 --- a/poincare/include/poincare/complex_cartesian.h +++ b/poincare/include/poincare/complex_cartesian.h @@ -38,8 +38,8 @@ class ComplexCartesian final : public Expression { public: ComplexCartesian() : Expression() {} ComplexCartesian(const ComplexCartesianNode * node) : Expression(node) {} - static ComplexCartesian Builder(); - static ComplexCartesian Builder(Expression child0, Expression child1); + static ComplexCartesian Builder() { return TreeHandle::FixedArityBuilder(); } + static ComplexCartesian Builder(Expression child0, Expression child1) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1).array(), 2); } // Getters Expression real() { return childAtIndex(0); } diff --git a/poincare/include/poincare/condensed_sum_layout.h b/poincare/include/poincare/condensed_sum_layout.h index 9c95a20d9..93c8ca9f9 100644 --- a/poincare/include/poincare/condensed_sum_layout.h +++ b/poincare/include/poincare/condensed_sum_layout.h @@ -51,7 +51,7 @@ private: class CondensedSumLayout final : public Layout { public: - static CondensedSumLayout Builder(Layout base, Layout subscript, Layout superscript); + static CondensedSumLayout Builder(Layout base, Layout subscript, Layout superscript) { return TreeHandle::FixedArityBuilder(ArrayBuilder(base, subscript, superscript).array(), 3); } CondensedSumLayout() = delete; }; diff --git a/poincare/include/poincare/confidence_interval.h b/poincare/include/poincare/confidence_interval.h index a030d0998..8f9652b89 100644 --- a/poincare/include/poincare/confidence_interval.h +++ b/poincare/include/poincare/confidence_interval.h @@ -45,7 +45,7 @@ class ConfidenceInterval : public Expression { friend class SimplePredictionInterval; public: ConfidenceInterval(const ConfidenceIntervalNode * n) : Expression(n) {} - static ConfidenceInterval Builder(Expression child0, Expression child1); + static ConfidenceInterval Builder(Expression child0, Expression child1) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1).array(), 2); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("confidence", 2, &UntypedBuilderTwoChildren); // Expression @@ -57,7 +57,7 @@ private: class SimplePredictionInterval final : public ConfidenceInterval { public: SimplePredictionInterval(const SimplePredictionIntervalNode * n) : ConfidenceInterval(n) {} - static SimplePredictionInterval Builder(Expression child0, Expression child1); + static SimplePredictionInterval Builder(Expression child0, Expression child1) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1).array(), 2); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("prediction", 2, &UntypedBuilderTwoChildren); }; diff --git a/poincare/include/poincare/conjugate.h b/poincare/include/poincare/conjugate.h index af45d709b..f2324c1f4 100644 --- a/poincare/include/poincare/conjugate.h +++ b/poincare/include/poincare/conjugate.h @@ -41,7 +41,7 @@ private: class Conjugate final : public Expression { public: Conjugate(const ConjugateNode * n) : Expression(n) {} - static Conjugate Builder(Expression child); + static Conjugate Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("conj", 1, &UntypedBuilderOneChild);; diff --git a/poincare/include/poincare/conjugate_layout.h b/poincare/include/poincare/conjugate_layout.h index fe0bf5ea9..8dabdf3cf 100644 --- a/poincare/include/poincare/conjugate_layout.h +++ b/poincare/include/poincare/conjugate_layout.h @@ -40,7 +40,7 @@ private: class ConjugateLayout final : public Layout { public: - static ConjugateLayout Builder(Layout child); + static ConjugateLayout Builder(Layout child) { return TreeHandle::FixedArityBuilder(&child, 1); } ConjugateLayout() = delete; }; diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index 532abf06f..8617103ee 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -46,7 +46,7 @@ private: class Cosine final : public Expression { public: Cosine(const CosineNode * n) : Expression(n) {} - static Cosine Builder(Expression child); + static Cosine Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("cos", 1, &UntypedBuilderOneChild); diff --git a/poincare/include/poincare/derivative.h b/poincare/include/poincare/derivative.h index e2bd29ad1..b4a76a19b 100644 --- a/poincare/include/poincare/derivative.h +++ b/poincare/include/poincare/derivative.h @@ -51,15 +51,8 @@ private: class Derivative final : public Expression { public: Derivative(const DerivativeNode * n) : Expression(n) {} - static Derivative Builder(Expression child0, Symbol child1, Expression child2); - static Expression UntypedBuilder(Expression children) { - assert(children.type() == ExpressionNode::Type::Matrix); - if (children.childAtIndex(1).type() != ExpressionNode::Type::Symbol) { - // Second parameter must be a Symbol. - return Expression(); - } - return Builder(children.childAtIndex(0), children.childAtIndex(1).convert(), children.childAtIndex(2)); - } + static Derivative Builder(Expression child0, Symbol child1, Expression child2) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1, child2).array(), 3); } + static Expression UntypedBuilder(Expression children); static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("diff", 3, &UntypedBuilder); Expression shallowReduce(); diff --git a/poincare/include/poincare/determinant.h b/poincare/include/poincare/determinant.h index d4a392d76..e80c2ceb3 100644 --- a/poincare/include/poincare/determinant.h +++ b/poincare/include/poincare/determinant.h @@ -35,7 +35,7 @@ private: class Determinant final : public Expression { public: Determinant(const DeterminantNode * n) : Expression(n) {} - static Determinant Builder(Expression child); + static Determinant Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("det", 1, &UntypedBuilderOneChild); diff --git a/poincare/include/poincare/division.h b/poincare/include/poincare/division.h index c1bf207b5..e73617d7c 100644 --- a/poincare/include/poincare/division.h +++ b/poincare/include/poincare/division.h @@ -61,8 +61,8 @@ private: class Division final : public Expression { public: Division(const DivisionNode * n) : Expression(n) {} - static Division Builder(); - static Division Builder(Expression numerator, Expression denominator); + static Division Builder() { return TreeHandle::FixedArityBuilder(); } + static Division Builder(Expression numerator, Expression denominator) { return TreeHandle::FixedArityBuilder(ArrayBuilder(numerator, denominator).array(), 2); } Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); }; diff --git a/poincare/include/poincare/division_quotient.h b/poincare/include/poincare/division_quotient.h index e74f8c8a3..f68c03b81 100644 --- a/poincare/include/poincare/division_quotient.h +++ b/poincare/include/poincare/division_quotient.h @@ -38,7 +38,7 @@ private: class DivisionQuotient final : public Expression { public: DivisionQuotient(const DivisionQuotientNode * n) : Expression(n) {} - static DivisionQuotient Builder(Expression child0, Expression child1); + static DivisionQuotient Builder(Expression child0, Expression child1) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1).array(), 2); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("quo", 2, &UntypedBuilderTwoChildren); // Expression diff --git a/poincare/include/poincare/division_remainder.h b/poincare/include/poincare/division_remainder.h index 9a4033005..9089fa60a 100644 --- a/poincare/include/poincare/division_remainder.h +++ b/poincare/include/poincare/division_remainder.h @@ -39,7 +39,7 @@ private: class DivisionRemainder final : public Expression { public: DivisionRemainder(const DivisionRemainderNode * n) : Expression(n) {} - static DivisionRemainder Builder(Expression child0, Expression child1); + static DivisionRemainder Builder(Expression child0, Expression child1) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1).array(), 2); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("rem", 2, &UntypedBuilderTwoChildren); // Expression diff --git a/poincare/include/poincare/empty_expression.h b/poincare/include/poincare/empty_expression.h index 332430992..80b83ead8 100644 --- a/poincare/include/poincare/empty_expression.h +++ b/poincare/include/poincare/empty_expression.h @@ -33,7 +33,7 @@ private: class EmptyExpression final : public Expression { public: - static EmptyExpression Builder(); + static EmptyExpression Builder() { return TreeHandle::FixedArityBuilder(); } EmptyExpression(const EmptyExpressionNode * n) : Expression(n) {} }; diff --git a/poincare/include/poincare/equal.h b/poincare/include/poincare/equal.h index e191b12ba..7a7b87303 100644 --- a/poincare/include/poincare/equal.h +++ b/poincare/include/poincare/equal.h @@ -35,7 +35,7 @@ private: class Equal final : public Expression { public: Equal(const EqualNode * n) : Expression(n) {} - static Equal Builder(Expression child0, Expression child1); + static Equal Builder(Expression child0, Expression child1) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1).array(), 2); } // For the equation A = B, create the reduced expression A-B Expression standardEquation(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index b250a00cb..e5c20b901 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -1,6 +1,7 @@ #ifndef POINCARE_EXPRESSION_REFERENCE_H #define POINCARE_EXPRESSION_REFERENCE_H +#include #include #include #include diff --git a/poincare/include/poincare/factor.h b/poincare/include/poincare/factor.h index 84d300a5d..8ca451238 100644 --- a/poincare/include/poincare/factor.h +++ b/poincare/include/poincare/factor.h @@ -37,7 +37,7 @@ private: class Factor final : public Expression { public: Factor(const FactorNode * n) : Expression(n) {} - static Factor Builder(Expression child); + static Factor Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("factor", 1, &UntypedBuilderOneChild); diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index c76129c69..2ea2ddb59 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -52,8 +52,7 @@ private: class Factorial final : public Expression { public: Factorial(const FactorialNode * n) : Expression(n) {} - static Factorial Builder(); - static Factorial Builder(Expression child); + static Factorial Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } Expression shallowReduce(); Expression shallowBeautify(); diff --git a/poincare/include/poincare/floor.h b/poincare/include/poincare/floor.h index c1c7736ee..a7a06be5a 100644 --- a/poincare/include/poincare/floor.h +++ b/poincare/include/poincare/floor.h @@ -44,7 +44,7 @@ private: class Floor final : public Expression { public: Floor(const FloorNode * n) : Expression(n) {} - static Floor Builder(Expression child); + static Floor Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("floor", 1, &UntypedBuilderOneChild); diff --git a/poincare/include/poincare/floor_layout.h b/poincare/include/poincare/floor_layout.h index 77ee2b986..0e560a917 100644 --- a/poincare/include/poincare/floor_layout.h +++ b/poincare/include/poincare/floor_layout.h @@ -29,7 +29,7 @@ protected: class FloorLayout final : public Layout { public: - static FloorLayout Builder(Layout child); + static FloorLayout Builder(Layout child) { return TreeHandle::FixedArityBuilder(&child, 1); } FloorLayout() = delete; }; diff --git a/poincare/include/poincare/frac_part.h b/poincare/include/poincare/frac_part.h index 3858deeec..d4ea74b51 100644 --- a/poincare/include/poincare/frac_part.h +++ b/poincare/include/poincare/frac_part.h @@ -44,7 +44,7 @@ private: class FracPart final : public Expression { public: FracPart(const FracPartNode * n) : Expression(n) {} - static FracPart Builder(Expression child); + static FracPart Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("frac", 1, &UntypedBuilderOneChild); diff --git a/poincare/include/poincare/fraction_layout.h b/poincare/include/poincare/fraction_layout.h index 17df46c28..03b3979b0 100644 --- a/poincare/include/poincare/fraction_layout.h +++ b/poincare/include/poincare/fraction_layout.h @@ -58,7 +58,7 @@ private: class FractionLayout final : public Layout { public: - static FractionLayout Builder(Layout numerator, Layout denominator); + static FractionLayout Builder(Layout child0, Layout child1) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1).array(), 2); } FractionLayout() = delete; }; diff --git a/poincare/include/poincare/ghost.h b/poincare/include/poincare/ghost.h index da30640df..1c7d3b56c 100644 --- a/poincare/include/poincare/ghost.h +++ b/poincare/include/poincare/ghost.h @@ -12,12 +12,7 @@ namespace Poincare { class Ghost final : public TreeHandle { public: - static Ghost Builder() { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(GhostNode)); - GhostNode * node = new (bufferNode) GhostNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); - return static_cast(h); - } + static Ghost Builder() { return TreeHandle::FixedArityBuilder(); } }; } diff --git a/poincare/include/poincare/great_common_divisor.h b/poincare/include/poincare/great_common_divisor.h index 318b78d93..89ffdb891 100644 --- a/poincare/include/poincare/great_common_divisor.h +++ b/poincare/include/poincare/great_common_divisor.h @@ -37,7 +37,7 @@ private: class GreatCommonDivisor final : public Expression { public: GreatCommonDivisor(const GreatCommonDivisorNode * n) : Expression(n) {} - static GreatCommonDivisor Builder(Expression child0, Expression child1); + static GreatCommonDivisor Builder(Expression child0, Expression child1) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1).array(), 2); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("gcd", 2, &UntypedBuilderTwoChildren); // Expression diff --git a/poincare/include/poincare/grid_layout.h b/poincare/include/poincare/grid_layout.h index 9510c75f9..d6f8f8f70 100644 --- a/poincare/include/poincare/grid_layout.h +++ b/poincare/include/poincare/grid_layout.h @@ -89,7 +89,8 @@ private: class GridLayout : public Layout { public: GridLayout(const GridLayoutNode * n) : Layout(n) {} - static GridLayout Builder(); + static GridLayout Builder() { return TreeHandle::NAryBuilder(); } + void setDimensions(int rows, int columns); void addChildAtIndex(Layout l, int index, int currentNumberOfChildren, LayoutCursor * cursor) { Layout::addChildAtIndex(l, index, currentNumberOfChildren, cursor); diff --git a/poincare/include/poincare/horizontal_layout.h b/poincare/include/poincare/horizontal_layout.h index 2b39ecd29..6f11a7b78 100644 --- a/poincare/include/poincare/horizontal_layout.h +++ b/poincare/include/poincare/horizontal_layout.h @@ -1,7 +1,6 @@ #ifndef POINCARE_HORIZONTAL_LAYOUT_NODE_H #define POINCARE_HORIZONTAL_LAYOUT_NODE_H -#include #include #include @@ -68,18 +67,12 @@ class HorizontalLayout final : public Layout { public: // Constructors HorizontalLayout(HorizontalLayoutNode * n) : Layout(n) {} - static HorizontalLayout Builder(); + static HorizontalLayout Builder() { return TreeHandle::NAryBuilder(); } static HorizontalLayout Builder(Layout l) { return HorizontalLayout::Builder(&l, 1); } static HorizontalLayout Builder(Layout l1, Layout l2) { return HorizontalLayout::Builder(ArrayBuilder(l1, l2).array(), 2); } static HorizontalLayout Builder(Layout l1, Layout l2, Layout l3) { return HorizontalLayout::Builder(ArrayBuilder(l1, l2, l3).array(), 3); } static HorizontalLayout Builder(Layout l1, Layout l2, Layout l3, Layout l4) { return HorizontalLayout::Builder(ArrayBuilder(l1, l2, l3, l4).array(), 4); } - static HorizontalLayout Builder(const Layout * children, size_t numberOfChildren) { - HorizontalLayout h = HorizontalLayout::Builder(); - for (size_t i = 0; i < numberOfChildren; i++) { - h.addChildAtIndexInPlace(children[i], i, i); - } - return h; - } + static HorizontalLayout Builder(Layout * children, size_t numberOfChildren) { return TreeHandle::NAryBuilder(static_cast(children), numberOfChildren); } void addChildAtIndex(Layout l, int index, int currentNumberOfChildren, LayoutCursor * cursor, bool removeEmptyChildren = false); // Remove puts a child at the end of the pool diff --git a/poincare/include/poincare/hyperbolic_arc_cosine.h b/poincare/include/poincare/hyperbolic_arc_cosine.h index 3ebeccbd8..59f6e725f 100644 --- a/poincare/include/poincare/hyperbolic_arc_cosine.h +++ b/poincare/include/poincare/hyperbolic_arc_cosine.h @@ -36,7 +36,7 @@ private: class HyperbolicArcCosine final : public HyperbolicTrigonometricFunction { public: HyperbolicArcCosine(const HyperbolicArcCosineNode * n) : HyperbolicTrigonometricFunction(n) {} - static HyperbolicArcCosine Builder(Expression child); + static HyperbolicArcCosine Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("acosh", 1, &UntypedBuilderOneChild); }; diff --git a/poincare/include/poincare/hyperbolic_arc_sine.h b/poincare/include/poincare/hyperbolic_arc_sine.h index 464235abe..5f8b4d4b7 100644 --- a/poincare/include/poincare/hyperbolic_arc_sine.h +++ b/poincare/include/poincare/hyperbolic_arc_sine.h @@ -36,7 +36,7 @@ private: class HyperbolicArcSine final : public HyperbolicTrigonometricFunction { public: HyperbolicArcSine(const HyperbolicArcSineNode * n) : HyperbolicTrigonometricFunction(n) {} - static HyperbolicArcSine Builder(Expression child); + static HyperbolicArcSine Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("asinh", 1, &UntypedBuilderOneChild); }; diff --git a/poincare/include/poincare/hyperbolic_arc_tangent.h b/poincare/include/poincare/hyperbolic_arc_tangent.h index 16b08b342..2244efbf5 100644 --- a/poincare/include/poincare/hyperbolic_arc_tangent.h +++ b/poincare/include/poincare/hyperbolic_arc_tangent.h @@ -36,7 +36,7 @@ private: class HyperbolicArcTangent final : public HyperbolicTrigonometricFunction { public: HyperbolicArcTangent(const HyperbolicArcTangentNode * n) : HyperbolicTrigonometricFunction(n) {} - static HyperbolicArcTangent Builder(Expression child); + static HyperbolicArcTangent Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("atanh", 1, &UntypedBuilderOneChild); }; diff --git a/poincare/include/poincare/hyperbolic_cosine.h b/poincare/include/poincare/hyperbolic_cosine.h index 2704a87a0..67ab4cf80 100644 --- a/poincare/include/poincare/hyperbolic_cosine.h +++ b/poincare/include/poincare/hyperbolic_cosine.h @@ -36,7 +36,7 @@ private: class HyperbolicCosine final : public HyperbolicTrigonometricFunction { public: HyperbolicCosine(const HyperbolicCosineNode * n) : HyperbolicTrigonometricFunction(n) {} - static HyperbolicCosine Builder(Expression child); + static HyperbolicCosine Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("cosh", 1, &UntypedBuilderOneChild); }; diff --git a/poincare/include/poincare/hyperbolic_sine.h b/poincare/include/poincare/hyperbolic_sine.h index 8aeadd16e..6686b4647 100644 --- a/poincare/include/poincare/hyperbolic_sine.h +++ b/poincare/include/poincare/hyperbolic_sine.h @@ -36,7 +36,7 @@ private: class HyperbolicSine final : public HyperbolicTrigonometricFunction { public: HyperbolicSine(const HyperbolicSineNode * n) : HyperbolicTrigonometricFunction(n) {} - static HyperbolicSine Builder(Expression child); + static HyperbolicSine Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("sinh", 1, &UntypedBuilderOneChild); }; diff --git a/poincare/include/poincare/hyperbolic_tangent.h b/poincare/include/poincare/hyperbolic_tangent.h index 321f5581e..ba6ec8693 100644 --- a/poincare/include/poincare/hyperbolic_tangent.h +++ b/poincare/include/poincare/hyperbolic_tangent.h @@ -36,7 +36,7 @@ private: class HyperbolicTangent final : public HyperbolicTrigonometricFunction { public: HyperbolicTangent(const HyperbolicTangentNode * n) : HyperbolicTrigonometricFunction(n) {} - static HyperbolicTangent Builder(Expression child); + static HyperbolicTangent Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("tanh", 1, &UntypedBuilderOneChild); }; diff --git a/poincare/include/poincare/imaginary_part.h b/poincare/include/poincare/imaginary_part.h index 882d9ebfa..c26367424 100644 --- a/poincare/include/poincare/imaginary_part.h +++ b/poincare/include/poincare/imaginary_part.h @@ -45,7 +45,7 @@ private: class ImaginaryPart final : public Expression { public: ImaginaryPart(const ImaginaryPartNode * n) : Expression(n) {} - static ImaginaryPart Builder(Expression child); + static ImaginaryPart Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("im", 1, &UntypedBuilderOneChild); diff --git a/poincare/include/poincare/integral.h b/poincare/include/poincare/integral.h index 1ebefe772..241521fc2 100644 --- a/poincare/include/poincare/integral.h +++ b/poincare/include/poincare/integral.h @@ -55,15 +55,9 @@ private: class Integral final : public Expression { public: Integral(const IntegralNode * n) : Expression(n) {} - static Integral Builder(Expression child0, Symbol child1, Expression child2, Expression child3); - static Expression UntypedBuilder(Expression children) { - assert(children.type() == ExpressionNode::Type::Matrix); - if (children.childAtIndex(1).type() != ExpressionNode::Type::Symbol) { - // Second parameter must be a Symbol. - return Expression(); - } - return Builder(children.childAtIndex(0), children.childAtIndex(1).convert(), children.childAtIndex(2), children.childAtIndex(3)); - } + static Integral Builder(Expression child0, Symbol child1, Expression child2, Expression child3) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1, child2, child3).array(), 4); } + static Expression UntypedBuilder(Expression children); + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("int", 4, &UntypedBuilder); // Expression diff --git a/poincare/include/poincare/integral_layout.h b/poincare/include/poincare/integral_layout.h index 79f6e8a73..30b8901cf 100644 --- a/poincare/include/poincare/integral_layout.h +++ b/poincare/include/poincare/integral_layout.h @@ -56,7 +56,7 @@ private: class IntegralLayout final : public Layout { public: - static IntegralLayout Builder(Layout integrand, Layout differential, Layout lowerBound, Layout upperBound); + static IntegralLayout Builder(Layout integrand, Layout differential, Layout lowerBound, Layout upperBound) { return TreeHandle::FixedArityBuilder(ArrayBuilder(integrand, differential, lowerBound, upperBound).array(), 4); } IntegralLayout() = delete; }; diff --git a/poincare/include/poincare/layout.h b/poincare/include/poincare/layout.h index 53d3dda14..2dfffdcd9 100644 --- a/poincare/include/poincare/layout.h +++ b/poincare/include/poincare/layout.h @@ -1,6 +1,7 @@ #ifndef POINCARE_LAYOUT_REFERENCE_H #define POINCARE_LAYOUT_REFERENCE_H +#include #include #include diff --git a/poincare/include/poincare/least_common_multiple.h b/poincare/include/poincare/least_common_multiple.h index 0155895b5..1fc06b42a 100644 --- a/poincare/include/poincare/least_common_multiple.h +++ b/poincare/include/poincare/least_common_multiple.h @@ -37,7 +37,7 @@ private: class LeastCommonMultiple final : public Expression { public: LeastCommonMultiple(const LeastCommonMultipleNode * n) : Expression(n) {} - static LeastCommonMultiple Builder(Expression child0, Expression child1); + static LeastCommonMultiple Builder(Expression child0, Expression child1) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1).array(), 2); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("lcm", 2, &UntypedBuilderTwoChildren); // Expression diff --git a/poincare/include/poincare/left_parenthesis_layout.h b/poincare/include/poincare/left_parenthesis_layout.h index 66f52047b..ffc0fe6df 100644 --- a/poincare/include/poincare/left_parenthesis_layout.h +++ b/poincare/include/poincare/left_parenthesis_layout.h @@ -35,7 +35,7 @@ protected: class LeftParenthesisLayout final : public Layout { public: - static LeftParenthesisLayout Builder(); + static LeftParenthesisLayout Builder() { return TreeHandle::FixedArityBuilder(); } LeftParenthesisLayout() = delete; }; diff --git a/poincare/include/poincare/left_square_bracket_layout.h b/poincare/include/poincare/left_square_bracket_layout.h index 558e69e3b..00720398a 100644 --- a/poincare/include/poincare/left_square_bracket_layout.h +++ b/poincare/include/poincare/left_square_bracket_layout.h @@ -29,7 +29,7 @@ protected: class LeftSquareBracketLayout final : public Layout { public: - static LeftSquareBracketLayout Builder(); + static LeftSquareBracketLayout Builder() { return TreeHandle::FixedArityBuilder(); } LeftSquareBracketLayout() = delete; }; diff --git a/poincare/include/poincare/logarithm.h b/poincare/include/poincare/logarithm.h index eede67cea..0826fe76e 100644 --- a/poincare/include/poincare/logarithm.h +++ b/poincare/include/poincare/logarithm.h @@ -44,7 +44,7 @@ public: class Logarithm final : public Expression { public: Logarithm(const LogarithmNode<2> * n) : Expression(n) {} - static Logarithm Builder(Expression child0, Expression child1); + static Logarithm Builder(Expression child0, Expression child1) { return TreeHandle::FixedArityBuilder>(ArrayBuilder(child0, child1).array(), 2); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("log", 2, &UntypedBuilderTwoChildren); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); @@ -60,7 +60,7 @@ private: class CommonLogarithm : public Expression { public: CommonLogarithm(const LogarithmNode<1> * n) : Expression(n) {} - static CommonLogarithm Builder(Expression child); + static CommonLogarithm Builder(Expression child) { return TreeHandle::FixedArityBuilder>(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("log", 1, &UntypedBuilderOneChild); diff --git a/poincare/include/poincare/matrix.h b/poincare/include/poincare/matrix.h index 790d7b556..96188ed5a 100644 --- a/poincare/include/poincare/matrix.h +++ b/poincare/include/poincare/matrix.h @@ -63,7 +63,7 @@ class Matrix final : public Expression { friend class GlobalContext; public: Matrix(const MatrixNode * node) : Expression(node) {} - static Matrix Builder(); + static Matrix Builder() { return TreeHandle::NAryBuilder(); } void setDimensions(int rows, int columns); int numberOfRows() const { return node()->numberOfRows(); } diff --git a/poincare/include/poincare/matrix_complex.h b/poincare/include/poincare/matrix_complex.h index 73a750a88..2566b1d44 100644 --- a/poincare/include/poincare/matrix_complex.h +++ b/poincare/include/poincare/matrix_complex.h @@ -57,7 +57,7 @@ class MatrixComplex final : public Evaluation { friend class MatrixComplexNode; public: MatrixComplex(MatrixComplexNode * node) : Evaluation(node) {} - static MatrixComplex Builder(); + static MatrixComplex Builder() { return TreeHandle::NAryBuilder, MatrixComplexNode>(); } static MatrixComplex Builder(std::complex * operands, int numberOfRows, int numberOfColumns); static MatrixComplex Undefined(); static MatrixComplex createIdentity(int dim); diff --git a/poincare/include/poincare/matrix_dimension.h b/poincare/include/poincare/matrix_dimension.h index 99dab0e30..ec1aa0663 100644 --- a/poincare/include/poincare/matrix_dimension.h +++ b/poincare/include/poincare/matrix_dimension.h @@ -35,7 +35,7 @@ private: class MatrixDimension final : public Expression { public: MatrixDimension(const MatrixDimensionNode * n) : Expression(n) {} - static MatrixDimension Builder(Expression child); + static MatrixDimension Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("dim", 1, &UntypedBuilderOneChild); diff --git a/poincare/include/poincare/matrix_inverse.h b/poincare/include/poincare/matrix_inverse.h index ea3ca6ce2..cd551cf21 100644 --- a/poincare/include/poincare/matrix_inverse.h +++ b/poincare/include/poincare/matrix_inverse.h @@ -34,7 +34,7 @@ private: class MatrixInverse final : public Expression { public: MatrixInverse(const MatrixInverseNode * n) : Expression(n) {} - static MatrixInverse Builder(Expression child); + static MatrixInverse Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("inverse", 1, &UntypedBuilderOneChild); diff --git a/poincare/include/poincare/matrix_layout.h b/poincare/include/poincare/matrix_layout.h index 519c6c585..21cf04985 100644 --- a/poincare/include/poincare/matrix_layout.h +++ b/poincare/include/poincare/matrix_layout.h @@ -58,16 +58,8 @@ class MatrixLayout /*final*/ : public GridLayout { friend class MatrixLayoutNode; public: MatrixLayout(const MatrixLayoutNode * n) : GridLayout(n) {} - static MatrixLayout Builder(); - static MatrixLayout Builder(Layout l1, Layout l2, Layout l3, Layout l4) { - MatrixLayout m = MatrixLayout::Builder(); - m.addChildAtIndexInPlace(l1, 0, 0); - m.addChildAtIndexInPlace(l2, 1, 1); - m.addChildAtIndexInPlace(l3, 2, 2); - m.addChildAtIndexInPlace(l4, 3, 3); - m.setDimensions(2, 2); - return m; - } + static MatrixLayout Builder() { return TreeHandle::NAryBuilder(); } + static MatrixLayout Builder(Layout l1, Layout l2, Layout l3, Layout l4); bool hasGreySquares() const { return node()->hasGreySquares(); } void addGreySquares() { node()->addGreySquares(); } diff --git a/poincare/include/poincare/matrix_trace.h b/poincare/include/poincare/matrix_trace.h index 9f729a09c..2192d36c9 100644 --- a/poincare/include/poincare/matrix_trace.h +++ b/poincare/include/poincare/matrix_trace.h @@ -34,7 +34,7 @@ private: class MatrixTrace final : public Expression { public: MatrixTrace(const MatrixTraceNode * n) : Expression(n) {} - static MatrixTrace Builder(Expression child); + static MatrixTrace Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("trace", 1, &UntypedBuilderOneChild); diff --git a/poincare/include/poincare/matrix_transpose.h b/poincare/include/poincare/matrix_transpose.h index 9f5951d9d..25e35102d 100644 --- a/poincare/include/poincare/matrix_transpose.h +++ b/poincare/include/poincare/matrix_transpose.h @@ -34,7 +34,7 @@ private: class MatrixTranspose final : public Expression { public: MatrixTranspose(const MatrixTransposeNode * n) : Expression(n) {} - static MatrixTranspose Builder(Expression child); + static MatrixTranspose Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("transpose", 1, &UntypedBuilderOneChild); diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 9b4dba610..e2a191c6f 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -2,7 +2,6 @@ #define POINCARE_MULTIPLICATION_H #include -#include #include namespace Poincare { @@ -67,7 +66,7 @@ class Multiplication final : public NAryExpression { friend class Power; public: Multiplication(const MultiplicationNode * n) : NAryExpression(n) {} - static Multiplication Builder(); + static Multiplication Builder() { return TreeHandle::NAryBuilder(); } static Multiplication Builder(Expression e1) { return Multiplication::Builder(&e1, 1); } static Multiplication Builder(Expression e1, Expression e2) { return Multiplication::Builder(ArrayBuilder(e1, e2).array(), 2); } static Multiplication Builder(Expression e1, Expression e2, Expression e3) { return Multiplication::Builder(ArrayBuilder(e1, e2, e3).array(), 3); } @@ -81,7 +80,7 @@ public: Expression denominator(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; private: // Constructors - static Multiplication Builder(Expression * children, size_t numberOfChildren); + static Multiplication Builder(Expression * children, size_t numberOfChildren) { return TreeHandle::NAryBuilder(children, numberOfChildren); } // Simplification Expression privateShallowReduce(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target, bool expand, bool canBeInterrupted); diff --git a/poincare/include/poincare/naperian_logarithm.h b/poincare/include/poincare/naperian_logarithm.h index 712b85f27..acb96931d 100644 --- a/poincare/include/poincare/naperian_logarithm.h +++ b/poincare/include/poincare/naperian_logarithm.h @@ -44,7 +44,7 @@ private: class NaperianLogarithm final : public Expression { public: NaperianLogarithm(const NaperianLogarithmNode * n) : Expression(n) {} - static NaperianLogarithm Builder(Expression child); + static NaperianLogarithm Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("ln", 1, &UntypedBuilderOneChild); diff --git a/poincare/include/poincare/nth_root.h b/poincare/include/poincare/nth_root.h index f0d637622..a043a7e2c 100644 --- a/poincare/include/poincare/nth_root.h +++ b/poincare/include/poincare/nth_root.h @@ -35,7 +35,7 @@ private: class NthRoot final : public Expression { public: NthRoot(const NthRootNode * n) : Expression(n) {} - static NthRoot Builder(Expression child0, Expression child1); + static NthRoot Builder(Expression child0, Expression child1) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1).array(), 2); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("root", 2, &UntypedBuilderTwoChildren); Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); diff --git a/poincare/include/poincare/opposite.h b/poincare/include/poincare/opposite.h index 424486585..40bbdd5a1 100644 --- a/poincare/include/poincare/opposite.h +++ b/poincare/include/poincare/opposite.h @@ -47,8 +47,8 @@ public: class Opposite final : public Expression { public: Opposite(const OppositeNode * n) : Expression(n) {} - static Opposite Builder(); - static Opposite Builder(Expression child); + static Opposite Builder() { return TreeHandle::FixedArityBuilder(); } + static Opposite Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); }; diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index ba8b2197e..bf1aa5c23 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -38,7 +38,7 @@ private: class Parenthesis final : public Expression { public: Parenthesis(const ParenthesisNode * n) : Expression(n) {} - static Parenthesis Builder(Expression child); + static Parenthesis Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } // Expression Expression shallowReduce(); }; diff --git a/poincare/include/poincare/permute_coefficient.h b/poincare/include/poincare/permute_coefficient.h index 8ec9da24a..f80b81096 100644 --- a/poincare/include/poincare/permute_coefficient.h +++ b/poincare/include/poincare/permute_coefficient.h @@ -41,7 +41,7 @@ private: class PermuteCoefficient final : public Expression { public: PermuteCoefficient(const PermuteCoefficientNode * n) : Expression(n) {} - static PermuteCoefficient Builder(Expression child0, Expression child1); + static PermuteCoefficient Builder(Expression child0, Expression child1) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1).array(), 2); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("permute", 2, &UntypedBuilderTwoChildren); // Expression diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 2c30a77ff..3799bec05 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -67,7 +67,7 @@ class Power final : public Expression { friend class Round; public: Power(const PowerNode * n) : Expression(n) {} - static Power Builder(Expression base, Expression exponent); + static Power Builder(Expression base, Expression exponent) { return TreeHandle::FixedArityBuilder(ArrayBuilder(base, exponent).array(), 2); } Expression setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); int getPolynomialCoefficients(Context & context, const char * symbolName, Expression coefficients[]) const; diff --git a/poincare/include/poincare/prediction_interval.h b/poincare/include/poincare/prediction_interval.h index 69da94c98..a664cfcea 100644 --- a/poincare/include/poincare/prediction_interval.h +++ b/poincare/include/poincare/prediction_interval.h @@ -37,7 +37,7 @@ private: class PredictionInterval final : public Expression { public: PredictionInterval(const PredictionIntervalNode * n) : Expression(n) {} - static PredictionInterval Builder(Expression child0, Expression child1); + static PredictionInterval Builder(Expression child0, Expression child1) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1).array(), 2); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("prediction95", 2, &UntypedBuilderTwoChildren); // Expression diff --git a/poincare/include/poincare/product.h b/poincare/include/poincare/product.h index 9a37e7868..c9dbaeb66 100644 --- a/poincare/include/poincare/product.h +++ b/poincare/include/poincare/product.h @@ -35,15 +35,9 @@ class Product final : public Expression { friend class ProductNode; public: Product(const ProductNode * n) : Expression(n) {} - static Product Builder(Expression child0, Symbol child1, Expression child2, Expression child3); - static Expression UntypedBuilder(Expression children) { - assert(children.type() == ExpressionNode::Type::Matrix); - if (children.childAtIndex(1).type() != ExpressionNode::Type::Symbol) { - // Second parameter must be a Symbol. - return Expression(); - } - return Builder(children.childAtIndex(0), children.childAtIndex(1).convert(), children.childAtIndex(2), children.childAtIndex(3)); - } + static Product Builder(Expression child0, Symbol child1, Expression child2, Expression child3) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1, child2, child3).array(), 4); } + static Expression UntypedBuilder(Expression children); + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("product", 4, &UntypedBuilder); }; diff --git a/poincare/include/poincare/product_layout.h b/poincare/include/poincare/product_layout.h index eeb28ec79..3ea063232 100644 --- a/poincare/include/poincare/product_layout.h +++ b/poincare/include/poincare/product_layout.h @@ -25,7 +25,7 @@ private: class ProductLayout final : public Layout { public: - static ProductLayout Builder(Layout argument, Layout variable, Layout lowerB, Layout upperB); + static ProductLayout Builder(Layout argument, Layout variable, Layout lowerB, Layout upperB) { return TreeHandle::FixedArityBuilder(ArrayBuilder(argument, variable, lowerB, upperB).array(), 4); } ProductLayout() = delete; }; diff --git a/poincare/include/poincare/randint.h b/poincare/include/poincare/randint.h index 292dc33cd..6d1b93516 100644 --- a/poincare/include/poincare/randint.h +++ b/poincare/include/poincare/randint.h @@ -41,7 +41,7 @@ class Randint final : public Expression { friend class RandintNode; public: Randint(const RandintNode * n) : Expression(n) {} - static Randint Builder(Expression child0, Expression child1); + static Randint Builder(Expression child0, Expression child1) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1).array(), 2); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("randint", 2, &UntypedBuilderTwoChildren); }; diff --git a/poincare/include/poincare/random.h b/poincare/include/poincare/random.h index 0446a25f9..b1982bceb 100644 --- a/poincare/include/poincare/random.h +++ b/poincare/include/poincare/random.h @@ -43,7 +43,7 @@ class Random final : public Expression { friend class RandomNode; public: Random(const RandomNode * n) : Expression(n) {} - static Random Builder(); + static Random Builder() { return TreeHandle::FixedArityBuilder(); } static Expression UntypedBuilder(Expression children) { assert(children.type() == ExpressionNode::Type::Matrix); return Builder(); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("random", 0, &UntypedBuilder); diff --git a/poincare/include/poincare/real_part.h b/poincare/include/poincare/real_part.h index 79b9cfd38..eefdc61eb 100644 --- a/poincare/include/poincare/real_part.h +++ b/poincare/include/poincare/real_part.h @@ -45,7 +45,7 @@ private: class RealPart final : public Expression { public: RealPart(const RealPartNode * n) : Expression(n) {} - static RealPart Builder(Expression child); + static RealPart Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("re", 1, &UntypedBuilderOneChild); diff --git a/poincare/include/poincare/right_parenthesis_layout.h b/poincare/include/poincare/right_parenthesis_layout.h index 779039803..2f3f03d9f 100644 --- a/poincare/include/poincare/right_parenthesis_layout.h +++ b/poincare/include/poincare/right_parenthesis_layout.h @@ -36,7 +36,7 @@ protected: class RightParenthesisLayout final : public Layout { public: - static RightParenthesisLayout Builder(); + static RightParenthesisLayout Builder() { return TreeHandle::FixedArityBuilder(); } RightParenthesisLayout() = delete; }; diff --git a/poincare/include/poincare/right_square_bracket_layout.h b/poincare/include/poincare/right_square_bracket_layout.h index 8c7ff1332..161ade869 100644 --- a/poincare/include/poincare/right_square_bracket_layout.h +++ b/poincare/include/poincare/right_square_bracket_layout.h @@ -29,7 +29,7 @@ protected: class RightSquareBracketLayout final : public Layout { public: - static RightSquareBracketLayout Builder(); + static RightSquareBracketLayout Builder() { return TreeHandle::FixedArityBuilder(); } RightSquareBracketLayout() = delete; }; diff --git a/poincare/include/poincare/round.h b/poincare/include/poincare/round.h index 2fc0075b6..f08c6ee41 100644 --- a/poincare/include/poincare/round.h +++ b/poincare/include/poincare/round.h @@ -38,7 +38,7 @@ private: class Round final : public Expression { public: Round(const RoundNode * n) : Expression(n) {} - static Round Builder(Expression child0, Expression child1); + static Round Builder(Expression child0, Expression child1) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1).array(), 2); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("round", 2, &UntypedBuilderTwoChildren); Expression shallowReduce(); diff --git a/poincare/include/poincare/sign_function.h b/poincare/include/poincare/sign_function.h index 2a4889e45..23d197933 100644 --- a/poincare/include/poincare/sign_function.h +++ b/poincare/include/poincare/sign_function.h @@ -45,7 +45,7 @@ private: class SignFunction final : public Expression { public: SignFunction(const SignFunctionNode * n) : Expression(n) {} - static SignFunction Builder(Expression child); + static SignFunction Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("sign", 1, &UntypedBuilderOneChild); diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index 75d65d604..5137f0b5f 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -48,7 +48,7 @@ private: class Sine final : public Expression { public: Sine(const SineNode * n) : Expression(n) {} - static Sine Builder(Expression child); + static Sine Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("sin", 1, &UntypedBuilderOneChild); diff --git a/poincare/include/poincare/square_root.h b/poincare/include/poincare/square_root.h index bf9629e62..4ea8737d1 100644 --- a/poincare/include/poincare/square_root.h +++ b/poincare/include/poincare/square_root.h @@ -41,7 +41,7 @@ private: class SquareRoot final : public Expression { public: SquareRoot(const SquareRootNode * n) : Expression(n) {} - static SquareRoot Builder(Expression child); + static SquareRoot Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static_assert('\x91' == Ion::Charset::Root, "Charset error"); static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("\x91", 1, &UntypedBuilderOneChild); diff --git a/poincare/include/poincare/store.h b/poincare/include/poincare/store.h index e9db5570b..dbedd4df0 100644 --- a/poincare/include/poincare/store.h +++ b/poincare/include/poincare/store.h @@ -40,7 +40,7 @@ class Store final : public Expression { friend class StoreNode; public: Store(const StoreNode * n) : Expression(n) {} - static Store Builder(Expression value, SymbolAbstract symbol); + static Store Builder(Expression value, SymbolAbstract symbol) { return TreeHandle::FixedArityBuilder(ArrayBuilder(value, symbol).array(), 2); } // Store const SymbolAbstract symbol() const { diff --git a/poincare/include/poincare/subtraction.h b/poincare/include/poincare/subtraction.h index 3fd149bcc..9c43f93af 100644 --- a/poincare/include/poincare/subtraction.h +++ b/poincare/include/poincare/subtraction.h @@ -55,8 +55,8 @@ private: class Subtraction final : public Expression { public: Subtraction(const SubtractionNode * n) : Expression(n) {} - static Subtraction Builder(); - static Subtraction Builder(Expression child0, Expression child1); + static Subtraction Builder() { return TreeHandle::FixedArityBuilder(); } + static Subtraction Builder(Expression child0, Expression child1) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1).array(), 2); } // Expression Expression shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); diff --git a/poincare/include/poincare/sum.h b/poincare/include/poincare/sum.h index 503591c84..4256a18c5 100644 --- a/poincare/include/poincare/sum.h +++ b/poincare/include/poincare/sum.h @@ -35,15 +35,9 @@ class Sum final : public Expression { friend class SumNode; public: Sum(const SumNode * n) : Expression(n) {} - static Sum Builder(Expression child0, Symbol child1, Expression child2, Expression child3); - static Expression UntypedBuilder(Expression children) { - assert(children.type() == ExpressionNode::Type::Matrix); - if (children.childAtIndex(1).type() != ExpressionNode::Type::Symbol) { - // Second parameter must be a Symbol. - return Expression(); - } - return Builder(children.childAtIndex(0), children.childAtIndex(1).convert(), children.childAtIndex(2), children.childAtIndex(3)); - } + static Sum Builder(Expression child0, Symbol child1, Expression child2, Expression child3) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1, child2, child3).array(), 4); } + static Expression UntypedBuilder(Expression children); + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("sum", 4, &UntypedBuilder); }; diff --git a/poincare/include/poincare/sum_layout.h b/poincare/include/poincare/sum_layout.h index b7999571e..57c6206db 100644 --- a/poincare/include/poincare/sum_layout.h +++ b/poincare/include/poincare/sum_layout.h @@ -23,7 +23,7 @@ private: class SumLayout final : public Layout { public: - static SumLayout Builder(Layout argument, Layout variable, Layout lowerB, Layout upperB); + static SumLayout Builder(Layout argument, Layout variable, Layout lowerB, Layout upperB) { return TreeHandle::FixedArityBuilder(ArrayBuilder(argument, variable, lowerB, upperB).array(), 4); } SumLayout() = delete; }; diff --git a/poincare/include/poincare/tangent.h b/poincare/include/poincare/tangent.h index ea04dd640..ee1ff3ec4 100644 --- a/poincare/include/poincare/tangent.h +++ b/poincare/include/poincare/tangent.h @@ -46,7 +46,7 @@ private: class Tangent final : public Expression { public: Tangent(const TangentNode * n) : Expression(n) {} - static Tangent Builder(Expression child); + static Tangent Builder(Expression child) { return TreeHandle::FixedArityBuilder(&child, 1); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("tan", 1, &UntypedBuilderOneChild); diff --git a/poincare/include/poincare/tree_handle.h b/poincare/include/poincare/tree_handle.h index 881d95206..5fd9ca72e 100644 --- a/poincare/include/poincare/tree_handle.h +++ b/poincare/include/poincare/tree_handle.h @@ -20,6 +20,8 @@ namespace Poincare { * equivalent to Logarithm l = Logarithm(clone())). */ class TreeHandle { + template + friend class ArrayBuilder; friend class TreeNode; friend class TreePool; public: @@ -108,8 +110,14 @@ protected: node()->retain(); } } + // WARNING: if the children table is the result of a cast, the object downcasted has to be the same size as a TreeHandle. - static TreeHandle BuildWithBasicChildren(TreeNode * node, TreeHandle * children = nullptr, int numberOfChildren = 0); + template + static T NAryBuilder(TreeHandle * children = nullptr, size_t numberOfChildren = 0); + template + static T FixedArityBuilder(TreeHandle * children = nullptr, size_t numberOfChildren = 0); + + static TreeHandle BuildWithGhostChildren(TreeNode * node); void setIdentifierAndRetain(int newId); void setTo(const TreeHandle & tr); @@ -127,6 +135,9 @@ protected: int m_identifier; private: + template + static TreeHandle Builder(); + void detachFromParent(); // Add ghost children on layout construction void buildGhostChildren(); diff --git a/poincare/include/poincare/undefined.h b/poincare/include/poincare/undefined.h index 8891fe236..3413d8bd9 100644 --- a/poincare/include/poincare/undefined.h +++ b/poincare/include/poincare/undefined.h @@ -42,7 +42,7 @@ protected: class Undefined final : public Number { public: Undefined(const UndefinedNode * n) : Number(n) {} - static Undefined Builder(); + static Undefined Builder() { return TreeHandle::FixedArityBuilder(); } static const char * Name() { return "undef"; } diff --git a/poincare/include/poincare/unreal.h b/poincare/include/poincare/unreal.h index 232f3607d..fdc54ac68 100644 --- a/poincare/include/poincare/unreal.h +++ b/poincare/include/poincare/unreal.h @@ -39,7 +39,7 @@ private: class Unreal final : public Number { public: - static Unreal Builder(); + static Unreal Builder() { return TreeHandle::FixedArityBuilder(); } Unreal() = delete; static const char * Name() { return "unreal"; diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 2999aef0f..a1053c10b 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -31,12 +31,6 @@ Expression AbsoluteValueNode::shallowReduce(Context & context, Preferences::Comp return AbsoluteValue(this).shallowReduce(context, complexFormat, angleUnit, target); } -AbsoluteValue AbsoluteValue::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(AbsoluteValueNode)); - AbsoluteValueNode * node = new (bufferNode) AbsoluteValueNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} Expression AbsoluteValue::setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { assert(s == ExpressionNode::Sign::Positive); diff --git a/poincare/src/absolute_value_layout.cpp b/poincare/src/absolute_value_layout.cpp deleted file mode 100644 index 0d445c654..000000000 --- a/poincare/src/absolute_value_layout.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include - -namespace Poincare { - -AbsoluteValueLayout AbsoluteValueLayout::Builder(Layout child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(AbsoluteValueLayoutNode)); - AbsoluteValueLayoutNode * node = new (bufferNode) AbsoluteValueLayoutNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} - -} diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 21a12a206..d9ae3cae6 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -87,21 +87,6 @@ int Addition::getPolynomialCoefficients(Context & context, const char * symbolNa return deg; } -Addition Addition::Builder() { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(AdditionNode)); - AdditionNode * node = new (bufferNode) AdditionNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); - return static_cast(h); -} - -Addition Addition::Builder(Expression * children, size_t numberOfChildren) { - Addition a = Addition::Builder(); - for (size_t i = 0; i < numberOfChildren; i++) { - a.addChildAtIndexInPlace(children[i], i, i); - } - return a; -} - Expression Addition::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { /* Beautifying AdditionNode essentially consists in adding Subtractions if * needed. diff --git a/poincare/src/arc_cosine.cpp b/poincare/src/arc_cosine.cpp index f32d5f6c5..f0895fe00 100644 --- a/poincare/src/arc_cosine.cpp +++ b/poincare/src/arc_cosine.cpp @@ -48,12 +48,6 @@ Complex ArcCosineNode::computeOnComplex(const std::complex c, Preferences: return Complex::Builder(Trigonometry::ConvertRadianToAngleUnit(result, angleUnit)); } -ArcCosine ArcCosine::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(ArcCosineNode)); - ArcCosineNode * node = new (bufferNode) ArcCosineNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} Expression ArcCosine::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { diff --git a/poincare/src/arc_sine.cpp b/poincare/src/arc_sine.cpp index 450c8df5f..eb2fc0d21 100644 --- a/poincare/src/arc_sine.cpp +++ b/poincare/src/arc_sine.cpp @@ -48,12 +48,6 @@ Complex ArcSineNode::computeOnComplex(const std::complex c, Preferences::C return Complex::Builder(Trigonometry::ConvertRadianToAngleUnit(result, angleUnit)); } -ArcSine ArcSine::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(ArcSineNode)); - ArcSineNode * node = new (bufferNode) ArcSineNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} Expression ArcSine::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { diff --git a/poincare/src/arc_tangent.cpp b/poincare/src/arc_tangent.cpp index 71fae7d4c..c63d9c7f6 100644 --- a/poincare/src/arc_tangent.cpp +++ b/poincare/src/arc_tangent.cpp @@ -48,12 +48,6 @@ Expression ArcTangentNode::shallowReduce(Context & context, Preferences::Complex return ArcTangent(this).shallowReduce(context, complexFormat, angleUnit, target); } -ArcTangent ArcTangent::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(ArcTangentNode)); - ArcTangentNode * node = new (bufferNode) ArcTangentNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} Expression ArcTangent::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { diff --git a/poincare/src/binomial_coefficient.cpp b/poincare/src/binomial_coefficient.cpp index 5a039966d..0c77913ff 100644 --- a/poincare/src/binomial_coefficient.cpp +++ b/poincare/src/binomial_coefficient.cpp @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -54,12 +53,6 @@ T BinomialCoefficientNode::compute(T k, T n) { return std::round(result); } -BinomialCoefficient BinomialCoefficient::Builder(Expression child0, Expression child1) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(BinomialCoefficientNode)); - BinomialCoefficientNode * node = new (bufferNode) BinomialCoefficientNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); - return static_cast(h); -} Expression BinomialCoefficient::shallowReduce() { { diff --git a/poincare/src/binomial_coefficient_layout.cpp b/poincare/src/binomial_coefficient_layout.cpp index dc7b95788..410861766 100644 --- a/poincare/src/binomial_coefficient_layout.cpp +++ b/poincare/src/binomial_coefficient_layout.cpp @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -107,11 +106,4 @@ void BinomialCoefficientLayoutNode::render(KDContext * ctx, KDPoint p, KDColor e RightParenthesisLayoutNode::RenderWithChildHeight(childHeight, ctx, p.translatedBy(KDPoint(rightParenthesisPointX, 0)), expressionColor, backgroundColor); } -BinomialCoefficientLayout BinomialCoefficientLayout::Builder(Layout n, Layout k) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(BinomialCoefficientLayoutNode)); - BinomialCoefficientLayoutNode * node = new (bufferNode) BinomialCoefficientLayoutNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(n,k).array(), 2); - return static_cast(h); -} - -} +} \ No newline at end of file diff --git a/poincare/src/ceiling.cpp b/poincare/src/ceiling.cpp index 9742abffe..7dfeaef7f 100644 --- a/poincare/src/ceiling.cpp +++ b/poincare/src/ceiling.cpp @@ -35,12 +35,6 @@ Expression CeilingNode::shallowReduce(Context & context, Preferences::ComplexFor return Ceiling(this).shallowReduce(); } -Ceiling Ceiling::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(CeilingNode)); - CeilingNode * node = new (bufferNode) CeilingNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} Expression Ceiling::shallowReduce() { { diff --git a/poincare/src/ceiling_layout.cpp b/poincare/src/ceiling_layout.cpp deleted file mode 100644 index 0c2c679f7..000000000 --- a/poincare/src/ceiling_layout.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include - -namespace Poincare { - -CeilingLayout CeilingLayout::Builder(Layout child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(CeilingLayoutNode)); - CeilingLayoutNode * node = new (bufferNode) CeilingLayoutNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} - -} diff --git a/poincare/src/char_layout.cpp b/poincare/src/char_layout.cpp index d303a5b89..c938c06ff 100644 --- a/poincare/src/char_layout.cpp +++ b/poincare/src/char_layout.cpp @@ -99,7 +99,7 @@ bool CharLayoutNode::isMultiplicationChar() const { CharLayout CharLayout::Builder(char c, const KDFont * font) { void * bufferNode = TreePool::sharedPool()->alloc(sizeof(CharLayoutNode)); CharLayoutNode * node = new (bufferNode) CharLayoutNode(c, font); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + TreeHandle h = TreeHandle::BuildWithGhostChildren(node); return static_cast(h); } diff --git a/poincare/src/complex.cpp b/poincare/src/complex.cpp index 7ea64fee8..1dc2cca01 100644 --- a/poincare/src/complex.cpp +++ b/poincare/src/complex.cpp @@ -71,7 +71,7 @@ template Complex Complex::Builder(std::complex c) { void * bufferNode = TreePool::sharedPool()->alloc(sizeof(ComplexNode)); ComplexNode * node = new (bufferNode) ComplexNode(c); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + TreeHandle h = TreeHandle::BuildWithGhostChildren(node); return static_cast &>(h); } diff --git a/poincare/src/complex_argument.cpp b/poincare/src/complex_argument.cpp index 9ac1de038..eb6983ec3 100644 --- a/poincare/src/complex_argument.cpp +++ b/poincare/src/complex_argument.cpp @@ -33,12 +33,6 @@ Complex ComplexArgumentNode::computeOnComplex(const std::complex c, Prefer return Complex::Builder(std::arg(c)); } -ComplexArgument ComplexArgument::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(ComplexArgumentNode)); - ComplexArgumentNode * node = new (bufferNode) ComplexArgumentNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} Expression ComplexArgument::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { diff --git a/poincare/src/complex_cartesian.cpp b/poincare/src/complex_cartesian.cpp index ccf3d88f1..ce0416d42 100644 --- a/poincare/src/complex_cartesian.cpp +++ b/poincare/src/complex_cartesian.cpp @@ -52,20 +52,6 @@ Complex ComplexCartesianNode::templatedApproximate(Context& context, Preferen return Complex::Builder(a.real(), b.real()); } -ComplexCartesian ComplexCartesian::Builder() { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(ComplexCartesianNode)); - ComplexCartesianNode * node = new (bufferNode) ComplexCartesianNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); - return static_cast(h); -} - -ComplexCartesian ComplexCartesian::Builder(Expression real, Expression imag) { - ComplexCartesian c = ComplexCartesian::Builder(); - c.replaceChildAtIndexInPlace(0, real); - c.replaceChildAtIndexInPlace(1, imag); - return c; -} - Expression ComplexCartesian::shallowReduce() { if (imag().isRationalZero()) { Expression r = real(); diff --git a/poincare/src/condensed_sum_layout.cpp b/poincare/src/condensed_sum_layout.cpp index a658e5d5d..c6c60bb14 100644 --- a/poincare/src/condensed_sum_layout.cpp +++ b/poincare/src/condensed_sum_layout.cpp @@ -37,11 +37,4 @@ KDPoint CondensedSumLayoutNode::positionOfChild(LayoutNode * child) { return KDPoint(x,y); } -CondensedSumLayout CondensedSumLayout::Builder(Layout base, Layout subscript, Layout superscript) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(CondensedSumLayoutNode)); - CondensedSumLayoutNode * node = new (bufferNode) CondensedSumLayoutNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(base, subscript, superscript).array(), 3); - return static_cast(h); -} - } diff --git a/poincare/src/confidence_interval.cpp b/poincare/src/confidence_interval.cpp index cc47829ac..1f7716e57 100644 --- a/poincare/src/confidence_interval.cpp +++ b/poincare/src/confidence_interval.cpp @@ -52,12 +52,6 @@ int SimplePredictionIntervalNode::serialize(char * buffer, int bufferSize, Prefe return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, SimplePredictionInterval::s_functionHelper.name()); } -ConfidenceInterval ConfidenceInterval::Builder(Expression child0, Expression child1) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(ConfidenceIntervalNode)); - ConfidenceIntervalNode * node = new (bufferNode) ConfidenceIntervalNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); - return static_cast(h); -} Expression ConfidenceInterval::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { @@ -105,11 +99,5 @@ Expression ConfidenceInterval::shallowReduce(Context & context, Preferences::Com return matrix; } -SimplePredictionInterval SimplePredictionInterval::Builder(Expression child0, Expression child1) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(SimplePredictionIntervalNode)); - SimplePredictionIntervalNode * node = new (bufferNode) SimplePredictionIntervalNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); - return static_cast(h); -} } diff --git a/poincare/src/conjugate.cpp b/poincare/src/conjugate.cpp index a5f40eabf..ba6bfe143 100644 --- a/poincare/src/conjugate.cpp +++ b/poincare/src/conjugate.cpp @@ -64,11 +64,5 @@ Expression Conjugate::shallowReduce(Context & context, Preferences::ComplexForma return *this; } -Conjugate Conjugate::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(ConjugateNode)); - ConjugateNode * node = new (bufferNode) ConjugateNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} } diff --git a/poincare/src/conjugate_layout.cpp b/poincare/src/conjugate_layout.cpp index 2522718aa..ac636dcad 100644 --- a/poincare/src/conjugate_layout.cpp +++ b/poincare/src/conjugate_layout.cpp @@ -104,11 +104,4 @@ bool ConjugateLayoutNode::willReplaceChild(LayoutNode * oldChild, LayoutNode * n return true; } -ConjugateLayout ConjugateLayout::Builder(Layout child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(ConjugateLayoutNode)); - ConjugateLayoutNode * node = new (bufferNode) ConjugateLayoutNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} - } diff --git a/poincare/src/cosine.cpp b/poincare/src/cosine.cpp index 46e0a90eb..3f904d83a 100644 --- a/poincare/src/cosine.cpp +++ b/poincare/src/cosine.cpp @@ -50,11 +50,5 @@ Expression Cosine::shallowReduce(Context & context, Preferences::ComplexFormat c return Trigonometry::shallowReduceDirectFunction(*this, context, complexFormat, angleUnit, target); } -Cosine Cosine::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(CosineNode)); - CosineNode * node = new (bufferNode) CosineNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} } diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index f883333c1..1e88397e9 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -332,7 +332,7 @@ Decimal Decimal::Builder(Integer m, int e) { Decimal Decimal::Builder(size_t size, const Integer & m, int e) { void * bufferNode = TreePool::sharedPool()->alloc(size); DecimalNode * node = new (bufferNode) DecimalNode(m.digits(), m.numberOfDigits(), e, m.isNegative()); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + TreeHandle h = TreeHandle::BuildWithGhostChildren(node); return static_cast(h); } diff --git a/poincare/src/derivative.cpp b/poincare/src/derivative.cpp index 426878745..cb6f1de12 100644 --- a/poincare/src/derivative.cpp +++ b/poincare/src/derivative.cpp @@ -156,11 +156,13 @@ Expression Derivative::shallowReduce() { return *this; } -Derivative Derivative::Builder(Expression child0, Symbol child1, Expression child2) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(DerivativeNode)); - DerivativeNode * node = new (bufferNode) DerivativeNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1, child2).array(), 3); - return static_cast(h); +Expression Derivative::UntypedBuilder(Expression children) { + assert(children.type() == ExpressionNode::Type::Matrix); + if (children.childAtIndex(1).type() != ExpressionNode::Type::Symbol) { + // Second parameter must be a Symbol. + return Expression(); + } + return Builder(children.childAtIndex(0), children.childAtIndex(1).convert(), children.childAtIndex(2)); } } diff --git a/poincare/src/determinant.cpp b/poincare/src/determinant.cpp index e0b973e25..7a4a7b110 100644 --- a/poincare/src/determinant.cpp +++ b/poincare/src/determinant.cpp @@ -32,12 +32,6 @@ Expression DeterminantNode::shallowReduce(Context & context, Preferences::Comple return Determinant(this).shallowReduce(context); } -Determinant Determinant::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(DeterminantNode)); - DeterminantNode * node = new (bufferNode) DeterminantNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} Expression Determinant::shallowReduce(Context & context) { { diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index 8a6f5bb49..ae63cb861 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -70,20 +70,6 @@ template MatrixComplex DivisionNode::computeOnMatrices(const Matr // Division -Division Division::Builder() { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(DivisionNode)); - DivisionNode * node = new (bufferNode) DivisionNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); - return static_cast(h); -} - -Division Division::Builder(Expression numerator, Expression denominator) { - Division d = Division::Builder(); - d.replaceChildAtIndexInPlace(0, numerator); - d.replaceChildAtIndexInPlace(1, denominator); - return d; -} - Expression Division::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { Expression e = Expression::defaultShallowReduce(); diff --git a/poincare/src/division_quotient.cpp b/poincare/src/division_quotient.cpp index b382a54cc..853eb1b56 100644 --- a/poincare/src/division_quotient.cpp +++ b/poincare/src/division_quotient.cpp @@ -35,12 +35,6 @@ Evaluation DivisionQuotientNode::templatedApproximate(Context& context, Prefe return Complex::Builder(std::floor(f1/f2)); } -DivisionQuotient DivisionQuotient::Builder(Expression child0, Expression child1) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(DivisionQuotientNode)); - DivisionQuotientNode * node = new (bufferNode) DivisionQuotientNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); - return static_cast(h); -} Expression DivisionQuotient::shallowReduce() { { diff --git a/poincare/src/division_remainder.cpp b/poincare/src/division_remainder.cpp index 030fb33ca..f4334e0ee 100644 --- a/poincare/src/division_remainder.cpp +++ b/poincare/src/division_remainder.cpp @@ -36,12 +36,6 @@ Evaluation DivisionRemainderNode::templatedApproximate(Context& context, Pref return Complex::Builder(std::round(f1-f2*std::floor(f1/f2))); } -DivisionRemainder DivisionRemainder::Builder(Expression child0, Expression child1) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(DivisionRemainderNode)); - DivisionRemainderNode * node = new (bufferNode) DivisionRemainderNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); - return static_cast(h); -} Expression DivisionRemainder::shallowReduce() { { diff --git a/poincare/src/empty_expression.cpp b/poincare/src/empty_expression.cpp index cf007c671..882d6311f 100644 --- a/poincare/src/empty_expression.cpp +++ b/poincare/src/empty_expression.cpp @@ -18,11 +18,4 @@ template Evaluation EmptyExpressionNode::templatedApproximate(Con return Complex::Undefined(); } -EmptyExpression EmptyExpression::Builder() { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(EmptyExpressionNode)); - EmptyExpressionNode * node = new (bufferNode) EmptyExpressionNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); - return static_cast(h); -} - } diff --git a/poincare/src/empty_layout.cpp b/poincare/src/empty_layout.cpp index f8a0f8f3b..4bed5b777 100644 --- a/poincare/src/empty_layout.cpp +++ b/poincare/src/empty_layout.cpp @@ -99,7 +99,7 @@ EmptyLayout::EmptyLayout(const EmptyLayoutNode * n) : Layout(n) {} EmptyLayout EmptyLayout::Builder(EmptyLayoutNode::Color color, bool visible, const KDFont * font, bool margins) { void * bufferNode = TreePool::sharedPool()->alloc(sizeof(EmptyLayoutNode)); EmptyLayoutNode * node = new (bufferNode) EmptyLayoutNode(color, visible, font, margins); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + TreeHandle h = TreeHandle::BuildWithGhostChildren(node); return static_cast(h); } diff --git a/poincare/src/equal.cpp b/poincare/src/equal.cpp index e3f9f0c3d..0f8c758fe 100644 --- a/poincare/src/equal.cpp +++ b/poincare/src/equal.cpp @@ -41,12 +41,6 @@ Evaluation EqualNode::templatedApproximate(Context& context, Preferences::Com return Complex::Undefined(); } -Equal Equal::Builder(Expression child0, Expression child1) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(EqualNode)); - EqualNode * node = new (bufferNode) EqualNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); - return static_cast(h); -} Expression Equal::standardEquation(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { Expression sub = Subtraction::Builder(childAtIndex(0).clone(), childAtIndex(1).clone()); diff --git a/poincare/src/factor.cpp b/poincare/src/factor.cpp index dd8e005c0..910ce935c 100644 --- a/poincare/src/factor.cpp +++ b/poincare/src/factor.cpp @@ -30,12 +30,6 @@ Expression FactorNode::shallowBeautify(Context & context, Preferences::ComplexFo return Factor(this).shallowBeautify(context, complexFormat, angleUnit); } -Factor Factor::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(FactorNode)); - FactorNode * node = new (bufferNode) FactorNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} Expression Factor::shallowBeautify(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { Expression c = childAtIndex(0); diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index 47786a22b..643d24001 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -89,12 +89,6 @@ int FactorialNode::serialize(char * buffer, int bufferSize, Preferences::PrintFl return numberOfChar; } -Factorial Factorial::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(FactorialNode)); - FactorialNode * node = new (bufferNode) FactorialNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} Expression Factorial::shallowReduce() { { diff --git a/poincare/src/float.cpp b/poincare/src/float.cpp index 1a37e4107..3b5f0c453 100644 --- a/poincare/src/float.cpp +++ b/poincare/src/float.cpp @@ -45,7 +45,7 @@ template Float Float::Builder(T value) { void * bufferNode = TreePool::sharedPool()->alloc(sizeof(FloatNode)); FloatNode * node = new (bufferNode) FloatNode(value); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + TreeHandle h = TreeHandle::BuildWithGhostChildren(node); return static_cast(h); } diff --git a/poincare/src/floor.cpp b/poincare/src/floor.cpp index 207e1c28e..12cc0cd91 100644 --- a/poincare/src/floor.cpp +++ b/poincare/src/floor.cpp @@ -35,12 +35,6 @@ Expression FloorNode::shallowReduce(Context & context, Preferences::ComplexForma return Floor(this).shallowReduce(); } -Floor Floor::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(FloorNode)); - FloorNode * node = new (bufferNode) FloorNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} Expression Floor::shallowReduce() { { diff --git a/poincare/src/floor_layout.cpp b/poincare/src/floor_layout.cpp deleted file mode 100644 index d0c04a6dc..000000000 --- a/poincare/src/floor_layout.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include - -namespace Poincare { - -FloorLayout FloorLayout::Builder(Layout child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(FloorLayoutNode)); - FloorLayoutNode * node = new (bufferNode) FloorLayoutNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} - -} diff --git a/poincare/src/frac_part.cpp b/poincare/src/frac_part.cpp index 20da772b0..e2877b965 100644 --- a/poincare/src/frac_part.cpp +++ b/poincare/src/frac_part.cpp @@ -31,12 +31,6 @@ Complex FracPartNode::computeOnComplex(const std::complex c, Preferences:: return Complex::Builder(c.real()-std::floor(c.real())); } -FracPart FracPart::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(FracPartNode)); - FracPartNode * node = new (bufferNode) FracPartNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} Expression FracPart::shallowReduce() { { diff --git a/poincare/src/fraction_layout.cpp b/poincare/src/fraction_layout.cpp index d9e15d9bd..2b615d11a 100644 --- a/poincare/src/fraction_layout.cpp +++ b/poincare/src/fraction_layout.cpp @@ -216,11 +216,4 @@ void FractionLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionCo ctx->fillRect(KDRect(p.x()+Metric::FractionAndConjugateHorizontalMargin, fractionLineY, layoutSize().width()-2*Metric::FractionAndConjugateHorizontalMargin, k_fractionLineHeight), expressionColor); } -FractionLayout FractionLayout::Builder(Layout numerator, Layout denominator) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(FractionLayoutNode)); - FractionLayoutNode * node = new (bufferNode) FractionLayoutNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(numerator, denominator).array(), 2); - return static_cast(h); -} - -} +} \ No newline at end of file diff --git a/poincare/src/great_common_divisor.cpp b/poincare/src/great_common_divisor.cpp index b07b8242f..7e27cb55c 100644 --- a/poincare/src/great_common_divisor.cpp +++ b/poincare/src/great_common_divisor.cpp @@ -1,5 +1,5 @@ #include -#include + #include #include #include @@ -49,12 +49,6 @@ Evaluation GreatCommonDivisorNode::templatedApproximate(Context& context, Pre return Complex::Builder(std::round((T)a)); } -GreatCommonDivisor GreatCommonDivisor::Builder(Expression child0, Expression child1) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(GreatCommonDivisorNode)); - GreatCommonDivisorNode * node = new (bufferNode) GreatCommonDivisorNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); - return static_cast(h); -} Expression GreatCommonDivisor::shallowReduce() { { diff --git a/poincare/src/grid_layout.cpp b/poincare/src/grid_layout.cpp index e96115515..0907208c7 100644 --- a/poincare/src/grid_layout.cpp +++ b/poincare/src/grid_layout.cpp @@ -268,11 +268,4 @@ void GridLayout::setDimensions(int rows, int columns) { setNumberOfColumns(columns); } -GridLayout GridLayout::Builder() { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(GridLayoutNode)); - GridLayoutNode * node = new (bufferNode) GridLayoutNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); - return static_cast(h); -} - -} +} \ No newline at end of file diff --git a/poincare/src/horizontal_layout.cpp b/poincare/src/horizontal_layout.cpp index 8ebb7dd9f..10dc63766 100644 --- a/poincare/src/horizontal_layout.cpp +++ b/poincare/src/horizontal_layout.cpp @@ -353,13 +353,6 @@ bool HorizontalLayoutNode::willReplaceChild(LayoutNode * oldChild, LayoutNode * // HorizontalLayout -HorizontalLayout HorizontalLayout::Builder() { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(HorizontalLayoutNode)); - HorizontalLayoutNode * node = new (bufferNode) HorizontalLayoutNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); - return static_cast(h); -} - void HorizontalLayout::addOrMergeChildAtIndex(Layout l, int index, bool removeEmptyChildren, LayoutCursor * cursor) { if (l.isHorizontal()) { mergeChildrenAtIndex(HorizontalLayout(static_cast(l.node())), index, removeEmptyChildren, cursor); diff --git a/poincare/src/hyperbolic_arc_cosine.cpp b/poincare/src/hyperbolic_arc_cosine.cpp index 59f74b32c..b52aa2383 100644 --- a/poincare/src/hyperbolic_arc_cosine.cpp +++ b/poincare/src/hyperbolic_arc_cosine.cpp @@ -26,12 +26,6 @@ Complex HyperbolicArcCosineNode::computeOnComplex(const std::complex c, Pr return Complex::Builder(Trigonometry::RoundToMeaningfulDigits(result, c)); } -HyperbolicArcCosine HyperbolicArcCosine::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(HyperbolicArcCosineNode)); - HyperbolicArcCosineNode * node = new (bufferNode) HyperbolicArcCosineNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} template Complex Poincare::HyperbolicArcCosineNode::computeOnComplex(std::complex, Preferences::ComplexFormat, Preferences::AngleUnit); template Complex Poincare::HyperbolicArcCosineNode::computeOnComplex(std::complex, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit); diff --git a/poincare/src/hyperbolic_arc_sine.cpp b/poincare/src/hyperbolic_arc_sine.cpp index 38fba0d13..a2c95af34 100644 --- a/poincare/src/hyperbolic_arc_sine.cpp +++ b/poincare/src/hyperbolic_arc_sine.cpp @@ -29,12 +29,6 @@ Complex HyperbolicArcSineNode::computeOnComplex(const std::complex c, Pref return Complex::Builder(Trigonometry::RoundToMeaningfulDigits(result, c)); } -HyperbolicArcSine HyperbolicArcSine::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(HyperbolicArcSineNode)); - HyperbolicArcSineNode * node = new (bufferNode) HyperbolicArcSineNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} template Complex Poincare::HyperbolicArcSineNode::computeOnComplex(std::complex, Preferences::ComplexFormat, Preferences::AngleUnit); template Complex Poincare::HyperbolicArcSineNode::computeOnComplex(std::complex, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit); diff --git a/poincare/src/hyperbolic_arc_tangent.cpp b/poincare/src/hyperbolic_arc_tangent.cpp index 83b52592b..099835978 100644 --- a/poincare/src/hyperbolic_arc_tangent.cpp +++ b/poincare/src/hyperbolic_arc_tangent.cpp @@ -30,12 +30,6 @@ Complex HyperbolicArcTangentNode::computeOnComplex(const std::complex c, P return Complex::Builder(Trigonometry::RoundToMeaningfulDigits(result, c)); } -HyperbolicArcTangent HyperbolicArcTangent::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(HyperbolicArcTangentNode)); - HyperbolicArcTangentNode * node = new (bufferNode) HyperbolicArcTangentNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} template Complex Poincare::HyperbolicArcTangentNode::computeOnComplex(std::complex, Preferences::ComplexFormat, Preferences::AngleUnit); template Complex Poincare::HyperbolicArcTangentNode::computeOnComplex(std::complex, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit); diff --git a/poincare/src/hyperbolic_cosine.cpp b/poincare/src/hyperbolic_cosine.cpp index cfa001d4a..30f564714 100644 --- a/poincare/src/hyperbolic_cosine.cpp +++ b/poincare/src/hyperbolic_cosine.cpp @@ -18,12 +18,6 @@ Complex HyperbolicCosineNode::computeOnComplex(const std::complex c, Prefe return Complex::Builder(Trigonometry::RoundToMeaningfulDigits(std::cosh(c), c)); } -HyperbolicCosine HyperbolicCosine::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(HyperbolicCosineNode)); - HyperbolicCosineNode * node = new (bufferNode) HyperbolicCosineNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} template Complex Poincare::HyperbolicCosineNode::computeOnComplex(std::complex, Preferences::ComplexFormat, Preferences::AngleUnit); template Complex Poincare::HyperbolicCosineNode::computeOnComplex(std::complex, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit); diff --git a/poincare/src/hyperbolic_sine.cpp b/poincare/src/hyperbolic_sine.cpp index ef3064d2d..d30b18b82 100644 --- a/poincare/src/hyperbolic_sine.cpp +++ b/poincare/src/hyperbolic_sine.cpp @@ -18,12 +18,6 @@ Complex HyperbolicSineNode::computeOnComplex(const std::complex c, Prefere return Complex::Builder(Trigonometry::RoundToMeaningfulDigits(std::sinh(c), c)); } -HyperbolicSine HyperbolicSine::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(HyperbolicSineNode)); - HyperbolicSineNode * node = new (bufferNode) HyperbolicSineNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} template Complex Poincare::HyperbolicSineNode::computeOnComplex(std::complex, Preferences::ComplexFormat, Preferences::AngleUnit); template Complex Poincare::HyperbolicSineNode::computeOnComplex(std::complex, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit); diff --git a/poincare/src/hyperbolic_tangent.cpp b/poincare/src/hyperbolic_tangent.cpp index 2f7b3cec8..df19fe5e3 100644 --- a/poincare/src/hyperbolic_tangent.cpp +++ b/poincare/src/hyperbolic_tangent.cpp @@ -18,12 +18,6 @@ Complex HyperbolicTangentNode::computeOnComplex(const std::complex c, Pref return Complex::Builder(Trigonometry::RoundToMeaningfulDigits(std::tanh(c), c)); } -HyperbolicTangent HyperbolicTangent::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(HyperbolicTangentNode)); - HyperbolicTangentNode * node = new (bufferNode) HyperbolicTangentNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} template Complex Poincare::HyperbolicTangentNode::computeOnComplex(std::complex, Preferences::ComplexFormat, Preferences::AngleUnit); template Complex Poincare::HyperbolicTangentNode::computeOnComplex(std::complex, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit); diff --git a/poincare/src/imaginary_part.cpp b/poincare/src/imaginary_part.cpp index 439900869..f50138ddf 100644 --- a/poincare/src/imaginary_part.cpp +++ b/poincare/src/imaginary_part.cpp @@ -24,12 +24,6 @@ Expression ImaginaryPartNode::shallowReduce(Context & context, Preferences::Comp return ImaginaryPart(this).shallowReduce(context, complexFormat, angleUnit, target); } -ImaginaryPart ImaginaryPart::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(ImaginaryPartNode)); - ImaginaryPartNode * node = new (bufferNode) ImaginaryPartNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} Expression ImaginaryPart::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { diff --git a/poincare/src/infinity.cpp b/poincare/src/infinity.cpp index 71eb0287b..a8dc2a552 100644 --- a/poincare/src/infinity.cpp +++ b/poincare/src/infinity.cpp @@ -34,7 +34,7 @@ template Evaluation InfinityNode::templatedApproximate() const { Infinity Infinity::Builder(bool negative) { void * bufferNode = TreePool::sharedPool()->alloc(sizeof(InfinityNode)); InfinityNode * node = new (bufferNode) InfinityNode(negative); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + TreeHandle h = TreeHandle::BuildWithGhostChildren(node); return static_cast(h); } diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 67fd3e295..51ed772b6 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -104,7 +104,7 @@ Integer Integer::BuildInteger(native_uint_t * digits, uint16_t numberOfDigits, b Integer::Integer(native_uint_t * digits, uint16_t numberOfDigits, bool negative) { void * bufferNode = TreePool::sharedPool()->alloc(IntegerSize(numberOfDigits)); IntegerNode * node = new (bufferNode) IntegerNode(digits, numberOfDigits); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + TreeHandle h = TreeHandle::BuildWithGhostChildren(node); /* Integer is a TreeHandle that keeps an extra integer. We cannot just cast * the TreeHandle in Integer, we have to build a new Integer. To do so, we * pilfer the TreeHandle identifier. */ diff --git a/poincare/src/integral.cpp b/poincare/src/integral.cpp index 91816bb9b..96c565d87 100644 --- a/poincare/src/integral.cpp +++ b/poincare/src/integral.cpp @@ -1,5 +1,5 @@ #include -#include + #include #include #include @@ -210,11 +210,13 @@ T IntegralNode::adaptiveQuadrature(T a, T b, T eps, int numberOfIterations, Cont } #endif -Integral Integral::Builder(Expression child0, Symbol child1, Expression child2, Expression child3) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(IntegralNode)); - IntegralNode * node = new (bufferNode) IntegralNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1, child2, child3).array(), 4); - return static_cast(h); +Expression Integral::UntypedBuilder(Expression children) { + assert(children.type() == ExpressionNode::Type::Matrix); + if (children.childAtIndex(1).type() != ExpressionNode::Type::Symbol) { + // Second parameter must be a Symbol. + return Expression(); + } + return Builder(children.childAtIndex(0), children.childAtIndex(1).convert(), children.childAtIndex(2), children.childAtIndex(3)); } Expression Integral::shallowReduce() { diff --git a/poincare/src/integral_layout.cpp b/poincare/src/integral_layout.cpp index 43e366540..b53035fa6 100644 --- a/poincare/src/integral_layout.cpp +++ b/poincare/src/integral_layout.cpp @@ -247,11 +247,4 @@ void IntegralLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionCo ctx->drawString("d", dPosition, k_font, expressionColor, backgroundColor); } -IntegralLayout IntegralLayout::Builder(Layout integrand, Layout differential, Layout lowerBound, Layout upperBound) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(IntegralLayoutNode)); - IntegralLayoutNode * node = new (bufferNode) IntegralLayoutNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(integrand, differential, lowerBound, upperBound).array(), 4); - return static_cast(h); -} - } diff --git a/poincare/src/least_common_multiple.cpp b/poincare/src/least_common_multiple.cpp index 6096658d7..cc28523fb 100644 --- a/poincare/src/least_common_multiple.cpp +++ b/poincare/src/least_common_multiple.cpp @@ -53,12 +53,6 @@ Evaluation LeastCommonMultipleNode::templatedApproximate(Context& context, Pr return Complex::Builder(product/a); } -LeastCommonMultiple LeastCommonMultiple::Builder(Expression child0, Expression child1) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(LeastCommonMultipleNode)); - LeastCommonMultipleNode * node = new (bufferNode) LeastCommonMultipleNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); - return static_cast(h); -} Expression LeastCommonMultiple::shallowReduce() { { diff --git a/poincare/src/left_parenthesis_layout.cpp b/poincare/src/left_parenthesis_layout.cpp index 1ec811828..8ddd2dea5 100644 --- a/poincare/src/left_parenthesis_layout.cpp +++ b/poincare/src/left_parenthesis_layout.cpp @@ -59,11 +59,4 @@ void LeftParenthesisLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expre RenderWithChildHeight(ParenthesisLayoutNode::ChildHeightGivenLayoutHeight(layoutSize().height()), ctx, p, expressionColor, backgroundColor); } -LeftParenthesisLayout LeftParenthesisLayout::Builder() { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(LeftParenthesisLayoutNode)); - LeftParenthesisLayoutNode * node = new (bufferNode) LeftParenthesisLayoutNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); - return static_cast(h); -} - } diff --git a/poincare/src/left_square_bracket_layout.cpp b/poincare/src/left_square_bracket_layout.cpp index 7a64a0253..2a8d85c92 100644 --- a/poincare/src/left_square_bracket_layout.cpp +++ b/poincare/src/left_square_bracket_layout.cpp @@ -8,11 +8,4 @@ void LeftSquareBracketLayoutNode::render(KDContext * ctx, KDPoint p, KDColor exp ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y() + childHeight(), k_bracketWidth, k_lineThickness), expressionColor); } -LeftSquareBracketLayout LeftSquareBracketLayout::Builder() { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(LeftSquareBracketLayoutNode)); - LeftSquareBracketLayoutNode * node = new (bufferNode) LeftSquareBracketLayoutNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); - return static_cast(h); -} - } diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index a2ed4480c..4301d3c07 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -1,5 +1,5 @@ #include -#include + #include #include #include @@ -86,13 +86,6 @@ template Evaluation LogarithmNode<2>::templatedApproximate(Contex return Complex::Builder(result); } -CommonLogarithm CommonLogarithm::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(LogarithmNode<1>)); - LogarithmNode<1> * node = new (bufferNode) LogarithmNode<1>(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} - Expression CommonLogarithm::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target){ { Expression e = Expression::defaultShallowReduce(); @@ -113,13 +106,6 @@ Expression CommonLogarithm::shallowReduce(Context & context, Preferences::Comple return log.shallowReduce(context, complexFormat, angleUnit, target); } -Logarithm Logarithm::Builder(Expression child0, Expression child1) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(LogarithmNode<2>)); - LogarithmNode<2> * node = new (bufferNode) LogarithmNode<2>(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); - return static_cast(h); -} - Expression Logarithm::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target){ { Expression e = Expression::defaultShallowReduce(); diff --git a/poincare/src/matrix.cpp b/poincare/src/matrix.cpp index 42e0bfad8..f2faeef90 100644 --- a/poincare/src/matrix.cpp +++ b/poincare/src/matrix.cpp @@ -89,13 +89,6 @@ Evaluation MatrixNode::templatedApproximate(Context& context, Preferences::Co // MATRIX -Matrix Matrix::Builder() { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(MatrixNode)); - MatrixNode * node = new (bufferNode) MatrixNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); - return static_cast(h); -} - void Matrix::setDimensions(int rows, int columns) { assert(rows * columns == numberOfChildren()); setNumberOfRows(rows); diff --git a/poincare/src/matrix_complex.cpp b/poincare/src/matrix_complex.cpp index 416b194ea..76eb28e57 100644 --- a/poincare/src/matrix_complex.cpp +++ b/poincare/src/matrix_complex.cpp @@ -130,14 +130,6 @@ MatrixComplex MatrixComplex::Builder(std::complex * operands, int numbe return m; } -template -MatrixComplex MatrixComplex::Builder() { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(MatrixComplexNode)); - MatrixComplexNode * node = new (bufferNode) MatrixComplexNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); - return static_cast &>(h); -} - template MatrixComplex MatrixComplex::Undefined() { std::complex undef = std::complex(NAN, NAN); diff --git a/poincare/src/matrix_dimension.cpp b/poincare/src/matrix_dimension.cpp index 24e1e273e..5390a43d0 100644 --- a/poincare/src/matrix_dimension.cpp +++ b/poincare/src/matrix_dimension.cpp @@ -37,12 +37,6 @@ Evaluation MatrixDimensionNode::templatedApproximate(Context& context, Prefer return MatrixComplex::Builder(operands, 1, 2); } -MatrixDimension MatrixDimension::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(MatrixDimensionNode)); - MatrixDimensionNode * node = new (bufferNode) MatrixDimensionNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} Expression MatrixDimension::shallowReduce() { { diff --git a/poincare/src/matrix_inverse.cpp b/poincare/src/matrix_inverse.cpp index d12e8164d..24aba3623 100644 --- a/poincare/src/matrix_inverse.cpp +++ b/poincare/src/matrix_inverse.cpp @@ -42,12 +42,6 @@ Evaluation MatrixInverseNode::templatedApproximate(Context& context, Preferen return inverse; } -MatrixInverse MatrixInverse::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(MatrixInverseNode)); - MatrixInverseNode * node = new (bufferNode) MatrixInverseNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} Expression MatrixInverse::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { diff --git a/poincare/src/matrix_layout.cpp b/poincare/src/matrix_layout.cpp index e184fc8f1..e7223c3e7 100644 --- a/poincare/src/matrix_layout.cpp +++ b/poincare/src/matrix_layout.cpp @@ -266,11 +266,10 @@ void MatrixLayoutNode::didReplaceChildAtIndex(int index, LayoutCursor * cursor, } } -MatrixLayout MatrixLayout::Builder() { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(MatrixLayoutNode)); - MatrixLayoutNode * node = new (bufferNode) MatrixLayoutNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); - return static_cast(h); +MatrixLayout MatrixLayout::Builder(Layout l1, Layout l2, Layout l3, Layout l4) { + MatrixLayout m = TreeHandle::NAryBuilder(ArrayBuilder(l1,l2,l3,l4).array(), 4); + m.setDimensions(2, 2); + return m; } } diff --git a/poincare/src/matrix_trace.cpp b/poincare/src/matrix_trace.cpp index 1ff3c58a1..dbe915cd7 100644 --- a/poincare/src/matrix_trace.cpp +++ b/poincare/src/matrix_trace.cpp @@ -32,12 +32,6 @@ Evaluation MatrixTraceNode::templatedApproximate(Context& context, Preference return result; } -MatrixTrace MatrixTrace::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(MatrixTraceNode)); - MatrixTraceNode * node = new (bufferNode) MatrixTraceNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} Expression MatrixTrace::shallowReduce() { { diff --git a/poincare/src/matrix_transpose.cpp b/poincare/src/matrix_transpose.cpp index c7e01c7be..8e8805d98 100644 --- a/poincare/src/matrix_transpose.cpp +++ b/poincare/src/matrix_transpose.cpp @@ -37,12 +37,6 @@ Evaluation MatrixTransposeNode::templatedApproximate(Context& context, Prefer return transpose; } -MatrixTranspose MatrixTranspose::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(MatrixTransposeNode)); - MatrixTransposeNode * node = new (bufferNode) MatrixTransposeNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} Expression MatrixTranspose::shallowReduce() { { diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 52efbe73d..29aceb262 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -108,21 +108,6 @@ Expression MultiplicationNode::denominator(Context & context, Preferences::Compl /* Multiplication */ -Multiplication Multiplication::Builder() { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(AdditionNode)); - MultiplicationNode * node = new (bufferNode) MultiplicationNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); - return static_cast(h); -} - -Multiplication Multiplication::Builder(Expression * children, size_t numberOfChildren) { - Multiplication m = Multiplication::Builder(); - for (size_t i = 0; i < numberOfChildren; i++) { - m.addChildAtIndexInPlace(children[i], i, i); - } - return m; -} - template void Multiplication::computeOnArrays(T * m, T * n, T * result, int mNumberOfColumns, int mNumberOfRows, int nNumberOfColumns) { for (int i = 0; i < mNumberOfRows; i++) { diff --git a/poincare/src/naperian_logarithm.cpp b/poincare/src/naperian_logarithm.cpp index 520dd5f3d..29ea6cb9b 100644 --- a/poincare/src/naperian_logarithm.cpp +++ b/poincare/src/naperian_logarithm.cpp @@ -22,12 +22,6 @@ Expression NaperianLogarithmNode::shallowReduce(Context & context, Preferences:: return NaperianLogarithm(this).shallowReduce(context, complexFormat, angleUnit, target); } -NaperianLogarithm NaperianLogarithm::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(NaperianLogarithmNode)); - NaperianLogarithmNode * node = new (bufferNode) NaperianLogarithmNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} Expression NaperianLogarithm::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index ecb3b2b18..b7cbe9566 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -63,12 +63,6 @@ Evaluation NthRootNode::templatedApproximate(Context& context, Preferences::C return result; } -NthRoot NthRoot::Builder(Expression child0, Expression child1) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(NthRootNode)); - NthRootNode * node = new (bufferNode) NthRootNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); - return static_cast(h); -} Expression NthRoot::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { diff --git a/poincare/src/nth_root_layout.cpp b/poincare/src/nth_root_layout.cpp index 59cab9af3..4e7dd4573 100644 --- a/poincare/src/nth_root_layout.cpp +++ b/poincare/src/nth_root_layout.cpp @@ -273,14 +273,17 @@ void NthRootLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionCol NthRootLayout NthRootLayout::Builder(Layout child) { void * bufferNode = TreePool::sharedPool()->alloc(sizeof(NthRootLayoutNode)); NthRootLayoutNode * node = new (bufferNode) NthRootLayoutNode(false); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); + TreeHandle h = TreeHandle::BuildWithGhostChildren(node); + h.replaceChildAtIndexInPlace(0, child); return static_cast(h); } NthRootLayout NthRootLayout::Builder(Layout child, Layout index) { void * bufferNode = TreePool::sharedPool()->alloc(sizeof(NthRootLayoutNode)); NthRootLayoutNode * node = new (bufferNode) NthRootLayoutNode(true); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child, index).array(), 2); + TreeHandle h = TreeHandle::BuildWithGhostChildren(node); + h.replaceChildAtIndexInPlace(0, child); + h.replaceChildAtIndexInPlace(1, index); return static_cast(h); } diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index 9d2d33613..ec4665c05 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -69,19 +69,6 @@ Expression OppositeNode::shallowReduce(Context & context, Preferences::ComplexFo /* Simplification */ -Opposite Opposite::Builder() { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(OppositeNode)); - OppositeNode * node = new (bufferNode) OppositeNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); - return static_cast(h); -} - -Opposite Opposite::Builder(Expression child) { - Opposite d = Opposite::Builder(); - d.replaceChildAtIndexInPlace(0, child); - return d; -} - Expression Opposite::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { Expression result = Expression::defaultShallowReduce(); if (result.isUndefined()) { diff --git a/poincare/src/parenthesis.cpp b/poincare/src/parenthesis.cpp index ce87f1b89..3ad088ca9 100644 --- a/poincare/src/parenthesis.cpp +++ b/poincare/src/parenthesis.cpp @@ -25,12 +25,6 @@ Evaluation ParenthesisNode::templatedApproximate(Context& context, Preference return childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); } -Parenthesis Parenthesis::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(ParenthesisNode)); - ParenthesisNode * node = new (bufferNode) ParenthesisNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} Expression Parenthesis::shallowReduce() { Expression e = Expression::defaultShallowReduce(); diff --git a/poincare/src/permute_coefficient.cpp b/poincare/src/permute_coefficient.cpp index 767295862..2e01cd395 100644 --- a/poincare/src/permute_coefficient.cpp +++ b/poincare/src/permute_coefficient.cpp @@ -49,12 +49,6 @@ Evaluation PermuteCoefficientNode::templatedApproximate(Context& context, Pre return Complex::Builder(std::round(result)); } -PermuteCoefficient PermuteCoefficient::Builder(Expression child0, Expression child1) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(PermuteCoefficientNode)); - PermuteCoefficientNode * node = new (bufferNode) PermuteCoefficientNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); - return static_cast(h); -} Expression PermuteCoefficient::shallowReduce() { { diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 2384d25f9..4c90df701 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -234,13 +234,6 @@ template MatrixComplex PowerNode::computeOnMatrices(const MatrixC // Power -Power Power::Builder(Expression base, Expression exponent) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(PowerNode)); - PowerNode * node = new (bufferNode) PowerNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(base, exponent).array(), 2); - return static_cast(h); -} - Expression Power::setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { assert(s == ExpressionNode::Sign::Positive); if (childAtIndex(0).sign(context) == ExpressionNode::Sign::Negative) { diff --git a/poincare/src/prediction_interval.cpp b/poincare/src/prediction_interval.cpp index 7f95e0f84..ac894f92b 100644 --- a/poincare/src/prediction_interval.cpp +++ b/poincare/src/prediction_interval.cpp @@ -46,12 +46,6 @@ Evaluation PredictionIntervalNode::templatedApproximate(Context& context, Pre return MatrixComplex::Builder(operands, 1, 2); } -PredictionInterval PredictionInterval::Builder(Expression child0, Expression child1) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(PredictionIntervalNode)); - PredictionIntervalNode * node = new (bufferNode) PredictionIntervalNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); - return static_cast(h); -} Expression PredictionInterval::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { diff --git a/poincare/src/product.cpp b/poincare/src/product.cpp index bb422b85d..ff6d7a8e0 100644 --- a/poincare/src/product.cpp +++ b/poincare/src/product.cpp @@ -46,11 +46,13 @@ Evaluation ProductNode::templatedApproximateWithNextTerm(Evaluation a, Eva return MultiplicationNode::computeOnMatrices(m, n, complexFormat); } -Product Product::Builder(Expression child0, Symbol child1, Expression child2, Expression child3) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(ProductNode)); - ProductNode * node = new (bufferNode) ProductNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1, child2, child3).array(), 4); - return static_cast(h); +Expression Product::UntypedBuilder(Expression children) { + assert(children.type() == ExpressionNode::Type::Matrix); + if (children.childAtIndex(1).type() != ExpressionNode::Type::Symbol) { + // Second parameter must be a Symbol. + return Expression(); + } + return Builder(children.childAtIndex(0), children.childAtIndex(1).convert(), children.childAtIndex(2), children.childAtIndex(3)); } } diff --git a/poincare/src/product_layout.cpp b/poincare/src/product_layout.cpp index 3685b81f9..8be05d651 100644 --- a/poincare/src/product_layout.cpp +++ b/poincare/src/product_layout.cpp @@ -30,11 +30,4 @@ void ProductLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionCol SequenceLayoutNode::render(ctx, p, expressionColor, backgroundColor); } -ProductLayout ProductLayout::Builder(Layout argument, Layout variable, Layout lowerB, Layout upperB) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(ProductLayoutNode)); - ProductLayoutNode * node = new (bufferNode) ProductLayoutNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(argument, variable, lowerB, upperB).array(), 4); - return static_cast(h); -} - } diff --git a/poincare/src/randint.cpp b/poincare/src/randint.cpp index 645e1ca88..47d20058b 100644 --- a/poincare/src/randint.cpp +++ b/poincare/src/randint.cpp @@ -37,11 +37,5 @@ template Evaluation RandintNode::templateApproximate(Context & c return Complex::Builder(result); } -Randint Randint::Builder(Expression child0, Expression child1) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(RandintNode)); - RandintNode * node = new (bufferNode) RandintNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); - return static_cast(h); -} } diff --git a/poincare/src/random.cpp b/poincare/src/random.cpp index 3d8e0e546..cd5e309a0 100644 --- a/poincare/src/random.cpp +++ b/poincare/src/random.cpp @@ -29,13 +29,6 @@ template Evaluation RandomNode::templateApproximate() const { return Complex::Builder(Random::random()); } -Random Random::Builder() { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(RandomNode)); - RandomNode * node = new (bufferNode) RandomNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); - return static_cast(h); -} - Expression Random::setSign(ExpressionNode::Sign s, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { assert(s == ExpressionNode::Sign::Positive); return *this; diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index 3247d5c2d..fa86aba96 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -220,7 +220,7 @@ Rational Rational::IntegerPower(const Rational & i, const Integer & j) { Rational Rational::Builder(const native_uint_t * i, uint8_t numeratorSize, const native_uint_t * j, uint8_t denominatorSize, bool negative) { void * bufferNode = TreePool::sharedPool()->alloc(RationalSize(numeratorSize, denominatorSize)); RationalNode * node = new (bufferNode) RationalNode(i, numeratorSize, j, denominatorSize, negative); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + TreeHandle h = TreeHandle::BuildWithGhostChildren(node); return static_cast(h); } diff --git a/poincare/src/real_part.cpp b/poincare/src/real_part.cpp index 95cf8534b..3fc75d22f 100644 --- a/poincare/src/real_part.cpp +++ b/poincare/src/real_part.cpp @@ -24,12 +24,6 @@ Expression RealPartNode::shallowReduce(Context & context, Preferences::ComplexFo return RealPart(this).shallowReduce(context, complexFormat, angleUnit, target); } -RealPart RealPart::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(RealPartNode)); - RealPartNode * node = new (bufferNode) RealPartNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} Expression RealPart::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { diff --git a/poincare/src/right_parenthesis_layout.cpp b/poincare/src/right_parenthesis_layout.cpp index 68a267f96..d38345f20 100644 --- a/poincare/src/right_parenthesis_layout.cpp +++ b/poincare/src/right_parenthesis_layout.cpp @@ -59,11 +59,4 @@ void RightParenthesisLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expr RenderWithChildHeight(ParenthesisLayoutNode::ChildHeightGivenLayoutHeight(layoutSize().height()), ctx, p, expressionColor, backgroundColor); } -RightParenthesisLayout RightParenthesisLayout::Builder() { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(RightParenthesisLayoutNode)); - RightParenthesisLayoutNode * node = new (bufferNode) RightParenthesisLayoutNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); - return static_cast(h); -} - } diff --git a/poincare/src/right_square_bracket_layout.cpp b/poincare/src/right_square_bracket_layout.cpp index 3707312fe..cd1608a02 100644 --- a/poincare/src/right_square_bracket_layout.cpp +++ b/poincare/src/right_square_bracket_layout.cpp @@ -8,11 +8,4 @@ void RightSquareBracketLayoutNode::render(KDContext * ctx, KDPoint p, KDColor ex ctx->fillRect(KDRect(p.x()+k_widthMargin-k_bracketWidth+1, p.y() + childHeight(), k_bracketWidth, k_lineThickness), expressionColor); } -RightSquareBracketLayout RightSquareBracketLayout::Builder() { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(RightSquareBracketLayoutNode)); - RightSquareBracketLayoutNode * node = new (bufferNode) RightSquareBracketLayoutNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); - return static_cast(h); -} - } diff --git a/poincare/src/round.cpp b/poincare/src/round.cpp index 5fc95311c..416bd2037 100644 --- a/poincare/src/round.cpp +++ b/poincare/src/round.cpp @@ -38,12 +38,6 @@ Evaluation RoundNode::templatedApproximate(Context& context, Preferences::Com return Complex::Builder(std::round(f1*err)/err); } -Round Round::Builder(Expression child0, Expression child1) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(RoundNode)); - RoundNode * node = new (bufferNode) RoundNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1).array(), 2); - return static_cast(h); -} Expression Round::shallowReduce() { { diff --git a/poincare/src/sign_function.cpp b/poincare/src/sign_function.cpp index 0099b02c7..cc8a8bf09 100644 --- a/poincare/src/sign_function.cpp +++ b/poincare/src/sign_function.cpp @@ -51,12 +51,6 @@ Complex SignFunctionNode::computeOnComplex(const std::complex c, Preferenc return Complex::Builder(1.0); } -SignFunction SignFunction::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(SignFunctionNode)); - SignFunctionNode * node = new (bufferNode) SignFunctionNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} Expression SignFunction::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { diff --git a/poincare/src/sine.cpp b/poincare/src/sine.cpp index 5099382d2..7241efff2 100644 --- a/poincare/src/sine.cpp +++ b/poincare/src/sine.cpp @@ -34,12 +34,6 @@ Expression SineNode::shallowReduce(Context & context, Preferences::ComplexFormat return Sine(this).shallowReduce(context, complexFormat, angleUnit, target); } -Sine Sine::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(SineNode)); - SineNode * node = new (bufferNode) SineNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} Expression Sine::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index 747d48c51..243bbc37a 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -42,12 +42,6 @@ Expression SquareRootNode::shallowReduce(Context & context, Preferences::Complex return SquareRoot(this).shallowReduce(context, complexFormat, angleUnit, target); } -SquareRoot SquareRoot::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(SquareRootNode)); - SquareRootNode * node = new (bufferNode) SquareRootNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} Expression SquareRoot::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index 4eb0830b0..0c085733d 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -69,13 +69,6 @@ Expression Store::shallowReduce(Context & context, Preferences::ComplexFormat co return storedExpression; } -Store Store::Builder(Expression value, SymbolAbstract symbol) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(StoreNode)); - StoreNode * node = new (bufferNode) StoreNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(value, symbol).array(), 2); - return static_cast(h); -} - Expression Store::storeValueForSymbol(Context& context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { Expression finalValue; if (symbol().type() == ExpressionNode::Type::Function) { diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index 8978925b0..44f670cf2 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -56,20 +56,6 @@ Expression SubtractionNode::shallowReduce(Context & context, Preferences::Comple return Subtraction(this).shallowReduce(context, complexFormat, angleUnit, target); } -Subtraction Subtraction::Builder() { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(SubtractionNode)); - SubtractionNode * node = new (bufferNode) SubtractionNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); - return static_cast(h); -} - -Subtraction Subtraction::Builder(Expression child0, Expression child1) { - Subtraction d = Subtraction::Builder(); - d.replaceChildAtIndexInPlace(0, child0); - d.replaceChildAtIndexInPlace(1, child1); - return d; -} - Expression Subtraction::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { Expression e = Expression::defaultShallowReduce(); if (e.isUndefined()) { diff --git a/poincare/src/sum.cpp b/poincare/src/sum.cpp index e8bdeac55..549cfdba9 100644 --- a/poincare/src/sum.cpp +++ b/poincare/src/sum.cpp @@ -46,11 +46,13 @@ Evaluation SumNode::templatedApproximateWithNextTerm(Evaluation a, Evaluat return AdditionNode::computeOnMatrices(m, n, complexFormat); } -Sum Sum::Builder(Expression child0, Symbol child1, Expression child2, Expression child3) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(SumNode)); - SumNode * node = new (bufferNode) SumNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1, child2, child3).array(), 4); - return static_cast(h); +Expression Sum::UntypedBuilder(Expression children) { + assert(children.type() == ExpressionNode::Type::Matrix); + if (children.childAtIndex(1).type() != ExpressionNode::Type::Symbol) { + // Second parameter must be a Symbol. + return Expression(); + } + return Builder(children.childAtIndex(0), children.childAtIndex(1).convert(), children.childAtIndex(2), children.childAtIndex(3)); } } diff --git a/poincare/src/sum_layout.cpp b/poincare/src/sum_layout.cpp index 1297b124a..9c9a079e8 100644 --- a/poincare/src/sum_layout.cpp +++ b/poincare/src/sum_layout.cpp @@ -45,11 +45,4 @@ void SumLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionColor, SequenceLayoutNode::render(ctx, p, expressionColor, backgroundColor); } -SumLayout SumLayout::Builder(Layout child0, Layout child1, Layout child2, Layout child3) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(SumLayoutNode)); - SumLayoutNode * node = new (bufferNode) SumLayoutNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, ArrayBuilder(child0, child1, child2, child3).array(), 4); - return static_cast(h); -} - } diff --git a/poincare/src/symbol_abstract.cpp b/poincare/src/symbol_abstract.cpp index 59bdf55f6..9e9a518ad 100644 --- a/poincare/src/symbol_abstract.cpp +++ b/poincare/src/symbol_abstract.cpp @@ -41,7 +41,7 @@ T SymbolAbstract::Builder(const char * name, int length) { size_t size = sizeof(U) + length + 1; void * bufferNode = TreePool::sharedPool()->alloc(size); U * node = new (bufferNode) U(name, length); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + TreeHandle h = TreeHandle::BuildWithGhostChildren(node); return static_cast(h); } diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp index cb162eb5a..afb372d38 100644 --- a/poincare/src/tangent.cpp +++ b/poincare/src/tangent.cpp @@ -37,12 +37,6 @@ Expression TangentNode::shallowReduce(Context & context, Preferences::ComplexFor return Tangent(this).shallowReduce(context, complexFormat, angleUnit, target); } -Tangent Tangent::Builder(Expression child) { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(TangentNode)); - TangentNode * node = new (bufferNode) TangentNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &child, 1); - return static_cast(h); -} Expression Tangent::shallowReduce(Context & context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { diff --git a/poincare/src/tree_handle.cpp b/poincare/src/tree_handle.cpp index 15dcbd51c..25b2aef27 100644 --- a/poincare/src/tree_handle.cpp +++ b/poincare/src/tree_handle.cpp @@ -1,4 +1,6 @@ #include +#include +#include #include #if POINCARE_TREE_LOG #include @@ -185,7 +187,32 @@ TreeHandle::TreeHandle(const TreeNode * node) : TreeHandle() { } } -TreeHandle TreeHandle::BuildWithBasicChildren(TreeNode * node, TreeHandle * children, int numberOfChildren) { +template +TreeHandle TreeHandle::Builder() { + void * bufferNode = TreePool::sharedPool()->alloc(sizeof(U)); + U * node = new (bufferNode) U(); + return TreeHandle::BuildWithGhostChildren(node); +} + +template +T TreeHandle::NAryBuilder(TreeHandle * children, size_t numberOfChildren) { + TreeHandle h = Builder(); + for (size_t i = 0; i < numberOfChildren; i++) { + h.addChildAtIndexInPlace(children[i], i, i); + } + return static_cast(h); +} + +template +T TreeHandle::FixedArityBuilder(TreeHandle * children, size_t numberOfChildren) { + TreeHandle h = Builder(); + for (size_t i = 0; i < numberOfChildren; i++) { + h.replaceChildAtIndexInPlace(i, children[i]); + } + return static_cast(h); +} + +TreeHandle TreeHandle::BuildWithGhostChildren(TreeNode * node) { assert(node != nullptr); TreePool * pool = TreePool::sharedPool(); int expectedNumberOfChildren = node->numberOfChildren(); @@ -198,17 +225,7 @@ TreeHandle TreeHandle::BuildWithBasicChildren(TreeNode * node, TreeHandle * chil assert((char *)ghost == (char *)node->next() + i*sizeof(GhostNode)); } node->rename(pool->generateIdentifier(), false); - TreeHandle h = TreeHandle(node); - /* Add or replace ghost children by the children given as arguments if - * possible. */ - for (int i = 0; i < numberOfChildren; i++) { - if (i < expectedNumberOfChildren) { - h.replaceChildAtIndexInPlace(i, children[i]); - } else { - h.addChildAtIndexInPlace(children[i], i, i); - } - } - return h; + return TreeHandle(node); } void TreeHandle::setIdentifierAndRetain(int newId) { @@ -243,4 +260,86 @@ void TreeHandle::release(int identifier) { node->release(node->numberOfChildren()); } +template AbsoluteValue TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template AbsoluteValueLayout TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Addition TreeHandle::NAryBuilder(TreeHandle*, size_t); +template ArcCosine TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template ArcSine TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template ArcTangent TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template BinomialCoefficient TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template BinomialCoefficientLayout TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Ceiling TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template CeilingLayout TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template CommonLogarithm TreeHandle::FixedArityBuilder >(TreeHandle*, size_t); +template ComplexArgument TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template ComplexCartesian TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template CondensedSumLayout TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template ConfidenceInterval TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Conjugate TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template ConjugateLayout TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Cosine TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Derivative TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Determinant TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Division TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template DivisionQuotient TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template DivisionRemainder TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template EmptyExpression TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Equal TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Factor TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Factorial TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Floor TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template FloorLayout TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template FracPart TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template FractionLayout TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template GreatCommonDivisor TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template HorizontalLayout TreeHandle::NAryBuilder(TreeHandle*, size_t); +template HyperbolicArcCosine TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template HyperbolicArcSine TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template HyperbolicArcTangent TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template HyperbolicCosine TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template HyperbolicSine TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template HyperbolicTangent TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template ImaginaryPart TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Integral TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template IntegralLayout TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template LeastCommonMultiple TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template LeftParenthesisLayout TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template LeftSquareBracketLayout TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Logarithm TreeHandle::FixedArityBuilder >(TreeHandle*, size_t); +template Matrix TreeHandle::NAryBuilder(TreeHandle*, size_t); +template MatrixComplex TreeHandle::NAryBuilder, MatrixComplexNode >(TreeHandle*, size_t); +template MatrixComplex TreeHandle::NAryBuilder, MatrixComplexNode >(TreeHandle*, size_t); +template MatrixDimension TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template MatrixInverse TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template MatrixTrace TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template MatrixTranspose TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Multiplication TreeHandle::NAryBuilder(TreeHandle*, size_t); +template NaperianLogarithm TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template NthRoot TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Opposite TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Parenthesis TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template PermuteCoefficient TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Power TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template PredictionInterval TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Product TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template ProductLayout TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Randint TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Random TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template RealPart TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template RightParenthesisLayout TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template RightSquareBracketLayout TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Round TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template SignFunction TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template SimplePredictionInterval TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Sine TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template SquareRoot TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Store TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Subtraction TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Sum TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template SumLayout TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Tangent TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Undefined TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template Unreal TreeHandle::FixedArityBuilder(TreeHandle*, size_t); +template MatrixLayout TreeHandle::NAryBuilder(TreeHandle*, size_t); + } diff --git a/poincare/src/undefined.cpp b/poincare/src/undefined.cpp index 0615d830e..7031aec61 100644 --- a/poincare/src/undefined.cpp +++ b/poincare/src/undefined.cpp @@ -34,13 +34,6 @@ template Evaluation UndefinedNode::templatedApproximate() const { return Complex::Undefined(); } -Undefined Undefined::Builder() { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(UndefinedNode)); - UndefinedNode * node = new (bufferNode) UndefinedNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); - return static_cast(h); -} - template Evaluation UndefinedNode::templatedApproximate() const; template Evaluation UndefinedNode::templatedApproximate() const; } diff --git a/poincare/src/unreal.cpp b/poincare/src/unreal.cpp index d8d45a25e..e60d16bd4 100644 --- a/poincare/src/unreal.cpp +++ b/poincare/src/unreal.cpp @@ -20,11 +20,4 @@ int UnrealNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloat return min(Unreal::NameSize(), bufferSize) - 1; } -Unreal Unreal::Builder() { - void * bufferNode = TreePool::sharedPool()->alloc(sizeof(UnrealNode)); - UnrealNode * node = new (bufferNode) UnrealNode(); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); - return static_cast(h); -} - } diff --git a/poincare/src/vertical_offset_layout.cpp b/poincare/src/vertical_offset_layout.cpp index 5686e6f16..5b41e6282 100644 --- a/poincare/src/vertical_offset_layout.cpp +++ b/poincare/src/vertical_offset_layout.cpp @@ -269,7 +269,8 @@ LayoutNode * VerticalOffsetLayoutNode::baseLayout() { VerticalOffsetLayout VerticalOffsetLayout::Builder(Layout l, VerticalOffsetLayoutNode::Type type) { void * bufferNode = TreePool::sharedPool()->alloc(sizeof(VerticalOffsetLayoutNode)); VerticalOffsetLayoutNode * node = new (bufferNode) VerticalOffsetLayoutNode(type); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, &l, 1); + TreeHandle h = TreeHandle::BuildWithGhostChildren(node); + h.replaceChildAtIndexInPlace(0, l); return static_cast(h); } diff --git a/poincare/test/tree/blob_node.h b/poincare/test/tree/blob_node.h index e2a0c907d..6bbd86395 100644 --- a/poincare/test/tree/blob_node.h +++ b/poincare/test/tree/blob_node.h @@ -26,7 +26,7 @@ public: static BlobByReference Builder(int data = 0) { void * bufferNode = TreePool::sharedPool()->alloc(sizeof(BlobNode)); BlobNode * node = new (bufferNode) BlobNode(data); - TreeHandle h = TreeHandle::BuildWithBasicChildren(node); + TreeHandle h = TreeHandle::BuildWithGhostChildren(node); return static_cast(h); } BlobByReference() = delete; diff --git a/poincare/test/tree/pair_node.h b/poincare/test/tree/pair_node.h index c041e186b..a6eb9dd06 100644 --- a/poincare/test/tree/pair_node.h +++ b/poincare/test/tree/pair_node.h @@ -3,7 +3,7 @@ #include #include -#include + namespace Poincare { @@ -24,7 +24,9 @@ public: void * bufferNode = TreePool::sharedPool()->alloc(sizeof(PairNode)); PairNode * node = new (bufferNode) PairNode(); TreeHandle children[2] = {t1, t2}; - TreeHandle h = TreeHandle::BuildWithBasicChildren(node, children, 2); + TreeHandle h = TreeHandle::BuildWithGhostChildren(node); + h.replaceChildAtIndexInPlace(0, t1); + h.replaceChildAtIndexInPlace(1, t2); return static_cast(h); } PairByReference() = delete; From 8ca4094e13a010e18e8b1a2900a18958759890f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 21 Feb 2019 10:47:39 +0100 Subject: [PATCH 346/373] [poincare] Un-inline Symbol and Function UntypedBuilder --- poincare/include/poincare/function.h | 10 +--------- poincare/include/poincare/symbol.h | 10 ++-------- poincare/src/function.cpp | 10 ++++++++++ poincare/src/symbol.cpp | 9 +++++++++ 4 files changed, 22 insertions(+), 17 deletions(-) diff --git a/poincare/include/poincare/function.h b/poincare/include/poincare/function.h index 781324826..c1109f0bd 100644 --- a/poincare/include/poincare/function.h +++ b/poincare/include/poincare/function.h @@ -53,15 +53,7 @@ friend class FunctionNode; public: Function(const FunctionNode * n) : SymbolAbstract(n) {} static Function Builder(const char * name, size_t length, Expression child = Expression()); - static Expression UntypedBuilder(const char * name, size_t length, Expression child, Context * context) { - /* Create an expression only if it is not in the context or defined as a - * function */ - Function f = Function::Builder(name, length, child); - if (SymbolAbstract::ValidInContext(f, context)) { - return f; - } - return Expression(); - } + static Expression UntypedBuilder(const char * name, size_t length, Expression child, Context * context); // Simplification Expression replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression); diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index fbe668d84..3c4c93ec4 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -67,14 +67,8 @@ public: static Symbol Builder(const char * name, int length) { return SymbolAbstract::Builder(name, length); } static Symbol Builder(char name) { return Symbol::Builder(&name, 1); } static Symbol Ans() { return Symbol::Builder(k_ans, k_ansLength); } - static Expression UntypedBuilder(const char * name, size_t length, Context * context) { - // create an expression only if it is not in the context or defined as a symbol - Symbol s = Symbol::Builder(name, length); - if (SymbolAbstract::ValidInContext(s, context)) { - return s; - } - return Expression(); - } + static Expression UntypedBuilder(const char * name, size_t length, Context * context); + // Symbol properties bool isSystemSymbol() const { return name()[0] == SpecialSymbols::UnknownX && name()[1] == 0; } static bool isSeriesSymbol(const char * c); diff --git a/poincare/src/function.cpp b/poincare/src/function.cpp index ec7910c85..50ed7e0b2 100644 --- a/poincare/src/function.cpp +++ b/poincare/src/function.cpp @@ -100,6 +100,16 @@ Function Function::Builder(const char * name, size_t length, Expression child) { return f; } +Expression Function::UntypedBuilder(const char * name, size_t length, Expression child, Context * context) { + /* Create an expression only if it is not in the context or defined as a + * function */ + Function f = Function::Builder(name, length, child); + if (SymbolAbstract::ValidInContext(f, context)) { + return f; + } + return Expression(); +} + Expression Function::replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression) { // Replace the symbol in the child childAtIndex(0).replaceSymbolWithExpression(symbol, expression); diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index f4225c05a..0428218eb 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -139,6 +139,15 @@ Evaluation SymbolNode::templatedApproximate(Context& context, Preferences::Co return e.node()->approximate(T(), context, complexFormat, angleUnit); } +Expression Symbol::UntypedBuilder(const char * name, size_t length, Context * context) { + // create an expression only if it is not in the context or defined as a symbol + Symbol s = Symbol::Builder(name, length); + if (SymbolAbstract::ValidInContext(s, context)) { + return s; + } + return Expression(); +} + bool Symbol::isSeriesSymbol(const char * c) { // [NV][1-3] if (c[2] == 0 && (c[0] == 'N' || c[0] == 'V') && c[1] >= '1' && c[1] <= '3') { From d26c98e9d586911167727ae592512b407b840c33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 21 Feb 2019 10:52:23 +0100 Subject: [PATCH 347/373] [poincare] Fix comments --- poincare/src/addition.cpp | 2 +- poincare/src/expression.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index d9ae3cae6..98a2f4928 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -93,7 +93,7 @@ Expression Addition::shallowBeautify(Context & context, Preferences::ComplexForm * In practice, we want to turn "a+(-1)*b" into "a-b". Or, more precisely, any * "a+(-r)*b" into "a-r*b" where r is a positive Rational. * Note: the process will slightly differ if the negative product occurs on - * the first term: we want to turn "Addition(Multiplication::Builder(-1,b))" into + * the first term: we want to turn "Addition(Multiplication(-1,b))" into * "Opposite(b)". * Last but not least, special care must be taken when iterating over children * since we may remove some during the process. */ diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index b11eb1a6c..ec19edd2f 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -369,7 +369,7 @@ bool Expression::isEqualToItsApproximationLayout(Expression approximation, char * to re-serialize it because the number of stored significative * numbers and the number of displayed significative numbers might not be * identical. (For example, 0.000025 might be displayed "0.00003" and stored - * as Decimal::Builder(0.000025) and isEqualToItsApproximationLayout should return + * as Decimal(0.000025) and isEqualToItsApproximationLayout should return * false) */ Expression approximateOutput = Expression::ParseAndSimplify(buffer, context, complexFormat, angleUnit); bool equal = isIdenticalTo(approximateOutput); @@ -453,10 +453,10 @@ void Expression::simplifyAndApproximate(Expression * simplifiedExpression, Expre if (approximateExpression) { /* Step 2: Approximation * We compute the approximate expression from the Cartesian form to avoid - * unprecision. For example, if the result is the ComplexCartesian::Builder(a,b), + * unprecision. For example, if the result is the ComplexCartesian(a,b), * the final expression is goind to be sqrt(a^2+b^2)*exp(i*arctan(b/a)... * in Polar ComplexFormat. If we approximate this expression instead of - * ComplexCartesian::Builder(a,b), we are going to loose precision on the resulting + * ComplexCartesian(a,b), we are going to loose precision on the resulting * complex.*/ // Clone the ComplexCartesian to use it to compute the approximation ComplexCartesian ecomplexClone = ecomplex.clone().convert(); From a540bfa7530d5407999e6b76c624bf98b963be2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 21 Feb 2019 11:20:06 +0100 Subject: [PATCH 348/373] [poincare] Add comment TreeHandle constructor --- poincare/include/poincare/tree_handle.h | 1 + 1 file changed, 1 insertion(+) diff --git a/poincare/include/poincare/tree_handle.h b/poincare/include/poincare/tree_handle.h index 5fd9ca72e..959141249 100644 --- a/poincare/include/poincare/tree_handle.h +++ b/poincare/include/poincare/tree_handle.h @@ -105,6 +105,7 @@ public: protected: /* Constructor */ TreeHandle(const TreeNode * node); + // Un-inlining this constructor actually inscreases the firmware size TreeHandle(int nodeIndentifier = TreeNode::NoNodeIdentifier) : m_identifier(nodeIndentifier) { if (hasNode(nodeIndentifier)) { node()->retain(); From 4f1d74f44bb213c3ccdd050781b57ae527865ce0 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Tue, 5 Mar 2019 17:13:47 +0100 Subject: [PATCH 349/373] [build] Use an out-of-tree build --- .gitignore | 46 +---- Makefile | 99 +++++++--- apps/Makefile | 64 +++--- apps/calculation/Makefile | 22 +-- apps/code/Makefile | 42 ++-- apps/graph/Makefile | 44 ++--- apps/hardware_test/Makefile | 28 +-- apps/home/Makefile | 18 +- apps/on_boarding/Makefile | 15 +- apps/on_boarding/logo_controller.cpp | 1 - apps/probability/Makefile | 95 ++++----- apps/regression/Makefile | 58 +++--- apps/sequence/Makefile | 42 ++-- apps/settings/Makefile | 24 +-- apps/shared/Makefile | 174 ++++++++-------- apps/solver/Makefile | 20 +- apps/statistics/Makefile | 42 ++-- apps/usb/Makefile | 6 +- escher/Makefile | 204 ++++++++++--------- escher/image/inliner.c | 8 +- ion/Makefile | 16 +- ion/src/device/Makefile | 54 ++--- ion/src/device/bench/Makefile | 36 ++-- ion/src/device/boot/Makefile | 2 +- ion/src/device/usb/Makefile | 101 +++++----- kandinsky/Makefile | 75 +++---- liba/Makefile | 229 +++++++++++---------- liba/Makefile.bridge | 2 +- libaxx/Makefile | 7 +- poincare/Makefile | 258 ++++++++++++------------ python/Makefile | 286 +++++++++++++-------------- 31 files changed, 1071 insertions(+), 1047 deletions(-) diff --git a/.gitignore b/.gitignore index cfd17d43a..36f753c92 100644 --- a/.gitignore +++ b/.gitignore @@ -1,52 +1,8 @@ -# No objects files. -*.o -*.elf -*.exe - -# No dependency files -*.d - -# No lex / yacc generated files. -poincare/src/expression_lexer.cpp -poincare/src/expression_lexer.hpp -poincare/src/expression_parser.cpp -poincare/src/expression_parser.hpp - -# No rulegen generated files -poincare/src/simplification/rulegen/rules_tokens.h -poincare/src/simplification/rulegen/rules_lexer.cpp -poincare/src/simplification/rulegen/rules_parser.cpp -poincare/src/simplification/rulegen/rulegen -poincare/src/simplification/demo_ruleset.h - -# Font related generated files. -kandinsky/fonts/rasterizer -kandinsky/src/font_large.cpp -kandinsky/src/font_small.cpp - # No i18n headers apps/i18n.h apps/i18n.cpp -# No PicView generated files -apps/picview/image.raw -apps/picview/image.c - -# No AST file -*.ast -*.ast.json - # Quiz output quiz/src/symbols.c -# No generated icon & font files -*_icon.cpp -*_icon.h -*_font.c -*_font.h - -# Ignore inliner binary -escher/image/inliner - -# Ignore generated qtsrdefs file -python/port/genhdr/qstrdefs.generated.h +outputs diff --git a/Makefile b/Makefile index bb10ae979..b626d010b 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,28 @@ include build/config.mak -default: epsilon.$(EXE) +# Disable default Make rules +.SUFFIXES: + +OUTPUT_DIRECTORY = outputs +object_for = $(addprefix $(OUTPUT_DIRECTORY)/,$(addsuffix .o,$(basename $(1)))) + +default: $(OUTPUT_DIRECTORY)/epsilon.$(EXE) + +# Define a standard rule helper +# If passed a last parameter value of with_local_version, we also define an +# extra rule that can build source files within the $(OUTPUT_DIRECTORY). This is +# useful for rules that can be applied for intermediate objects (for example, +# when going .png -> .cpp -> .o). +define rule_for +$(addprefix $$(OUTPUT_DIRECTORY)/,$(strip $(2))): $(strip $(3)) | $$$$(@D)/. + @ echo "$(shell printf "%-8s" $(strip $(1)))$$(@:$$(OUTPUT_DIRECTORY)/%=%)" + $(Q) $(4) +ifeq ($(strip $(5)),with_local_version) +$(addprefix $$(OUTPUT_DIRECTORY)/,$(strip $(2))): $(addprefix $$(OUTPUT_DIRECTORY)/,$(strip $(3))) + @ echo "$(shell printf "%-8s" $(strip $(1)))$$(@:$$(OUTPUT_DIRECTORY)/%=%)" + $(Q) $(4) +endif +endef .PHONY: info info: @@ -10,16 +32,22 @@ info: @echo "EPSILON_APPS = $(EPSILON_APPS)" @echo "EPSILON_I18N = $(EPSILON_I18N)" -# Each sub-Makefile can either add objects to the $(objs) variable or define a -# new executable target. The $(objs) variable lists the objects that will be -# linked to every executable being generated. Each Makefile is also responsible -# for keeping the $(product) variable updated. This variable lists all files -# that could be generated during the build and that needs to be cleaned up -# afterwards. +# Since we're building out-of-tree, we need to make sure the output directories +# are created, otherwise the receipes will fail (e.g. gcc will fail to create +# "output/foo/bar.o" because the directory "output/foo" doesn't exist). +# We need to mark those directories as precious, otherwise Make will try to get +# rid of them upon completion (and fail, since those folders won't be empty). +.PRECIOUS: $(OUTPUT_DIRECTORY)/. $(OUTPUT_DIRECTORY)%/. +$(OUTPUT_DIRECTORY)/. $(OUTPUT_DIRECTORY)%/.: + $(Q) mkdir -p $(dir $@) -products := +# To make objects dependent on their directory, we need a second expansion +.SECONDEXPANSION: + +# Each sub-Makefile can either add sources to the $(src) variable or define a +# new executable target. The $(src) variable lists the sources that will be +# built and linked to every executable being generated. -# Library Makefiles ifeq ($(USE_LIBA),0) include liba/Makefile.bridge else @@ -38,39 +66,46 @@ include build/struct_layout/Makefile include build/scenario/Makefile include quiz/Makefile # Quiz needs to be included at the end -products += $(objs) +objs = $(call object_for,$(src)) -all_objs = $(filter %.o, $(products)) -dependencies = $(all_objs:.o=.d) --include $(dependencies) -products += $(dependencies) - -$(all_objs): $(generated_headers) - -epsilon.$(EXE): $(objs) -test.$(EXE): $(objs) +# Load source-based dependencies +# Compilers can generate Makefiles that states the dependencies of a given +# objet to other source and headers. This serve no purpose for a clean build, +# but allows correct yet optimal incremental builds. +-include $(objs:.o=.d) .SECONDARY: $(objs) -%.$(EXE): - @echo "LD $@" - $(Q) $(LD) $^ $(LDFLAGS) -o $@ +$(OUTPUT_DIRECTORY)/epsilon.$(EXE): $(objs) +$(OUTPUT_DIRECTORY)/test.$(EXE): $(objs) -%.o: %.c - @echo "CC $@" - $(Q) $(CC) $(SFLAGS) $(CFLAGS) -c $< -o $@ +# Define standard compilation rules -%.o: %.s - @echo "AS $@" - $(Q) $(CC) $(SFLAGS) -c $< -o $@ +$(eval $(call rule_for, \ + AS, %.o, %.s, \ + $$(CC) $$(SFLAGS) -c $$< -o $$@ \ +)) -%.o: %.cpp - @echo "CXX $@" - $(Q) $(CXX) $(SFLAGS) $(CXXFLAGS) -c $< -o $@ +$(eval $(call rule_for, \ + CC, %.o, %.c, \ + $$(CC) $$(SFLAGS) $$(CFLAGS) -c $$< -o $$@, \ + with_local_version \ +)) + +$(eval $(call rule_for, \ + CXX, %.o, %.cpp, \ + $$(CC) $$(SFLAGS) $$(CXXFLAGS) -c $$< -o $$@, \ + with_local_version \ +)) + +$(eval $(call rule_for, \ + LD, %.$$(EXE), , \ + $$(LD) $$^ $$(LDFLAGS) -o $$@ \ +)) .PHONY: clean clean: @echo "CLEAN" - $(Q) rm -f $(products) + $(Q) rm -rf $(OUTPUT_DIRECTORY) .PHONY: cowsay_% cowsay_%: diff --git a/apps/Makefile b/apps/Makefile index 98141b448..31ef222b2 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -10,26 +10,26 @@ apps = # (path to the apps header). $(foreach i,${EPSILON_APPS},$(eval include apps/$(i)/Makefile)) -app_objs += $(addprefix apps/,\ - apps_container.o\ - apps_container_storage.o\ - apps_window.o\ - battery_timer.o\ - battery_view.o\ - constant.o\ - backlight_dimming_timer.o\ - empty_battery_window.o\ - exam_pop_up_controller.o\ - global_preferences.o\ - i18n.o\ - lock_view.o\ - main.o\ - math_toolbox.o\ - shift_alpha_lock_view.o\ - suspend_timer.o\ - title_bar_view.o\ - variable_box_controller.o\ - variable_box_empty_controller.o\ +app_src += $(addprefix apps/,\ + apps_container.cpp \ + apps_container_storage.cpp \ + apps_window.cpp \ + backlight_dimming_timer.cpp \ + battery_timer.cpp \ + battery_view.cpp \ + constant.cpp \ + empty_battery_window.cpp \ + exam_pop_up_controller.cpp \ + global_preferences.cpp \ + i18n.cpp \ + lock_view.cpp \ + main.cpp \ + math_toolbox.cpp \ + shift_alpha_lock_view.cpp \ + suspend_timer.cpp \ + title_bar_view.cpp \ + variable_box_controller.cpp \ + variable_box_empty_controller.cpp \ ) snapshots_declaration = $(foreach i,$(apps),$(i)::Snapshot m_snapshot$(subst :,,$(i))Snapshot;) @@ -40,7 +40,7 @@ snapshots_count = $(words $(apps)) snapshot_includes = $(foreach i,$(app_headers),-include $(i) ) epsilon_app_names = '$(foreach i,${EPSILON_APPS},"$(i)", )' -apps/apps_container_storage.o apps/main.o: CXXFLAGS += $(snapshot_includes) -DAPPS_CONTAINER_APPS_DECLARATION="$(apps_declaration)" -DAPPS_CONTAINER_SNAPSHOT_DECLARATIONS="$(snapshots_declaration)" -DAPPS_CONTAINER_SNAPSHOT_CONSTRUCTORS="$(snapshots_construction)" -DAPPS_CONTAINER_SNAPSHOT_LIST="$(snapshots_list)" -DAPPS_CONTAINER_SNAPSHOT_COUNT=$(snapshots_count) -DEPSILON_APPS_NAMES=$(epsilon_app_names) +$(call object_for,apps/apps_container_storage.cpp apps/main.cpp): CXXFLAGS += $(snapshot_includes) -DAPPS_CONTAINER_APPS_DECLARATION="$(apps_declaration)" -DAPPS_CONTAINER_SNAPSHOT_DECLARATIONS="$(snapshots_declaration)" -DAPPS_CONTAINER_SNAPSHOT_CONSTRUCTORS="$(snapshots_construction)" -DAPPS_CONTAINER_SNAPSHOT_LIST="$(snapshots_list)" -DAPPS_CONTAINER_SNAPSHOT_COUNT=$(snapshots_count) -DEPSILON_APPS_NAMES=$(epsilon_app_names) i18n_files += $(addprefix apps/language_,$(addsuffix .universal.i18n, $(EPSILON_I18N))) @@ -68,11 +68,12 @@ apps/i18n.cpp: $(i18n_files) @echo "I18N $@" $(Q) $(PYTHON) apps/i18n.py --header $(subst .cpp,.h,$@) --implementation $@ --locales $(EPSILON_I18N) --files $^ -$(app_objs): apps/i18n.h +#$(app_objs): apps/i18n.h products += apps/i18n.h apps/i18n.cpp -app_images += apps/exam_icon.png +$(eval $(call depends_on_image,apps/title_bar_view.cpp,apps/exam_icon.png)) + # Tracking which source file uses which image is painful. But we need to ensure # that a .png file has been inlined before building any source file that uses @@ -80,15 +81,20 @@ app_images += apps/exam_icon.png # As a shortcut, we simply say that every app file depends on every image. In # practice, this forces all the images to be before the app. -app_image_objs := $(app_images:.png=.o) -.SECONDARY: $(app_images:.png=.cpp) -$(app_objs): $(app_image_objs) +#app_image_objs := $(OUTPUT_DIRECTORY)/$(app_images:.png=.o) +#.SECONDARY: $(OUTPUT_DIRECTORY)/$(app_images:.png=.cpp) +#$(app_objs): $(app_image_objs) +#app_image_src := $(app_images:.png=.cpp) -epsilon.$(EXE): $(app_objs) $(app_image_objs) +#epsilon.$(EXE): $(app_objs) $(app_image_objs) +#app_objs = $(call object_for,$(app_src)) + +#epsilon.$(EXE): $(app_objs) + +src += $(app_src) +#$(app_image_src) TO_REMOVE := apps/main.o apps/i18n.o TMP := $(app_objs) $(app_image_objs) VAR := $(filter-out $(TO_REMOVE), $(TMP)) test.$(EXE): $(VAR) - -products += epsilon.$(EXE) $(app_objs) $(call INLINER_PRODUCTS,$(app_images)) diff --git a/apps/calculation/Makefile b/apps/calculation/Makefile index 7b797bea7..c8960bb30 100644 --- a/apps/calculation/Makefile +++ b/apps/calculation/Makefile @@ -1,16 +1,16 @@ apps += Calculation::App app_headers += apps/calculation/app.h -app_objs += $(addprefix apps/calculation/,\ - app.o\ - calculation.o\ - calculation_store.o\ - edit_expression_controller.o\ - expression_field.o\ - history_view_cell.o\ - history_controller.o\ - scrollable_expression_view.o\ - selectable_table_view.o\ +app_src += $(addprefix apps/calculation/,\ + app.cpp \ + calculation.cpp \ + calculation_store.cpp \ + edit_expression_controller.cpp \ + expression_field.cpp \ + history_view_cell.cpp \ + history_controller.cpp \ + scrollable_expression_view.cpp \ + selectable_table_view.cpp \ ) i18n_files += $(addprefix apps/calculation/,\ @@ -25,4 +25,4 @@ tests += $(addprefix apps/calculation/test/,\ calculation_store.cpp\ ) -app_images += apps/calculation/calculation_icon.png +$(eval $(call depends_on_image,apps/calculation/app.cpp,apps/calculation/calculation_icon.png)) diff --git a/apps/code/Makefile b/apps/code/Makefile index 25b63e4ee..891aa24d2 100644 --- a/apps/code/Makefile +++ b/apps/code/Makefile @@ -1,26 +1,26 @@ apps += Code::App app_headers += apps/code/app.h -app_objs += $(addprefix apps/code/,\ - app.o\ - console_controller.o\ - console_edit_cell.o\ - console_line_cell.o\ - console_store.o\ - editor_controller.o\ - editor_view.o\ - helpers.o\ - menu_controller.o\ - python_toolbox.o\ - python_text_area.o\ - sandbox_controller.o\ - script.o\ - script_name_cell.o\ - script_node_cell.o\ - script_parameter_controller.o\ - script_store.o\ - script_template.o\ - variable_box_controller.o\ +app_src += $(addprefix apps/code/,\ + app.cpp \ + console_controller.cpp \ + console_edit_cell.cpp \ + console_line_cell.cpp \ + console_store.cpp \ + editor_controller.cpp \ + editor_view.cpp \ + helpers.cpp \ + menu_controller.cpp \ + python_toolbox.cpp \ + python_text_area.cpp \ + sandbox_controller.cpp \ + script.cpp \ + script_name_cell.cpp \ + script_node_cell.cpp \ + script_parameter_controller.cpp \ + script_store.cpp \ + script_template.cpp \ + variable_box_controller.cpp \ ) i18n_files += $(addprefix apps/code/,\ @@ -44,4 +44,4 @@ i18n_files += $(addprefix apps/code/,\ toolbox.universal.i18n\ ) -app_images += apps/code/code_icon.png +$(eval $(call depends_on_image,apps/code/app.cpp,apps/code/code_icon.png)) diff --git a/apps/graph/Makefile b/apps/graph/Makefile index 9c631beff..8e7b1ef68 100644 --- a/apps/graph/Makefile +++ b/apps/graph/Makefile @@ -1,27 +1,27 @@ apps += Graph::App app_headers += apps/graph/app.h -app_objs += $(addprefix apps/graph/,\ - app.o\ - storage_cartesian_function_store.o\ - graph/banner_view.o\ - graph/calculation_graph_controller.o\ - graph/calculation_parameter_controller.o\ - graph/curve_parameter_controller.o\ - graph/extremum_graph_controller.o\ - graph/graph_controller.o\ - graph/graph_controller_helper.o\ - graph/graph_view.o\ - graph/integral_graph_controller.o\ - graph/intersection_graph_controller.o\ - graph/root_graph_controller.o\ - graph/tangent_graph_controller.o\ - list/list_parameter_controller.o\ - list/storage_list_controller.o\ - list/text_field_function_title_cell.o\ - values/storage_derivative_parameter_controller.o\ - values/storage_function_parameter_controller.o\ - values/storage_values_controller.o\ +app_src += $(addprefix apps/graph/,\ + app.cpp \ + storage_cartesian_function_store.cpp \ + graph/banner_view.cpp \ + graph/calculation_graph_controller.cpp \ + graph/calculation_parameter_controller.cpp \ + graph/curve_parameter_controller.cpp \ + graph/extremum_graph_controller.cpp \ + graph/graph_controller.cpp \ + graph/graph_controller_helper.cpp \ + graph/graph_view.cpp \ + graph/integral_graph_controller.cpp \ + graph/intersection_graph_controller.cpp \ + graph/root_graph_controller.cpp \ + graph/tangent_graph_controller.cpp \ + list/list_parameter_controller.cpp \ + list/storage_list_controller.cpp \ + list/text_field_function_title_cell.cpp \ + values/storage_derivative_parameter_controller.cpp \ + values/storage_function_parameter_controller.cpp \ + values/storage_values_controller.cpp \ ) i18n_files += $(addprefix apps/graph/,\ @@ -32,4 +32,4 @@ i18n_files += $(addprefix apps/graph/,\ base.pt.i18n\ ) -app_images += apps/graph/graph_icon.png +$(eval $(call depends_on_image,apps/graph/app.cpp,apps/graph/graph_icon.png)) diff --git a/apps/hardware_test/Makefile b/apps/hardware_test/Makefile index 209104e22..f6a490b0d 100644 --- a/apps/hardware_test/Makefile +++ b/apps/hardware_test/Makefile @@ -1,15 +1,15 @@ -app_objs += $(addprefix apps/hardware_test/,\ - app.o\ - arrow_view.o\ - battery_test_controller.o\ - code_128b_view.o\ - keyboard_test_controller.o\ - keyboard_view.o\ - led_test_controller.o\ - pattern.o\ - pattern_view.o\ - pop_up_controller.o\ - screen_test_controller.o\ - screen_test_controller.o\ - serial_number_controller.o\ +app_src += $(addprefix apps/hardware_test/,\ + app.cpp \ + arrow_view.cpp \ + battery_test_controller.cpp \ + code_128b_view.cpp \ + keyboard_test_controller.cpp \ + keyboard_view.cpp \ + led_test_controller.cpp \ + pattern.cpp \ + pattern_view.cpp \ + pop_up_controller.cpp \ + screen_test_controller.cpp \ + screen_test_controller.cpp \ + serial_number_controller.cpp \ ) diff --git a/apps/home/Makefile b/apps/home/Makefile index ac3e309e1..b6c5428b9 100644 --- a/apps/home/Makefile +++ b/apps/home/Makefile @@ -1,13 +1,13 @@ -app_objs += $(addprefix apps/home/,\ - app.o\ - app_cell.o\ - controller.o\ +app_src += $(addprefix apps/home/,\ + app.cpp \ + app_cell.cpp \ + controller.cpp \ ) i18n_files += $(addprefix apps/home/,\ - base.de.i18n\ - base.en.i18n\ - base.es.i18n\ - base.fr.i18n\ - base.pt.i18n\ + base.de.i18n \ + base.en.i18n \ + base.es.i18n \ + base.fr.i18n \ + base.pt.i18n \ ) diff --git a/apps/on_boarding/Makefile b/apps/on_boarding/Makefile index b11b5d216..c013f074e 100644 --- a/apps/on_boarding/Makefile +++ b/apps/on_boarding/Makefile @@ -1,9 +1,9 @@ -app_objs += $(addprefix apps/on_boarding/,\ - app.o\ - language_controller.o\ - logo_controller.o\ - logo_view.o\ - pop_up_controller.o\ +app_src += $(addprefix apps/on_boarding/,\ + app.cpp \ + language_controller.cpp \ + logo_controller.cpp \ + logo_view.cpp \ + pop_up_controller.cpp \ ) i18n_files += $(addprefix apps/on_boarding/,\ @@ -14,5 +14,4 @@ i18n_files += $(addprefix apps/on_boarding/,\ base.pt.i18n\ ) -app_images += apps/on_boarding/logo_icon.png - +$(eval $(call depends_on_image,apps/on_boarding/logo_view.cpp,apps/on_boarding/logo_icon.png)) diff --git a/apps/on_boarding/logo_controller.cpp b/apps/on_boarding/logo_controller.cpp index 9fa2f10cb..3068da16c 100644 --- a/apps/on_boarding/logo_controller.cpp +++ b/apps/on_boarding/logo_controller.cpp @@ -1,5 +1,4 @@ #include "logo_controller.h" -#include "logo_icon.h" namespace OnBoarding { diff --git a/apps/probability/Makefile b/apps/probability/Makefile index 8093a11a1..2087afa1c 100644 --- a/apps/probability/Makefile +++ b/apps/probability/Makefile @@ -1,30 +1,30 @@ apps += Probability::App app_headers += apps/probability/app.h -app_objs += $(addprefix apps/probability/,\ - app.o\ - calculation/calculation.o\ - calculation/discrete_calculation.o\ - calculation/left_integral_calculation.o\ - calculation/right_integral_calculation.o\ - calculation/finite_integral_calculation.o\ - calculation_controller.o\ - calculation_cell.o\ - calculation_type_controller.o\ - cell.o\ - image_cell.o\ - law/binomial_law.o\ - law/erf_inv.o\ - law/exponential_law.o\ - law/law.o\ - law/normal_law.o\ - law/poisson_law.o\ - law/two_parameter_law.o\ - law/uniform_law.o\ - law_controller.o\ - law_curve_view.o\ - parameters_controller.o\ - responder_image_cell.o\ +app_src += $(addprefix apps/probability/,\ + app.cpp \ + calculation/calculation.cpp \ + calculation/discrete_calculation.cpp \ + calculation/left_integral_calculation.cpp \ + calculation/right_integral_calculation.cpp \ + calculation/finite_integral_calculation.cpp \ + calculation_controller.cpp \ + calculation_cell.cpp \ + calculation_type_controller.cpp \ + cell.cpp \ + image_cell.cpp \ + law/binomial_law.cpp \ + law/erf_inv.cpp \ + law/exponential_law.cpp \ + law/law.cpp \ + law/normal_law.cpp \ + law/poisson_law.cpp \ + law/two_parameter_law.cpp \ + law/uniform_law.cpp \ + law_controller.cpp \ + law_curve_view.cpp \ + parameters_controller.cpp \ + responder_image_cell.cpp \ ) i18n_files += $(addprefix apps/probability/,\ @@ -39,25 +39,30 @@ tests += $(addprefix apps/probability/test/,\ erf_inv.cpp\ ) -app_images += apps/probability/probability_icon.png +# Image dependencies -app_images += $(addprefix apps/probability/images/,\ - binomial_icon.png\ - calcul1_icon.png\ - calcul2_icon.png\ - calcul3_icon.png\ - calcul4_icon.png\ - exponential_icon.png\ - focused_binomial_icon.png\ - focused_calcul1_icon.png\ - focused_calcul2_icon.png\ - focused_calcul3_icon.png\ - focused_calcul4_icon.png\ - focused_exponential_icon.png\ - focused_normal_icon.png\ - focused_poisson_icon.png\ - focused_uniform_icon.png\ - normal_icon.png\ - poisson_icon.png\ - uniform_icon.png\ -) +$(eval $(call depends_on_image,apps/probability/app.cpp,apps/probability/probability_icon.png)) + +$(eval $(call depends_on_image,apps/probability/law_controller.cpp,$(addprefix apps/probability/images/, \ + binomial_icon.png \ + exponential_icon.png \ + focused_binomial_icon.png \ + focused_exponential_icon.png \ + focused_normal_icon.png \ + focused_poisson_icon.png \ + focused_uniform_icon.png \ + normal_icon.png \ + poisson_icon.png \ + uniform_icon.png \ +))) + +$(eval $(call depends_on_image,$(addprefix apps/probability/,calculation_type_controller.cpp calculation_controller.cpp),$(addprefix apps/probability/images/, \ + calcul1_icon.png \ + calcul2_icon.png \ + calcul3_icon.png \ + calcul4_icon.png \ + focused_calcul1_icon.png \ + focused_calcul2_icon.png \ + focused_calcul3_icon.png \ + focused_calcul4_icon.png \ +))) diff --git a/apps/regression/Makefile b/apps/regression/Makefile index 3065bc27f..450d3a471 100644 --- a/apps/regression/Makefile +++ b/apps/regression/Makefile @@ -1,36 +1,36 @@ apps += Regression::App app_headers += apps/regression/app.h -app_objs += $(addprefix apps/regression/,\ - app.o\ - banner_view.o\ - calculation_controller.o\ - column_title_cell.o\ - even_odd_buffer_text_cell_with_margin.o\ - even_odd_double_buffer_text_cell_with_separator.o\ - go_to_parameter_controller.o\ - graph_controller.o\ - graph_options_controller.o\ - graph_view.o\ - initialisation_parameter_controller.o\ - regression_context.o\ - regression_controller.o\ - store.o\ - store_controller.o\ - store_parameter_controller.o\ +app_src += $(addprefix apps/regression/,\ + app.cpp \ + banner_view.cpp \ + calculation_controller.cpp \ + column_title_cell.cpp \ + even_odd_buffer_text_cell_with_margin.cpp \ + even_odd_double_buffer_text_cell_with_separator.cpp \ + go_to_parameter_controller.cpp \ + graph_controller.cpp \ + graph_options_controller.cpp \ + graph_view.cpp \ + initialisation_parameter_controller.cpp \ + regression_context.cpp \ + regression_controller.cpp \ + store.cpp \ + store_controller.cpp \ + store_parameter_controller.cpp \ ) -app_objs += $(addprefix apps/regression/model/,\ - cubic_model.o\ - exponential_model.o\ - linear_model.o\ - logarithmic_model.o\ - logistic_model.o\ - model.o\ - power_model.o\ - quadratic_model.o\ - quartic_model.o\ - trigonometric_model.o\ +app_src += $(addprefix apps/regression/model/,\ + cubic_model.cpp \ + exponential_model.cpp \ + linear_model.cpp \ + logarithmic_model.cpp \ + logistic_model.cpp \ + model.cpp \ + power_model.cpp \ + quadratic_model.cpp \ + quartic_model.cpp \ + trigonometric_model.cpp \ ) i18n_files += $(addprefix apps/regression/,\ @@ -46,4 +46,4 @@ tests += $(addprefix apps/regression/test/,\ model.cpp\ ) -app_images += apps/regression/regression_icon.png +$(eval $(call depends_on_image,apps/regression/app.cpp,apps/regression/regression_icon.png)) diff --git a/apps/sequence/Makefile b/apps/sequence/Makefile index 76354d74c..149b48e4e 100644 --- a/apps/sequence/Makefile +++ b/apps/sequence/Makefile @@ -1,26 +1,26 @@ apps += Sequence::App app_headers += apps/sequence/app.h -app_objs += $(addprefix apps/sequence/,\ - app.o\ - graph/banner_view.o\ - graph/curve_parameter_controller.o\ - graph/curve_view_range.o\ - graph/go_to_parameter_controller.o\ - graph/graph_controller.o\ - graph/graph_view.o\ - graph/term_sum_controller.o\ - list/list_controller.o\ - list/list_parameter_controller.o\ - list/sequence_toolbox.o\ - list/type_parameter_controller.o\ - values/interval_parameter_controller.o\ - values/values_controller.o\ - cache_context.o\ - sequence.o\ - sequence_context.o\ - sequence_store.o\ - sequence_title_cell.o\ +app_src += $(addprefix apps/sequence/,\ + app.cpp \ + graph/banner_view.cpp \ + graph/curve_parameter_controller.cpp \ + graph/curve_view_range.cpp \ + graph/go_to_parameter_controller.cpp \ + graph/graph_controller.cpp \ + graph/graph_view.cpp \ + graph/term_sum_controller.cpp \ + list/list_controller.cpp \ + list/list_parameter_controller.cpp \ + list/sequence_toolbox.cpp \ + list/type_parameter_controller.cpp \ + values/interval_parameter_controller.cpp \ + values/values_controller.cpp \ + cache_context.cpp \ + sequence.cpp \ + sequence_context.cpp \ + sequence_store.cpp \ + sequence_title_cell.cpp \ ) i18n_files += $(addprefix apps/sequence/,\ @@ -35,4 +35,4 @@ tests += $(addprefix apps/sequence/test/,\ sequence.cpp\ ) -app_images += apps/sequence/sequence_icon.png +$(eval $(call depends_on_image,apps/sequence/app.cpp,apps/sequence/sequence_icon.png)) diff --git a/apps/settings/Makefile b/apps/settings/Makefile index d19995855..7061f6951 100644 --- a/apps/settings/Makefile +++ b/apps/settings/Makefile @@ -1,17 +1,17 @@ apps += Settings::App app_headers += apps/settings/app.h -app_objs += $(addprefix apps/settings/,\ - app.o\ - main_controller.o\ - settings_message_tree.o\ - sub_menu/about_controller.o\ - sub_menu/display_mode_controller.o\ - sub_menu/exam_mode_controller.o\ - sub_menu/generic_sub_controller.o\ - sub_menu/language_controller.o\ - sub_menu/message_table_cell_with_editable_text_with_separator.o\ - sub_menu/preferences_controller.o\ +app_src += $(addprefix apps/settings/,\ + app.cpp \ + main_controller.cpp \ + settings_message_tree.cpp \ + sub_menu/about_controller.cpp \ + sub_menu/display_mode_controller.cpp \ + sub_menu/exam_mode_controller.cpp \ + sub_menu/generic_sub_controller.cpp \ + sub_menu/language_controller.cpp \ + sub_menu/message_table_cell_with_editable_text_with_separator.cpp \ + sub_menu/preferences_controller.cpp \ ) i18n_files += $(addprefix apps/settings/,\ @@ -22,4 +22,4 @@ i18n_files += $(addprefix apps/settings/,\ base.pt.i18n\ ) -app_images += apps/settings/settings_icon.png +$(eval $(call depends_on_image,apps/settings/app.cpp,apps/settings/settings_icon.png)) diff --git a/apps/shared/Makefile b/apps/shared/Makefile index db1d6dd7f..93e7e4d52 100644 --- a/apps/shared/Makefile +++ b/apps/shared/Makefile @@ -1,88 +1,88 @@ -app_objs += $(addprefix apps/shared/,\ - banner_view.o\ - buffer_function_title_cell.o\ - buffer_text_view_with_text_field.o\ - button_with_separator.o\ - cursor_view.o\ - curve_view.o\ - curve_view_cursor.o\ - curve_view_range.o\ - double_pair_store.o\ - editable_cell_table_view_controller.o\ - expression_field_delegate_app.o\ - expression_model.o\ - expression_model_list_controller.o\ - expression_model_store.o\ - float_parameter_controller.o\ - function.o\ - function_app.o\ - function_banner_delegate.o\ - function_curve_parameter_controller.o\ - function_expression_cell.o\ - function_go_to_parameter_controller.o\ - function_graph_view.o\ - function_graph_controller.o\ - function_list_controller.o\ - function_store.o\ - function_title_cell.o\ - global_context.o\ - go_to_parameter_controller.o\ - hideable_even_odd_cell.o\ - hideable_even_odd_editable_text_cell.o\ - initialisation_parameter_controller.o\ - input_event_handler_delegate_app.o\ - interactive_curve_view_controller.o\ - interactive_curve_view_range.o\ - interactive_curve_view_range_delegate.o\ - interval.o\ - interval_parameter_controller.o\ - language_controller.o\ - layout_field_delegate.o\ - list_parameter_controller.o\ - margin_even_odd_message_text_cell.o\ - memoized_curve_view_range.o\ - message_view.o\ - ok_view.o\ - parameter_text_field_delegate.o\ - range_parameter_controller.o\ - regular_table_view_data_source.o\ - round_cursor_view.o\ - scrollable_exact_approximate_expressions_cell.o\ - scrollable_exact_approximate_expressions_view.o\ - separator_even_odd_buffer_text_cell.o\ - simple_interactive_curve_view_controller.o\ - storage_cartesian_function.o\ - storage_expression_model.o\ - storage_expression_model_store.o\ - storage_expression_model_list_controller.o\ - storage_function.o\ - storage_function_app.o\ - storage_function_banner_delegate.o\ - storage_function_curve_parameter_controller.o\ - storage_function_go_to_parameter_controller.o\ - storage_function_graph_controller.o\ - storage_function_graph_view.o\ - storage_function_list_controller.o\ - storage_function_store.o\ - storage_list_parameter_controller.o\ - storage_sum_graph_controller.o\ - storage_values_function_parameter_controller.o\ - storage_values_controller.o\ - store_cell.o\ - store_context.o\ - store_controller.o\ - store_parameter_controller.o\ - store_selectable_table_view.o\ - store_title_cell.o\ - sum_graph_controller.o\ - tab_table_controller.o\ - text_field_delegate.o\ - text_field_delegate_app.o\ - text_field_with_extension.o\ - toolbox_helpers.o\ - values_function_parameter_controller.o\ - values_parameter_controller.o\ - values_controller.o\ - vertical_cursor_view.o\ - zoom_parameter_controller.o\ +app_src += $(addprefix apps/shared/,\ + banner_view.cpp \ + buffer_function_title_cell.cpp \ + buffer_text_view_with_text_field.cpp \ + button_with_separator.cpp \ + cursor_view.cpp \ + curve_view.cpp \ + curve_view_cursor.cpp \ + curve_view_range.cpp \ + double_pair_store.cpp \ + editable_cell_table_view_controller.cpp \ + expression_field_delegate_app.cpp \ + expression_model.cpp \ + expression_model_list_controller.cpp \ + expression_model_store.cpp \ + float_parameter_controller.cpp \ + function.cpp \ + function_app.cpp \ + function_banner_delegate.cpp \ + function_curve_parameter_controller.cpp \ + function_expression_cell.cpp \ + function_go_to_parameter_controller.cpp \ + function_graph_controller.cpp \ + function_graph_view.cpp \ + function_list_controller.cpp \ + function_store.cpp \ + function_title_cell.cpp \ + global_context.cpp \ + go_to_parameter_controller.cpp \ + hideable_even_odd_cell.cpp \ + hideable_even_odd_editable_text_cell.cpp \ + initialisation_parameter_controller.cpp \ + input_event_handler_delegate_app.cpp \ + interactive_curve_view_controller.cpp \ + interactive_curve_view_range.cpp \ + interactive_curve_view_range_delegate.cpp \ + interval.cpp \ + interval_parameter_controller.cpp \ + language_controller.cpp \ + layout_field_delegate.cpp \ + list_parameter_controller.cpp \ + margin_even_odd_message_text_cell.cpp \ + memoized_curve_view_range.cpp \ + message_view.cpp \ + ok_view.cpp \ + parameter_text_field_delegate.cpp \ + range_parameter_controller.cpp \ + regular_table_view_data_source.cpp \ + round_cursor_view.cpp \ + scrollable_exact_approximate_expressions_cell.cpp \ + scrollable_exact_approximate_expressions_view.cpp \ + separator_even_odd_buffer_text_cell.cpp \ + simple_interactive_curve_view_controller.cpp \ + storage_cartesian_function.cpp \ + storage_expression_model.cpp \ + storage_expression_model_list_controller.cpp \ + storage_expression_model_store.cpp \ + storage_function.cpp \ + storage_function_app.cpp \ + storage_function_banner_delegate.cpp \ + storage_function_curve_parameter_controller.cpp \ + storage_function_go_to_parameter_controller.cpp \ + storage_function_graph_controller.cpp \ + storage_function_graph_view.cpp \ + storage_function_list_controller.cpp \ + storage_function_store.cpp \ + storage_list_parameter_controller.cpp \ + storage_sum_graph_controller.cpp \ + storage_values_controller.cpp \ + storage_values_function_parameter_controller.cpp \ + store_cell.cpp \ + store_context.cpp \ + store_controller.cpp \ + store_parameter_controller.cpp \ + store_selectable_table_view.cpp \ + store_title_cell.cpp \ + sum_graph_controller.cpp \ + tab_table_controller.cpp \ + text_field_delegate.cpp \ + text_field_delegate_app.cpp \ + text_field_with_extension.cpp \ + toolbox_helpers.cpp \ + values_controller.cpp \ + values_function_parameter_controller.cpp \ + values_parameter_controller.cpp \ + vertical_cursor_view.cpp \ + zoom_parameter_controller.cpp \ ) diff --git a/apps/solver/Makefile b/apps/solver/Makefile index a15ab0b36..a87822ad6 100644 --- a/apps/solver/Makefile +++ b/apps/solver/Makefile @@ -1,15 +1,15 @@ apps += Solver::App app_headers += apps/solver/app.h -app_objs += $(addprefix apps/solver/,\ - app.o\ - equation_models_parameter_controller.o\ - equation.o\ - equation_list_view.o\ - equation_store.o\ - interval_controller.o\ - list_controller.o\ - solutions_controller.o\ +app_src += $(addprefix apps/solver/,\ + app.cpp \ + equation_models_parameter_controller.cpp \ + equation.cpp \ + equation_list_view.cpp \ + equation_store.cpp \ + interval_controller.cpp \ + list_controller.cpp \ + solutions_controller.cpp \ ) i18n_files += $(addprefix apps/solver/,\ @@ -24,4 +24,4 @@ tests += $(addprefix apps/solver/test/,\ equation_store.cpp\ ) -app_images += apps/solver/solver_icon.png +$(eval $(call depends_on_image,apps/solver/app.cpp,apps/solver/solver_icon.png)) diff --git a/apps/statistics/Makefile b/apps/statistics/Makefile index 424fb48c0..8e5fa5b7d 100644 --- a/apps/statistics/Makefile +++ b/apps/statistics/Makefile @@ -1,26 +1,26 @@ apps += Statistics::App app_headers += apps/statistics/app.h -app_objs += $(addprefix apps/statistics/,\ - app.o\ - box_axis_view.o\ - box_banner_view.o\ - box_controller.o\ - box_range.o\ - box_view.o\ - calculation_controller.o\ - calculation_selectable_table_view.o\ - histogram_banner_view.o\ - histogram_controller.o\ - histogram_parameter_controller.o\ - histogram_view.o\ - multiple_boxes_view.o\ - multiple_data_view.o\ - multiple_data_view_controller.o\ - multiple_histograms_view.o\ - statistics_context.o\ - store.o\ - store_controller.o\ +app_src += $(addprefix apps/statistics/,\ + app.cpp \ + box_axis_view.cpp \ + box_banner_view.cpp \ + box_controller.cpp \ + box_range.cpp \ + box_view.cpp \ + calculation_controller.cpp \ + calculation_selectable_table_view.cpp \ + histogram_banner_view.cpp \ + histogram_controller.cpp \ + histogram_parameter_controller.cpp \ + histogram_view.cpp \ + multiple_boxes_view.cpp \ + multiple_data_view.cpp \ + multiple_data_view_controller.cpp \ + multiple_histograms_view.cpp \ + statistics_context.cpp \ + store.cpp \ + store_controller.cpp \ ) i18n_files += $(addprefix apps/statistics/,\ @@ -35,4 +35,4 @@ tests += $(addprefix apps/statistics/test/,\ store.cpp\ ) -app_images += apps/statistics/stat_icon.png +$(eval $(call depends_on_image,apps/statistics/app.cpp,apps/statistics/stat_icon.png)) diff --git a/apps/usb/Makefile b/apps/usb/Makefile index 0bb37aa5f..45c6e0d8d 100644 --- a/apps/usb/Makefile +++ b/apps/usb/Makefile @@ -1,6 +1,6 @@ -app_objs += $(addprefix apps/usb/,\ - app.o\ - usb_connected_controller.o\ +app_src += $(addprefix apps/usb/,\ + app.cpp \ + usb_connected_controller.cpp \ ) i18n_files += $(addprefix apps/usb/,\ diff --git a/escher/Makefile b/escher/Makefile index 3c96dcd46..12aee399e 100644 --- a/escher/Makefile +++ b/escher/Makefile @@ -1,102 +1,118 @@ SFLAGS += -Iescher/include -objs += $(addprefix escher/src/,\ - alternate_empty_view_controller.o\ - app.o\ - bank_view_controller.o\ - buffer_text_view.o\ - button.o\ - button_row_controller.o\ - chevron_view.o\ - clipboard.o\ - container.o\ - editable_text_cell.o\ - ellipsis_view.o\ - expression_field.o\ - even_odd_cell.o\ - even_odd_cell_with_ellipsis.o\ - even_odd_buffer_text_cell.o\ - even_odd_editable_text_cell.o\ - even_odd_expression_cell.o\ - even_odd_message_text_cell.o\ - expression_table_cell.o\ - expression_table_cell_with_pointer.o\ - expression_table_cell_with_expression.o\ - expression_view.o\ - highlight_cell.o\ - gauge_view.o\ - image_view.o\ - input_event_handler.o\ - invocation.o\ - input_view_controller.o\ - key_view.o\ - layout_field.o\ - list_view_data_source.o\ - message_table_cell.o\ - message_table_cell_with_buffer.o\ - message_table_cell_with_chevron.o\ - message_table_cell_with_chevron_and_message.o\ - message_table_cell_with_chevron_and_expression.o\ - message_table_cell_with_editable_text.o\ - message_table_cell_with_expression.o\ - message_table_cell_with_gauge.o\ - message_table_cell_with_message.o\ - message_table_cell_with_switch.o\ - message_text_view.o\ - message_tree.o\ - modal_view_controller.o\ - nested_menu_controller.o\ - palette.o\ - pointer_text_view.o\ - responder.o\ - run_loop.o\ - scroll_view.o\ - scroll_view_data_source.o\ - scroll_view_indicator.o\ - scrollable_view.o\ - selectable_table_view.o\ - selectable_table_view_data_source.o\ - selectable_table_view_delegate.o\ - simple_list_view_data_source.o\ - simple_table_view_data_source.o\ - solid_color_view.o\ - solid_text_area.o\ - stack_view.o\ - stack_view_controller.o\ - switch_view.o\ - tab_view.o\ - tab_view_cell.o\ - tab_view_controller.o\ - tab_view_data_source.o\ - table_cell.o\ - table_view.o\ - table_view_data_source.o\ - text_cursor_view.o\ - text_area.o\ - text_field.o\ - text_input.o\ - text_input_helpers.o\ - text_view.o\ - tiled_view.o\ - timer.o\ - toolbox.o\ - transparent_view.o\ - view.o\ - view_controller.o\ - warning_controller.o\ - window.o\ +src += $(addprefix escher/src/,\ + alternate_empty_view_controller.cpp \ + app.cpp \ + bank_view_controller.cpp \ + buffer_text_view.cpp \ + button.cpp \ + button_row_controller.cpp \ + chevron_view.cpp \ + clipboard.cpp \ + container.cpp \ + editable_text_cell.cpp \ + ellipsis_view.cpp \ + expression_field.cpp \ + even_odd_cell.cpp \ + even_odd_cell_with_ellipsis.cpp \ + even_odd_buffer_text_cell.cpp \ + even_odd_editable_text_cell.cpp \ + even_odd_expression_cell.cpp \ + even_odd_message_text_cell.cpp \ + expression_table_cell.cpp \ + expression_table_cell_with_pointer.cpp \ + expression_table_cell_with_expression.cpp \ + expression_view.cpp \ + highlight_cell.cpp \ + gauge_view.cpp \ + image_view.cpp \ + input_event_handler.cpp \ + invocation.cpp \ + input_view_controller.cpp \ + key_view.cpp \ + layout_field.cpp \ + list_view_data_source.cpp \ + message_table_cell.cpp \ + message_table_cell_with_buffer.cpp \ + message_table_cell_with_chevron.cpp \ + message_table_cell_with_chevron_and_message.cpp \ + message_table_cell_with_chevron_and_expression.cpp \ + message_table_cell_with_editable_text.cpp \ + message_table_cell_with_expression.cpp \ + message_table_cell_with_gauge.cpp \ + message_table_cell_with_message.cpp \ + message_table_cell_with_switch.cpp \ + message_text_view.cpp \ + message_tree.cpp \ + modal_view_controller.cpp \ + nested_menu_controller.cpp \ + palette.cpp \ + pointer_text_view.cpp \ + responder.cpp \ + run_loop.cpp \ + scroll_view.cpp \ + scroll_view_data_source.cpp \ + scroll_view_indicator.cpp \ + scrollable_view.cpp \ + selectable_table_view.cpp \ + selectable_table_view_data_source.cpp \ + selectable_table_view_delegate.cpp \ + simple_list_view_data_source.cpp \ + simple_table_view_data_source.cpp \ + solid_color_view.cpp \ + solid_text_area.cpp \ + stack_view.cpp \ + stack_view_controller.cpp \ + switch_view.cpp \ + tab_view.cpp \ + tab_view_cell.cpp \ + tab_view_controller.cpp \ + tab_view_data_source.cpp \ + table_cell.cpp \ + table_view.cpp \ + table_view_data_source.cpp \ + text_cursor_view.cpp \ + text_area.cpp \ + text_field.cpp \ + text_input.cpp \ + text_input_helpers.cpp \ + text_view.cpp \ + tiled_view.cpp \ + timer.cpp \ + toolbox.cpp \ + transparent_view.cpp \ + view.cpp \ + view_controller.cpp \ + warning_controller.cpp \ + window.cpp \ ) -INLINER := escher/image/inliner -$(INLINER): escher/image/inliner.c $(addprefix ion/src/external/lz4/, lz4.c lz4hc.c) - @echo "HOSTCC $@" - $(Q) $(HOSTCC) -std=c99 `libpng-config --cflags` $^ `libpng-config --ldflags` -o $@ +$(eval $(call rule_for, \ + HOSTCC, \ + escher/image/inliner, \ + escher/image/inliner.c $(addprefix ion/src/external/lz4/, lz4.c lz4hc.c), \ + $$(HOSTCC) -std=c99 `libpng-config --cflags` $$^ `libpng-config --ldflags` -o $$@ \ +)) -%.h %.cpp : %.png $(INLINER) - @echo "INLINER $@" - $(Q) $(INLINER) $< +INLINER := $(OUTPUT_DIRECTORY)/escher/image/inliner -INLINER_PRODUCTS = $(1:.png=.h) $(1:.png=.cpp) $(1:.png=.o) +.PRECIOUS: $(OUTPUT_DIRECTORY)/%.h $(OUTPUT_DIRECTORY)/%.cpp +$(eval $(call rule_for, \ + INLINER, \ + %.h %.cpp, \ + %.png $$(INLINER), \ + $$(INLINER) $$< $$(basename $$@).h $$(basename $$@).cpp \ +)) -products += $(INLINER) +# Mark a .cpp file as depending on a .png one +# This is called with $1 = code.cpp and $2 = image.png +# First, we mark code.o as requiring image.o. Rules will take care of inlining +# the PNG and building the inlined cpp file. Second, we add the directory +# corresponding to the one of code.cpp in the output dir as a header search +# path. Since $1 can be a list, we have to map with foreach. +define depends_on_image +$(call object_for,$(1)): $(call object_for,$(2)) +$(call object_for,$(1)): SFLAGS += $(foreach d,$(sort $(dir $(call object_for,$(1)))),-I$(d)) +src += $(2) +endef diff --git a/escher/image/inliner.c b/escher/image/inliner.c index 4f3a4290b..67d983feb 100644 --- a/escher/image/inliner.c +++ b/escher/image/inliner.c @@ -16,7 +16,7 @@ #include #include "../../ion/src/external/lz4/lz4hc.h" -#define ERROR_IF(cond, message) if (cond) { printf(message); return -1; }; +#define ERROR_IF(cond, message) if (cond) { printf(message "\n"); return -1; }; #define MAX_FILENAME_LENGTH 255 void generateHeaderFromImage(FILE * file, const char * guardian, const char * variable); @@ -29,7 +29,7 @@ void camelCaseNameFromSnakeCaseNames(const char * snakeCaseName, const char * up // TODO: truncate the app image dimensions to 55x56 pixels int main(int argc, char * argv[]) { - ERROR_IF(argc != 2, "Usage: inliner source.png"); + ERROR_IF(argc != 4, "Usage: inliner source.png output.h output.cpp"); const char * inputPath = argv[1]; FILE * inputFile = fopen(inputPath, "rb"); @@ -79,6 +79,7 @@ int main(int argc, char * argv[]) { snakeCaseNameToUpperSnakeName(lowerSnakeCaseName, upperSnakeCaseName, MAX_FILENAME_LENGTH); camelCaseNameFromSnakeCaseNames(lowerSnakeCaseName, upperSnakeCaseName, camelCaseName, MAX_FILENAME_LENGTH); + /* char headerPath[MAX_FILENAME_LENGTH]; size_t pathLength = strlen(inputPath); strcpy(headerPath, inputPath); @@ -92,6 +93,9 @@ int main(int argc, char * argv[]) { implementationPath[pathLength-3] = 'c'; implementationPath[pathLength-2] = 'p'; implementationPath[pathLength-1] = 'p'; + */ + char * headerPath = argv[2]; + char * implementationPath = argv[3]; FILE * header = fopen(headerPath, "w"); generateHeaderFromImage(header, upperSnakeCaseName, camelCaseName); diff --git a/ion/Makefile b/ion/Makefile index e123b4595..5dbe116b6 100644 --- a/ion/Makefile +++ b/ion/Makefile @@ -14,17 +14,17 @@ include ion/src/shared/tools/Makefile # char test[4]= "ab"; is valid and should initialize test to 'a','b',0,0). # Older versions of GCC are not conformant so we resort to an initializer list. initializer_list = $(shell echo $(1) | sed "s/\(.\)/'\1',/g")0 -ion/src/shared/platform_info.o: SFLAGS += -DPATCH_LEVEL="$(call initializer_list,$(PATCH_LEVEL))" -DEPSILON_VERSION="$(call initializer_list,$(EPSILON_VERSION))" +$(call object_for,ion/src/shared/platform_info.cpp): SFLAGS += -DPATCH_LEVEL="$(call initializer_list,$(PATCH_LEVEL))" -DEPSILON_VERSION="$(call initializer_list,$(EPSILON_VERSION))" -objs += $(addprefix ion/src/shared/, \ - crc32_padded.o\ - events.o \ - platform_info.o \ - storage.o \ - decompress.o \ +src += $(addprefix ion/src/shared/, \ + crc32_padded.cpp \ + decompress.cpp \ + events.cpp \ + platform_info.cpp \ + storage.cpp \ ) -objs += ion/src/external/lz4/lz4.o +src += ion/src/external/lz4/lz4.c tests += $(addprefix ion/test/,\ crc32.cpp\ diff --git a/ion/src/device/Makefile b/ion/src/device/Makefile index 3d243bd47..d6f784acc 100644 --- a/ion/src/device/Makefile +++ b/ion/src/device/Makefile @@ -2,35 +2,35 @@ include ion/src/device/boot/Makefile include ion/src/device/bench/Makefile include ion/src/device/usb/Makefile -ion/src/shared/platform_info.o: SFLAGS += -DHEADER_SECTION="__attribute__((section(\".header\")))" +$(call object_for,ion/src/shared/platform_info.cpp): SFLAGS += -DHEADER_SECTION="__attribute__((section(\".header\")))" -objs += $(addprefix ion/src/shared/, \ - console_line.o \ - crc32_padded.o\ - events_modifier.o \ +src += $(addprefix ion/src/shared/, \ + console_line.cpp \ + crc32_padded.cpp \ + events_modifier.cpp \ ) # If you need to profile execution, you can replace events_keyboard with # events_replay.o and dummy/events_modifier.o -objs += $(addprefix ion/src/device/, \ - backlight.o \ - battery.o\ - base64.o\ - console.o \ - device.o\ - display.o\ - events.o\ - flash.o\ - keyboard.o\ - led.o\ - power.o\ - sd_card.o\ - stack.o\ - swd.o \ - timing.o \ - usb.o \ - wakeup.o \ +src += $(addprefix ion/src/device/, \ + backlight.cpp \ + battery.cpp \ + base64.cpp \ + console.cpp \ + device.cpp \ + display.cpp \ + events.cpp \ + flash.cpp \ + keyboard.cpp \ + led.cpp \ + power.cpp \ + sd_card.cpp \ + stack.cpp \ + swd.cpp \ + timing.cpp \ + usb.cpp \ + wakeup.cpp \ ) # When using the register.h C++ file in production mode, we expect the compiler @@ -41,10 +41,10 @@ objs += $(addprefix ion/src/device/, \ ifneq ($(DEBUG),1) ifneq ($(COMPILER),llvm) -ion/src/device/led.o: SFLAGS+=-O3 -ion/src/device/console.o: SFLAGS+=-O3 -ion/src/device/display.o: SFLAGS+=-O3 -ion/src/device/swd.o: SFLAGS+=-O3 +$(OUTPUT_DIRECTORY)/ion/src/device/led.o: SFLAGS+=-O3 +$(OUTPUT_DIRECTORY)/ion/src/device/console.o: SFLAGS+=-O3 +$(OUTPUT_DIRECTORY)/ion/src/device/display.o: SFLAGS+=-O3 +$(OUTPUT_DIRECTORY)/ion/src/device/swd.o: SFLAGS+=-O3 endif endif diff --git a/ion/src/device/bench/Makefile b/ion/src/device/bench/Makefile index 90b0c82b6..c882e1393 100644 --- a/ion/src/device/bench/Makefile +++ b/ion/src/device/bench/Makefile @@ -1,21 +1,21 @@ -objs += $(addprefix ion/src/device/bench/, \ - bench.o \ - command_handler.o \ - command_list.o \ +src += $(addprefix ion/src/device/bench/, \ + bench.cpp \ + command_handler.cpp \ + command_list.cpp \ ) -objs += $(addprefix ion/src/device/bench/command/, \ - command.o \ - adc.o \ - backlight.o \ - charge.o \ - display.o \ - exit.o \ - keyboard.o \ - led.o \ - mcu_serial.o \ - ping.o \ - print.o \ - suspend.o \ - vblank.o \ +src += $(addprefix ion/src/device/bench/command/, \ + adc.cpp \ + backlight.cpp \ + charge.cpp \ + command.cpp \ + display.cpp \ + exit.cpp \ + keyboard.cpp \ + led.cpp \ + mcu_serial.cpp \ + ping.cpp \ + print.cpp \ + suspend.cpp \ + vblank.cpp \ ) diff --git a/ion/src/device/boot/Makefile b/ion/src/device/boot/Makefile index ded572acd..275c45bb5 100644 --- a/ion/src/device/boot/Makefile +++ b/ion/src/device/boot/Makefile @@ -1,2 +1,2 @@ -objs += $(addprefix ion/src/device/boot/, isr.o rt0.o) +src += $(addprefix ion/src/device/boot/, isr.c rt0.cpp) LDSCRIPT = ion/src/device/boot/flash.ld diff --git a/ion/src/device/usb/Makefile b/ion/src/device/usb/Makefile index a2d840eef..aca2218de 100644 --- a/ion/src/device/usb/Makefile +++ b/ion/src/device/usb/Makefile @@ -1,67 +1,74 @@ -usb_objs += $(addprefix ion/src/device/usb/, \ - calculator.o \ - dfu_interface.o\ +usb_src += $(addprefix ion/src/device/usb/, \ + calculator.cpp \ + dfu_interface.cpp \ ) -usb_objs += $(addprefix ion/src/device/usb/stack/, \ - device.o\ - endpoint0.o \ - interface.o\ - request_recipient.o\ - setup_packet.o\ - streamable.o\ +usb_src += $(addprefix ion/src/device/usb/stack/, \ + device.cpp \ + endpoint0.cpp \ + interface.cpp \ + request_recipient.cpp \ + setup_packet.cpp \ + streamable.cpp \ ) -usb_objs += $(addprefix ion/src/device/usb/stack/descriptor/, \ - bos_descriptor.o\ - configuration_descriptor.o \ - descriptor.o\ - device_descriptor.o\ - device_capability_descriptor.o\ - dfu_functional_descriptor.o\ - extended_compat_id_descriptor.o \ - interface_descriptor.o\ - language_id_string_descriptor.o \ - microsoft_os_string_descriptor.o\ - platform_device_capability_descriptor.o\ - string_descriptor.o\ - url_descriptor.o\ - webusb_platform_descriptor.o\ +usb_src += $(addprefix ion/src/device/usb/stack/descriptor/, \ + bos_descriptor.cpp \ + configuration_descriptor.cpp \ + descriptor.cpp \ + device_capability_descriptor.cpp \ + device_descriptor.cpp \ + dfu_functional_descriptor.cpp \ + extended_compat_id_descriptor.cpp \ + interface_descriptor.cpp \ + language_id_string_descriptor.cpp \ + microsoft_os_string_descriptor.cpp \ + platform_device_capability_descriptor.cpp \ + string_descriptor.cpp \ + url_descriptor.cpp \ + webusb_platform_descriptor.cpp \ ) EPSILON_USB_DFU_XIP ?= 0 ifeq ($(EPSILON_USB_DFU_XIP),1) -objs += ion/src/device/usb/dfu_xip.o -objs += $(usb_objs) +src += ion/src/device/usb/dfu_xip.cpp +src += $(usb_src) else -dfu_objs += liba/src/assert.o -dfu_objs += liba/src/strlen.o -dfu_objs += liba/src/strlcpy.o -dfu_objs += liba/src/memset.o -dfu_objs += liba/src/memcpy.o -dfu_objs += libaxx/src/cxxabi/pure_virtual.o -dfu_objs += ion/src/device/usb/boot.o -dfu_objs += ion/src/device/keyboard.o -dfu_objs += ion/src/device/device.o -dfu_objs += ion/src/device/usb.o -dfu_objs += ion/src/device/base64.o -dfu_objs += ion/src/device/flash.o -dfu_objs += ion/src/device/timing.o +dfu_src += liba/src/assert.cpp +dfu_src += liba/src/strlen.cpp +dfu_src += liba/src/strlcpy.cpp +dfu_src += liba/src/memset.cpp +dfu_src += liba/src/memcpy.cpp +dfu_src += libaxx/src/cxxabi/pure_virtual.cpp +dfu_src += ion/src/device/usb/boot.cpp +dfu_src += ion/src/device/keyboard.cpp +dfu_src += ion/src/device/device.cpp +dfu_src += ion/src/device/usb.cpp +dfu_src += ion/src/device/base64.cpp +dfu_src += ion/src/device/flash.cpp +dfu_src += ion/src/device/timing.cpp -ion/src/device/usb/dfu.elf: LDSCRIPT = ion/src/device/usb/dfu.ld -ion/src/device/usb/dfu.elf: $(usb_objs) $(dfu_objs) +$(OUTPUT_DIRECTORY)/ion/src/device/usb/dfu.elf: LDSCRIPT = ion/src/device/usb/dfu.ld +$(OUTPUT_DIRECTORY)/ion/src/device/usb/dfu.elf: $(call object_for,$(usb_src)) $(call object_for,$(dfu_src)) -ion/src/device/usb/dfu.o: ion/src/device/usb/dfu.bin +# This command embeds a binary file into an object one. +# This allows us to embed standalone code (the dfu routines) into the final +# executable, and easily relocate it to RAM for execution. The objcopy command +# that turns binary data into an ELF object generates three symbols (start, size +# and end), but prefixes them with a mangled file path. To have consistent names +# we simply "cd" into the directory. This assumes input and output lives in the +# same directory. +$(OUTPUT_DIRECTORY)/ion/src/device/usb/dfu.o: $(OUTPUT_DIRECTORY)/ion/src/device/usb/dfu.bin @echo "OBJCOPY $@" - $(Q) $(OBJCOPY) -I binary -O elf32-littlearm -B arm --rename-section .data=.rodata --redefine-sym _binary_ion_src_device_usb_dfu_bin_start=_dfu_bootloader_flash_start --redefine-sym _binary_ion_src_device_usb_dfu_bin_end=_dfu_bootloader_flash_end $< $@ + $(Q) cd $(dir $<) ; $(OBJCOPY) -I binary -O elf32-littlearm -B arm --rename-section .data=.rodata --redefine-sym _binary_dfu_bin_start=_dfu_bootloader_flash_start --redefine-sym _binary_dfu_bin_end=_dfu_bootloader_flash_end $(notdir $<) $(notdir $@) -objs += ion/src/device/usb/dfu.o -objs += ion/src/device/usb/dfu_relocated.o +src += ion/src/device/usb/dfu.cpp +src += ion/src/device/usb/dfu_relocated.cpp -products += $(usb_objs) $(addprefix ion/src/device/usb/dfu, .elf .bin) +#products += $(usb_objs) $(addprefix ion/src/device/usb/dfu, .elf .bin) endif diff --git a/kandinsky/Makefile b/kandinsky/Makefile index 5c23b1b64..d9d3793ea 100644 --- a/kandinsky/Makefile +++ b/kandinsky/Makefile @@ -1,19 +1,23 @@ SFLAGS += -Ikandinsky/include -objs += $(addprefix kandinsky/src/,\ - color.o\ - context.o\ - context_line.o\ - context_pixel.o\ - context_rect.o\ - context_text.o\ - font.o\ - font_large.o\ - font_small.o\ - framebuffer.o\ - framebuffer_context.o\ - ion_context.o\ - point.o\ - rect.o\ + +src += $(addprefix kandinsky/src/,\ + color.cpp \ + context.cpp \ + context_line.cpp \ + context_pixel.cpp \ + context_rect.cpp \ + context_text.cpp \ + font.cpp \ + framebuffer.cpp \ + framebuffer_context.cpp \ + ion_context.cpp \ + point.cpp \ + rect.cpp \ +) + +src += $(addprefix kandinsky/fonts/, \ + LargeSourcePixel.ttf \ + SmallSourcePixel.ttf \ ) tests += $(addprefix kandinsky/test/,\ @@ -21,14 +25,6 @@ tests += $(addprefix kandinsky/test/,\ rect.cpp\ ) -FREETYPE_PATH := /usr/local/Cellar/freetype/2.6.3 -# LIBPNG_PATH is optional. If LIBPNG_PATH is not defined, rasterizer will be -# built w/o PNG support and simply won't output an image of the rasterization -#LIBPNG_PATH := /usr/local/Cellar/libpng/1.6.21 - -small_font_files = $(addprefix kandinsky/src/, font_small.cpp) -large_font_files = $(addprefix kandinsky/src/, font_large.cpp) - RASTERIZER_CFLAGS := -std=c99 `pkg-config freetype2 --cflags` RASTERIZER_LDFLAGS := `pkg-config freetype2 --libs` @@ -38,20 +34,25 @@ ifdef LIBPNG_PATH RASTERIZER_CFLAGS += -I$(LIBPNG_PATH)/include -DGENERATE_PNG=1 -L$(LIBPNG_PATH)/lib -lpng endif -# Even though raster will generate both .c and .h files, we don't declare it as -# such to make. If we did, "make -jN" with N>1 may call "raster" twice. +$(eval $(call rule_for, \ + HOSTCC, \ + kandinsky/fonts/rasterizer, \ + kandinsky/fonts/rasterizer.c kandinsky/fonts/unicode_for_symbol.c $(addprefix ion/src/external/lz4/, lz4.c lz4hc.c), \ + $$(HOSTCC) $$(RASTERIZER_CFLAGS) $$^ $$(RASTERIZER_LDFLAGS) -o $$@ \ +)) -kandinsky/src/font_small.cpp: kandinsky/fonts/rasterizer - @echo "RASTER $(small_font_files)" - $(Q) $< kandinsky/fonts/SmallSourcePixel.ttf 12 12 SmallFont $(small_font_files) +RASTERIZER := $(OUTPUT_DIRECTORY)/kandinsky/fonts/rasterizer -kandinsky/src/font_large.cpp: kandinsky/fonts/rasterizer - @echo "RASTER $(large_font_files)" - $(Q) $< kandinsky/fonts/LargeSourcePixel.ttf 16 16 LargeFont $(large_font_files) - -kandinsky/fonts/rasterizer: kandinsky/fonts/rasterizer.c kandinsky/fonts/unicode_for_symbol.c $(addprefix ion/src/external/lz4/, lz4.c lz4hc.c) - @echo "HOSTCC $@" - $(Q) $(HOSTCC) $(RASTERIZER_CFLAGS) $^ $(RASTERIZER_LDFLAGS) -o $@ - -products += $(small_font_files) $(large_font_files) kandinsky/fonts/rasterizer +$(eval $(call rule_for, \ + RASTER, \ + kandinsky/fonts/SmallSourcePixel.cpp, \ + kandinsky/fonts/SmallSourcePixel.ttf $$(RASTERIZER), \ + $$(RASTERIZER) $$< 12 12 SmallFont $$@ \ +)) +$(eval $(call rule_for, \ + RASTER, \ + kandinsky/fonts/LargeSourcePixel.cpp, \ + kandinsky/fonts/LargeSourcePixel.ttf $$(RASTERIZER), \ + $$(RASTERIZER) $$< 16 16 LargeFont $$@ \ +)) diff --git a/liba/Makefile b/liba/Makefile index da54983c1..96bf3f3bc 100644 --- a/liba/Makefile +++ b/liba/Makefile @@ -1,126 +1,125 @@ SFLAGS += -Iliba/include -liba/src/external/sqlite/mem5.o: CFLAGS += -w - -objs += $(addprefix liba/src/, \ - armv7m/setjmp.o \ - armv7m/longjmp.o \ - assert.o \ - bzero.o \ - ctype.o \ - errno.o \ - fpclassify.o \ - fpclassifyf.o \ - ieee754.o \ - malloc.o \ - memcmp.o \ - memcpy.o \ - memmove.o \ - memset.o \ - nearbyint.o \ - nearbyintf.o \ - strcmp.o \ - strchr.o \ - strlcpy.o \ - strlen.o \ - external/sqlite/mem5.o \ +src += $(addprefix liba/src/, \ + armv7m/setjmp.s \ + armv7m/longjmp.s \ + assert.c \ + bzero.c \ + ctype.c \ + errno.c \ + fpclassify.c \ + fpclassifyf.c \ + ieee754.c \ + malloc.c \ + memcmp.c \ + memcpy.c \ + memmove.c \ + memset.c \ + nearbyint.c \ + nearbyintf.c \ + strcmp.c \ + strchr.c \ + strlcpy.c \ + strlen.c \ + external/sqlite/mem5.c \ ) -objs += $(addprefix liba/src/external/openbsd/, \ - b_exp__D.o \ - b_log__D.o \ - b_tgamma.o \ - e_acosf.o \ - e_acoshf.o \ - e_asinf.o \ - e_atanhf.o \ - e_atan2f.o \ - e_coshf.o \ - e_expf.o \ - e_fmodf.o \ - e_hypotf.o \ - e_lgammaf_r.o \ - e_log10f.o \ - e_log2.o \ - e_logf.o \ - e_powf.o \ - e_rem_pio2f.o \ - e_scalb.o \ - e_sinhf.o \ - e_sqrtf.o \ - k_cosf.o \ - k_rem_pio2f.o \ - k_sinf.o \ - k_tanf.o \ +src += $(addprefix liba/src/external/openbsd/, \ + b_exp__D.c \ + b_log__D.c \ + b_tgamma.c \ + e_acosf.c \ + e_acoshf.c \ + e_asinf.c \ + e_atanhf.c \ + e_atan2f.c \ + e_coshf.c \ + e_expf.c \ + e_fmodf.c \ + e_hypotf.c \ + e_lgammaf_r.c \ + e_log10f.c \ + e_log2.c \ + e_logf.c \ + e_powf.c \ + e_rem_pio2f.c \ + e_scalb.c \ + e_sinhf.c \ + e_sqrtf.c \ + k_cosf.c \ + k_rem_pio2f.c \ + k_sinf.c \ + k_tanf.c \ s_asinhf.o\ - s_atanf.o \ - s_ceilf.o \ - s_copysignf.o \ - s_cosf.o \ - s_erf.o \ + s_atanf.c \ + s_ceilf.c \ + s_copysignf.c \ + s_cosf.c \ + s_erf.c \ s_expm1f.o\ - s_fabsf.o \ - s_fmaxf.o \ - s_floorf.o \ - s_frexpf.o \ - s_frexp.o \ - s_log1pf.o \ - s_logb.o \ - s_modf.o \ - s_modff.o \ - s_rint.o \ - s_roundf.o \ - s_scalbnf.o \ - s_signgam.o \ - s_sinf.o \ - s_tanf.o \ - s_tanhf.o \ - s_trunc.o \ - s_truncf.o \ - w_lgammaf.o \ + s_fabsf.c \ + s_fmaxf.c \ + s_floorf.c \ + s_frexpf.c \ + s_frexp.c \ + s_log1pf.c \ + s_logb.c \ + s_modf.c \ + s_modff.c \ + s_rint.c \ + s_roundf.c \ + s_scalbnf.c \ + s_signgam.c \ + s_sinf.c \ + s_tanf.c \ + s_tanhf.c \ + s_trunc.c \ + s_truncf.c \ + w_lgammaf.c \ ) -objs += $(addprefix liba/src/external/openbsd/, \ - e_acos.o \ - e_acosh.o \ - e_asin.o \ - e_atanh.o \ - e_atan2.o \ - e_cosh.o \ - e_exp.o \ - e_fmod.o \ - e_hypot.o \ - e_lgamma_r.o \ - e_log.o \ - e_log10.o \ - e_pow.o \ - e_rem_pio2.o \ - e_sinh.o \ - e_sqrt.o \ - k_cos.o \ - k_rem_pio2.o \ - k_sin.o \ - k_tan.o \ - s_asinh.o \ - s_atan.o \ - s_ceil.o \ - s_copysign.o \ - s_cos.o \ - s_expm1.o \ - s_fabs.o \ - s_fmax.o \ - s_floor.o \ - s_log1p.o \ - s_round.o \ - s_scalbn.o \ - s_sin.o \ - s_tan.o \ - s_tanh.o \ - w_lgamma.o \ +src += $(addprefix liba/src/external/openbsd/, \ + e_acos.c \ + e_acosh.c \ + e_asin.c \ + e_atanh.c \ + e_atan2.c \ + e_cosh.c \ + e_exp.c \ + e_fmod.c \ + e_hypot.c \ + e_lgamma_r.c \ + e_log.c \ + e_log10.c \ + e_pow.c \ + e_rem_pio2.c \ + e_sinh.c \ + e_sqrt.c \ + k_cos.c \ + k_rem_pio2.c \ + k_sin.c \ + k_tan.c \ + s_asinh.c \ + s_atan.c \ + s_ceil.c \ + s_copysign.c \ + s_cos.c \ + s_expm1.c \ + s_fabs.c \ + s_fmax.c \ + s_floor.c \ + s_log1p.c \ + s_round.c \ + s_scalbn.c \ + s_sin.c \ + s_tan.c \ + s_tanh.c \ + w_lgamma.c \ ) -liba/src/external/openbsd/%.o: SFLAGS := -Iliba/src/external/openbsd/include $(SFLAGS) -liba/src/external/openbsd/%.o: CFLAGS += -w +$(call object_for,liba/src/external/sqlite/mem5.c): CFLAGS += -w +$(call object_for,liba/src/external/openbsd/%.c): SFLAGS := -Iliba/src/external/openbsd/include $(SFLAGS) +$(call object_for,liba/src/external/openbsd/%.c): CFLAGS += -w tests += $(addprefix liba/test/, \ aeabi.c \ @@ -136,6 +135,6 @@ tests += $(addprefix liba/test/, \ # The use of aeabi-rt could be made conditional to an AEABI target. # In practice we're always using liba on such a target. -objs += $(addprefix liba/src/aeabi-rt/, \ - atexit.o \ +src += $(addprefix liba/src/aeabi-rt/, \ + atexit.c \ ) diff --git a/liba/Makefile.bridge b/liba/Makefile.bridge index f9157402a..70e190f58 100644 --- a/liba/Makefile.bridge +++ b/liba/Makefile.bridge @@ -1,3 +1,3 @@ SFLAGS += -Iliba/include/bridge -objs += liba/src/bridge.o +src += liba/src/bridge.c diff --git a/libaxx/Makefile b/libaxx/Makefile index f2e6702f5..fd64e42ea 100644 --- a/libaxx/Makefile +++ b/libaxx/Makefile @@ -1,6 +1,5 @@ SFLAGS += -Ilibaxx/include -objs += $(addprefix libaxx/src/, new.o) -objs += $(addprefix libaxx/src/cxxabi/, atexit.o pure_virtual.o) -objs += $(addprefix libaxx/include/external/libcxx/, complex.o) - +src += $(addprefix libaxx/src/, new.cpp) +src += $(addprefix libaxx/src/cxxabi/, atexit.cpp pure_virtual.cpp) +src += $(addprefix libaxx/include/external/libcxx/, complex.cpp) diff --git a/poincare/Makefile b/poincare/Makefile index 28c3096e6..4a41680f9 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -1,140 +1,138 @@ SFLAGS += -Ipoincare/include -#include poincare/src/simplify/Makefile -#include poincare/src/simplification/Makefile -objs += $(addprefix poincare/src/,\ - binomial_coefficient_layout.o\ - bracket_layout.o\ - bracket_pair_layout.o\ - char_layout.o\ - condensed_sum_layout.o\ - conjugate_layout.o\ - empty_layout.o\ - fraction_layout.o\ - grid_layout.o\ - horizontal_layout.o\ - integral_layout.o\ - layout_cursor.o\ - layout.o\ - layout_node.o\ - left_parenthesis_layout.o\ - left_square_bracket_layout.o\ - matrix_layout.o\ - nth_root_layout.o\ - parenthesis_layout.o\ - product_layout.o\ - right_parenthesis_layout.o\ - right_square_bracket_layout.o\ - sequence_layout.o\ - sum_layout.o\ - vertical_offset_layout.o\ +src += $(addprefix poincare/src/,\ + binomial_coefficient_layout.cpp \ + bracket_layout.cpp \ + bracket_pair_layout.cpp \ + char_layout.cpp \ + condensed_sum_layout.cpp \ + conjugate_layout.cpp \ + empty_layout.cpp \ + fraction_layout.cpp \ + grid_layout.cpp \ + horizontal_layout.cpp \ + integral_layout.cpp \ + layout_cursor.cpp \ + layout.cpp \ + layout_node.cpp \ + left_parenthesis_layout.cpp \ + left_square_bracket_layout.cpp \ + matrix_layout.cpp \ + nth_root_layout.cpp \ + parenthesis_layout.cpp \ + product_layout.cpp \ + right_parenthesis_layout.cpp \ + right_square_bracket_layout.cpp \ + sequence_layout.cpp \ + sum_layout.cpp \ + vertical_offset_layout.cpp \ ) -objs += $(addprefix poincare/src/,\ - init.o\ - exception_checkpoint.o\ - helpers.o\ +src += $(addprefix poincare/src/,\ + init.cpp \ + exception_checkpoint.cpp \ + helpers.cpp \ ) -objs += $(addprefix poincare/src/,\ - absolute_value.o\ - addition.o\ - approximation_helper.o\ - arc_cosine.o\ - arc_sine.o\ - arc_tangent.o\ - arithmetic.o\ - binomial_coefficient.o\ - ceiling.o\ - complex.o\ - complex_argument.o\ - complex_cartesian.o\ - confidence_interval.o\ - conjugate.o\ - constant.o\ - cosine.o\ - decimal.o\ - derivative.o\ - determinant.o\ - division.o\ - division_quotient.o\ - division_remainder.o\ - empty_expression.o\ - equal.o\ - evaluation.o\ - expression.o\ - expression_node.o\ - factor.o\ - factorial.o\ - float.o\ - floor.o\ - frac_part.o\ - function.o\ - great_common_divisor.o\ - hyperbolic_arc_cosine.o\ - hyperbolic_arc_sine.o\ - hyperbolic_arc_tangent.o\ - hyperbolic_cosine.o\ - hyperbolic_sine.o\ - hyperbolic_tangent.o\ - hyperbolic_trigonometric_function.o\ - imaginary_part.o\ - infinity.o\ - integer.o\ - integral.o\ - layout_helper.o\ - least_common_multiple.o\ - logarithm.o\ - matrix.o\ - matrix_complex.o\ - matrix_dimension.o\ - matrix_inverse.o\ - matrix_trace.o\ - matrix_transpose.o\ - multiplication.o\ - n_ary_expression_node.o\ - naperian_logarithm.o\ - nth_root.o\ - number.o\ - opposite.o\ - parametered_expression_helper.o\ - parenthesis.o\ - permute_coefficient.o\ - power.o\ - prediction_interval.o\ - preferences.o\ - print_float.o\ - product.o\ - randint.o\ - random.o\ - rational.o\ - real_part.o\ - round.o\ - sequence.o\ - serialization_helper.o\ - sign_function.o\ - simplification_helper.o\ - sine.o\ - square_root.o\ - store.o\ - subtraction.o\ - sum.o\ - symbol.o\ - symbol_abstract.o\ - tangent.o\ - tree_handle.o\ - tree_node.o\ - tree_pool.o\ - trigonometry.o\ - trigonometry_cheat_table.o\ - undefined.o\ - unreal.o\ - variable_context.o\ +src += $(addprefix poincare/src/,\ + absolute_value.cpp \ + addition.cpp \ + approximation_helper.cpp \ + arc_cosine.cpp \ + arc_sine.cpp \ + arc_tangent.cpp \ + arithmetic.cpp \ + binomial_coefficient.cpp \ + ceiling.cpp \ + complex.cpp \ + complex_argument.cpp \ + complex_cartesian.cpp \ + confidence_interval.cpp \ + conjugate.cpp \ + constant.cpp \ + cosine.cpp \ + decimal.cpp \ + derivative.cpp \ + determinant.cpp \ + division.cpp \ + division_quotient.cpp \ + division_remainder.cpp \ + empty_expression.cpp \ + equal.cpp \ + evaluation.cpp \ + expression.cpp \ + expression_node.cpp \ + factor.cpp \ + factorial.cpp \ + float.cpp \ + floor.cpp \ + frac_part.cpp \ + function.cpp \ + great_common_divisor.cpp \ + hyperbolic_arc_cosine.cpp \ + hyperbolic_arc_sine.cpp \ + hyperbolic_arc_tangent.cpp \ + hyperbolic_cosine.cpp \ + hyperbolic_sine.cpp \ + hyperbolic_tangent.cpp \ + hyperbolic_trigonometric_function.cpp \ + imaginary_part.cpp \ + infinity.cpp \ + integer.cpp \ + integral.cpp \ + layout_helper.cpp \ + least_common_multiple.cpp \ + logarithm.cpp \ + matrix.cpp \ + matrix_complex.cpp \ + matrix_dimension.cpp \ + matrix_inverse.cpp \ + matrix_trace.cpp \ + matrix_transpose.cpp \ + multiplication.cpp \ + n_ary_expression_node.cpp \ + naperian_logarithm.cpp \ + nth_root.cpp \ + number.cpp \ + opposite.cpp \ + parametered_expression_helper.cpp \ + parenthesis.cpp \ + permute_coefficient.cpp \ + power.cpp \ + prediction_interval.cpp \ + preferences.cpp \ + print_float.cpp \ + product.cpp \ + randint.cpp \ + random.cpp \ + rational.cpp \ + real_part.cpp \ + round.cpp \ + sequence.cpp \ + serialization_helper.cpp \ + sign_function.cpp \ + simplification_helper.cpp \ + sine.cpp \ + square_root.cpp \ + store.cpp \ + subtraction.cpp \ + sum.cpp \ + symbol.cpp \ + symbol_abstract.cpp \ + tangent.cpp \ + tree_handle.cpp \ + tree_node.cpp \ + tree_pool.cpp \ + trigonometry.cpp \ + trigonometry_cheat_table.cpp \ + undefined.cpp \ + unreal.cpp \ + variable_context.cpp \ ) -objs += $(addprefix poincare/src/parsing/,\ - parser.o\ - tokenizer.o\ +src += $(addprefix poincare/src/parsing/,\ + parser.cpp \ + tokenizer.cpp \ ) tests += $(addprefix poincare/test/,\ @@ -185,7 +183,7 @@ test_objs += $(addprefix apps/shared/, global_context.o) ifdef POINCARE_TESTS_PRINT_EXPRESSIONS tests += poincare/src/expression_debug.o -objs += poincare/src/expression_debug.o +src += poincare/src/expression_debug.cpp SFLAGS += -DPOINCARE_TESTS_PRINT_EXPRESSIONS=1 endif diff --git a/python/Makefile b/python/Makefile index a053976a1..35c23812c 100644 --- a/python/Makefile +++ b/python/Makefile @@ -1,142 +1,143 @@ SFLAGS += -Ipython/src SFLAGS += -Ipython/port +SFLAGS += -I$(OUTPUT_DIRECTORY)/python/port # How to maintain this Makefile # - Copy PY_CORE_O_BASENAME from py.mk into py_objs # - Copy select PY_EXTMOD_O_BASENAME from py.mk into extmod_objs # - Edit special-case workarounds below as needed -py_objs = $(addprefix python/src/py/,\ - mpstate.o \ - nlr.o \ - nlrx86.o \ - nlrx64.o \ - nlrthumb.o \ - nlrxtensa.o \ - nlrsetjmp.o \ - malloc.o \ - gc.o \ - pystack.o \ - qstr.o \ - vstr.o \ - mpprint.o \ - unicode.o \ - mpz.o \ - reader.o \ - lexer.o \ - parse.o \ - scope.o \ - compile.o \ - emitcommon.o \ - emitbc.o \ - asmbase.o \ - asmx64.o \ - emitnx64.o \ - asmx86.o \ - emitnx86.o \ - asmthumb.o \ - emitnthumb.o \ - emitinlinethumb.o \ - asmarm.o \ - emitnarm.o \ - asmxtensa.o \ - emitnxtensa.o \ - emitinlinextensa.o \ - formatfloat.o \ - parsenumbase.o \ - parsenum.o \ - emitglue.o \ - persistentcode.o \ - runtime.o \ - runtime_utils.o \ - scheduler.o \ - nativeglue.o \ - stackctrl.o \ - argcheck.o \ - warning.o \ - map.o \ - obj.o \ - objarray.o \ - objattrtuple.o \ - objbool.o \ - objboundmeth.o \ - objcell.o \ - objclosure.o \ - objcomplex.o \ - objdeque.o \ - objdict.o \ - objenumerate.o \ - objexcept.o \ - objfilter.o \ - objfloat.o \ - objfun.o \ - objgenerator.o \ - objgetitemiter.o \ - objint.o \ - objint_longlong.o \ - objint_mpz.o \ - objlist.o \ - objmap.o \ - objmodule.o \ - objobject.o \ - objpolyiter.o \ - objproperty.o \ - objnone.o \ - objnamedtuple.o \ - objrange.o \ - objreversed.o \ - objset.o \ - objsingleton.o \ - objslice.o \ - objstr.o \ - objstrunicode.o \ - objstringio.o \ - objtuple.o \ - objtype.o \ - objzip.o \ - opmethods.o \ - sequence.o \ - stream.o \ - binary.o \ - builtinimport.o \ - builtinevex.o \ - builtinhelp.o \ - modarray.o \ - modbuiltins.o \ - modcollections.o \ - modgc.o \ - modio.o \ - modmath.o \ - modcmath.o \ - modmicropython.o \ - modstruct.o \ - modsys.o \ - moduerrno.o \ - modthread.o \ - vm.o \ - bc.o \ - showbc.o \ - repl.o \ - smallint.o \ - frozenmod.o \ +py_src = $(addprefix python/src/py/,\ + mpstate.c \ + nlr.c \ + nlrx86.c \ + nlrx64.c \ + nlrthumb.c \ + nlrxtensa.c \ + nlrsetjmp.c \ + malloc.c \ + gc.c \ + pystack.c \ + qstr.c \ + vstr.c \ + mpprint.c \ + unicode.c \ + mpz.c \ + reader.c \ + lexer.c \ + parse.c \ + scope.c \ + compile.c \ + emitcommon.c \ + emitbc.c \ + asmbase.c \ + asmx64.c \ + emitnx64.c \ + asmx86.c \ + emitnx86.c \ + asmthumb.c \ + emitnthumb.c \ + emitinlinethumb.c \ + asmarm.c \ + emitnarm.c \ + asmxtensa.c \ + emitnxtensa.c \ + emitinlinextensa.c \ + formatfloat.c \ + parsenumbase.c \ + parsenum.c \ + emitglue.c \ + persistentcode.c \ + runtime.c \ + runtime_utils.c \ + scheduler.c \ + nativeglue.c \ + stackctrl.c \ + argcheck.c \ + warning.c \ + map.c \ + obj.c \ + objarray.c \ + objattrtuple.c \ + objbool.c \ + objboundmeth.c \ + objcell.c \ + objclosure.c \ + objcomplex.c \ + objdeque.c \ + objdict.c \ + objenumerate.c \ + objexcept.c \ + objfilter.c \ + objfloat.c \ + objfun.c \ + objgenerator.c \ + objgetitemiter.c \ + objint.c \ + objint_longlong.c \ + objint_mpz.c \ + objlist.c \ + objmap.c \ + objmodule.c \ + objobject.c \ + objpolyiter.c \ + objproperty.c \ + objnone.c \ + objnamedtuple.c \ + objrange.c \ + objreversed.c \ + objset.c \ + objsingleton.c \ + objslice.c \ + objstr.c \ + objstrunicode.c \ + objstringio.c \ + objtuple.c \ + objtype.c \ + objzip.c \ + opmethods.c \ + sequence.c \ + stream.c \ + binary.c \ + builtinimport.c \ + builtinevex.c \ + builtinhelp.c \ + modarray.c \ + modbuiltins.c \ + modcollections.c \ + modgc.c \ + modio.c \ + modmath.c \ + modcmath.c \ + modmicropython.c \ + modstruct.c \ + modsys.c \ + moduerrno.c \ + modthread.c \ + vm.c \ + bc.c \ + showbc.c \ + repl.c \ + smallint.c \ + frozenmod.c \ ) -extmod_objs += $(addprefix python/src/extmod/,\ - modurandom.o \ +extmod_src += $(addprefix python/src/extmod/,\ + modurandom.c \ ) -port_objs += $(addprefix python/port/,\ - port.o \ - builtins.o\ - helpers.o \ - mod/kandinsky/modkandinsky.o \ - mod/kandinsky/modkandinsky_table.o \ - mod/time/modtime.o \ - mod/time/modtime_table.o \ - mod/turtle/modturtle.o \ - mod/turtle/modturtle_table.o \ - mod/turtle/turtle.o \ - mphalport.o \ +port_src += $(addprefix python/port/,\ + port.c \ + builtins.c \ + helpers.c \ + mod/kandinsky/modkandinsky.cpp \ + mod/kandinsky/modkandinsky_table.cpp \ + mod/time/modtime.c \ + mod/time/modtime_table.c \ + mod/turtle/modturtle.cpp \ + mod/turtle/modturtle_table.cpp \ + mod/turtle/turtle.cpp \ + mphalport.c \ ) # Workarounds @@ -145,14 +146,14 @@ port_objs += $(addprefix python/port/,\ # In order to change the name of the micropython module 'urandom' to 'random' # (without altering micropython files), we redefined the macro MP_QSTR_urandom # by DMP_QSTR_random. -python/src/py/objmodule.o: SFLAGS += -DMP_QSTR_urandom="MP_QSTR_random" -python/src/extmod/modurandom.o: SFLAGS += -DMP_QSTR_urandom="MP_QSTR_random" +$(call object_for,python/src/py/objmodule.c): SFLAGS += -DMP_QSTR_urandom="MP_QSTR_random" +$(call object_for,python/src/extmod/modurandom.c): SFLAGS += -DMP_QSTR_urandom="MP_QSTR_random" # Handle upward-growing stack # Some platforms such as emscripten have a stack that grows up. We've rewritten # the stack control file to handle this case. -py_objs := $(filter-out python/src/py/stackctrl.o, $(py_objs)) -port_objs += python/port/stackctrl.o +py_src := $(filter-out python/src/py/stackctrl.c, $(py_src)) +port_src += python/port/stackctrl.c # Fix the GC on emscripten # With optimizations, register and stack variables might be held in a JavaScript @@ -162,21 +163,20 @@ port_objs += python/port/stackctrl.o # computing resumes, if necessary heap objects have been destroyed, the Python # program crashes. ifeq ($(PLATFORM),emscripten) -$(py_objs): SFLAGS := $(subst -Os,-O0,$(SFLAGS)) +$(call object_for,$(py_src)): SFLAGS := $(subst -Os,-O0,$(SFLAGS)) endif +python_src = $(py_src) $(extmod_src) $(port_src) + # QSTR generation -generated_headers += $(addprefix python/port/genhdr/, qstrdefs.generated.h) +$(eval $(call rule_for, \ + QSTRDAT, \ + python/port/genhdr/qstrdefs.generated.h, \ + python/port/genhdr/qstrdefs.in.h, \ + $$(PYTHON) python/src/py/makeqstrdata.py $$< > $$@ \ +)) -python/port/genhdr/qstrdefs.generated.h: python/port/genhdr/qstrdefs.in.h - @echo "QSTRDAT $@" - $(Q) $(PYTHON) python/src/py/makeqstrdata.py $< > $@ +$(call object_for,$(python_src)): $(OUTPUT_DIRECTORY)/python/port/genhdr/qstrdefs.generated.h -products += python/port/genhdr/qstrdefs.generated.h - -$(py_objs) $(extmod_objs) $(port_objs): python/port/genhdr/qstrdefs.generated.h - -# List all objects needed - -objs += $(extmod_objs) $(py_objs) $(port_objs) \ No newline at end of file +src += $(python_src) From 4f2c7a37635e8a7c4b74402a9ff2b77d7ffd1fde Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Tue, 5 Mar 2019 17:14:34 +0100 Subject: [PATCH 350/373] [build] Update the i18n processing to fit the out-of-tree build --- .gitignore | 4 --- apps/Makefile | 27 ++++++++++++++----- apps/calculation/app.cpp | 2 +- apps/code/app.cpp | 2 +- apps/code/menu_controller.cpp | 2 +- apps/code/script_parameter_controller.h | 2 +- apps/empty_battery_window.cpp | 2 +- apps/exam_pop_up_controller.cpp | 2 +- apps/global_preferences.h | 2 +- apps/graph/app.cpp | 2 +- apps/graph/graph/banner_view.cpp | 2 +- .../graph/calculation_parameter_controller.h | 2 +- .../graph/curve_parameter_controller.cpp | 2 +- apps/graph/list/storage_list_controller.cpp | 2 +- apps/hardware_test/pop_up_controller.cpp | 2 +- apps/home/app.cpp | 2 +- apps/i18n.py | 2 +- apps/on_boarding/pop_up_controller.h | 2 +- apps/probability/app.cpp | 2 +- apps/probability/calculation_cell.cpp | 2 +- apps/probability/law/law.h | 2 +- apps/regression/app.cpp | 2 +- .../initialisation_parameter_controller.h | 2 +- apps/regression/model/model.h | 2 +- apps/regression/regression_controller.h | 2 +- apps/settings/app.cpp | 2 +- apps/settings/main_controller.cpp | 2 +- apps/shared/expression_field_delegate_app.cpp | 2 +- .../shared/expression_model_list_controller.h | 2 +- apps/shared/function_list_controller.h | 2 +- .../initialisation_parameter_controller.h | 2 +- apps/shared/language_controller.cpp | 2 +- apps/shared/language_controller.h | 2 +- apps/shared/list_parameter_controller.h | 2 +- ...ble_exact_approximate_expressions_view.cpp | 2 +- ...storage_expression_model_list_controller.h | 2 +- .../shared/storage_function_list_controller.h | 2 +- .../storage_list_parameter_controller.h | 2 +- apps/shared/storage_values_controller.h | 2 +- ...age_values_function_parameter_controller.h | 2 +- apps/shared/store_parameter_controller.h | 2 +- apps/shared/text_field_delegate_app.h | 2 +- apps/shared/values_controller.h | 2 +- .../values_function_parameter_controller.h | 2 +- apps/shared/zoom_parameter_controller.h | 2 +- apps/shift_alpha_lock_view.h | 2 +- apps/solver/app.cpp | 2 +- .../equation_models_parameter_controller.cpp | 2 +- apps/solver/interval_controller.cpp | 2 +- apps/solver/list_controller.h | 2 +- apps/solver/solutions_controller.h | 2 +- apps/statistics/app.cpp | 2 +- apps/statistics/box_banner_view.h | 2 +- apps/statistics/histogram_banner_view.h | 2 +- .../multiple_data_view_controller.cpp | 2 +- apps/title_bar_view.h | 2 +- apps/usb/usb_connected_controller.cpp | 2 +- apps/variable_box_controller.h | 2 +- apps/variable_box_empty_controller.cpp | 2 +- 59 files changed, 78 insertions(+), 67 deletions(-) diff --git a/.gitignore b/.gitignore index 36f753c92..2e261bfd8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,3 @@ -# No i18n headers -apps/i18n.h -apps/i18n.cpp - # Quiz output quiz/src/symbols.c diff --git a/apps/Makefile b/apps/Makefile index 31ef222b2..6c0d0a4cf 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -43,6 +43,12 @@ epsilon_app_names = '$(foreach i,${EPSILON_APPS},"$(i)", )' $(call object_for,apps/apps_container_storage.cpp apps/main.cpp): CXXFLAGS += $(snapshot_includes) -DAPPS_CONTAINER_APPS_DECLARATION="$(apps_declaration)" -DAPPS_CONTAINER_SNAPSHOT_DECLARATIONS="$(snapshots_declaration)" -DAPPS_CONTAINER_SNAPSHOT_CONSTRUCTORS="$(snapshots_construction)" -DAPPS_CONTAINER_SNAPSHOT_LIST="$(snapshots_list)" -DAPPS_CONTAINER_SNAPSHOT_COUNT=$(snapshots_count) -DEPSILON_APPS_NAMES=$(epsilon_app_names) + +# I18n file generation + +# The header is refered to as so make sure it's findable this way +SFLAGS += -I$(OUTPUT_DIRECTORY) + i18n_files += $(addprefix apps/language_,$(addsuffix .universal.i18n, $(EPSILON_I18N))) i18n_files += $(addprefix apps/,\ shared.de.i18n\ @@ -63,14 +69,23 @@ i18n_files += $(addprefix apps/,\ variables.pt.i18n\ ) -apps/i18n.h: apps/i18n.cpp -apps/i18n.cpp: $(i18n_files) - @echo "I18N $@" - $(Q) $(PYTHON) apps/i18n.py --header $(subst .cpp,.h,$@) --implementation $@ --locales $(EPSILON_I18N) --files $^ +$(eval $(call rule_for, \ + I18N, \ + apps/i18n.cpp, \ + $(i18n_files), \ + $$(PYTHON) apps/i18n.py --header $$(subst .cpp,.h,$$@) --implementation $$@ --locales $$(EPSILON_I18N) --files $$^ \ +)) -#$(app_objs): apps/i18n.h +# Make sure apps/i18n.o is built +# The extension added to app_src doesn't really matter since it'll be processed +# by the object_for function. +app_src += apps/i18n.py -products += apps/i18n.h apps/i18n.cpp +$(OUTPUT_DIRECTORY)/apps/i18n.h: $(OUTPUT_DIRECTORY)/apps/i18n.cpp + +$(call object_for,$(app_src)): $(OUTPUT_DIRECTORY)/apps/i18n.h + +# Handle PNG files $(eval $(call depends_on_image,apps/title_bar_view.cpp,apps/exam_icon.png)) diff --git a/apps/calculation/app.cpp b/apps/calculation/app.cpp index 5be4fa94f..44c2a938e 100644 --- a/apps/calculation/app.cpp +++ b/apps/calculation/app.cpp @@ -1,7 +1,7 @@ #include "app.h" #include "../apps_container.h" #include "calculation_icon.h" -#include "../i18n.h" +#include #include using namespace Poincare; diff --git a/apps/code/app.cpp b/apps/code/app.cpp index bedd3d0f1..16dfa0150 100644 --- a/apps/code/app.cpp +++ b/apps/code/app.cpp @@ -1,7 +1,7 @@ #include "app.h" #include "../apps_container.h" #include "code_icon.h" -#include "../i18n.h" +#include #include "helpers.h" namespace Code { diff --git a/apps/code/menu_controller.cpp b/apps/code/menu_controller.cpp index 940e145fe..bf4533456 100644 --- a/apps/code/menu_controller.cpp +++ b/apps/code/menu_controller.cpp @@ -1,6 +1,6 @@ #include "menu_controller.h" #include "app.h" -#include "../i18n.h" +#include #include "../apps_container.h" #include #include diff --git a/apps/code/script_parameter_controller.h b/apps/code/script_parameter_controller.h index 5d6fc6dcf..1fef1d752 100644 --- a/apps/code/script_parameter_controller.h +++ b/apps/code/script_parameter_controller.h @@ -2,7 +2,7 @@ #define CODE_SCRIPT_PARAMETER_CONTROLLER_H #include -#include "../i18n.h" +#include #include "script_store.h" namespace Code { diff --git a/apps/empty_battery_window.cpp b/apps/empty_battery_window.cpp index bae9b0f00..b0e58e2dd 100644 --- a/apps/empty_battery_window.cpp +++ b/apps/empty_battery_window.cpp @@ -1,6 +1,6 @@ #include "empty_battery_window.h" #include "global_preferences.h" -#include "i18n.h" +#include extern "C" { #include } diff --git a/apps/exam_pop_up_controller.cpp b/apps/exam_pop_up_controller.cpp index 915fcf547..b72bca2b5 100644 --- a/apps/exam_pop_up_controller.cpp +++ b/apps/exam_pop_up_controller.cpp @@ -1,6 +1,6 @@ #include "exam_pop_up_controller.h" #include "apps_container.h" -#include "i18n.h" +#include #include "global_preferences.h" #include diff --git a/apps/global_preferences.h b/apps/global_preferences.h index 07bbd5320..24ff19581 100644 --- a/apps/global_preferences.h +++ b/apps/global_preferences.h @@ -1,7 +1,7 @@ #ifndef APPS_GLOBAL_PREFERENCES_H #define APPS_GLOBAL_PREFERENCES_H -#include "i18n.h" +#include class GlobalPreferences { public: diff --git a/apps/graph/app.cpp b/apps/graph/app.cpp index 82ffd6d16..c150b7f97 100644 --- a/apps/graph/app.cpp +++ b/apps/graph/app.cpp @@ -1,7 +1,7 @@ #include "app.h" #include "../apps_container.h" #include "graph_icon.h" -#include "../i18n.h" +#include using namespace Poincare; using namespace Shared; diff --git a/apps/graph/graph/banner_view.cpp b/apps/graph/graph/banner_view.cpp index aebd501d1..0ce02d0b2 100644 --- a/apps/graph/graph/banner_view.cpp +++ b/apps/graph/graph/banner_view.cpp @@ -1,5 +1,5 @@ #include "banner_view.h" -#include "../../i18n.h" +#include namespace Graph { diff --git a/apps/graph/graph/calculation_parameter_controller.h b/apps/graph/graph/calculation_parameter_controller.h index a875c759e..9c483122a 100644 --- a/apps/graph/graph/calculation_parameter_controller.h +++ b/apps/graph/graph/calculation_parameter_controller.h @@ -10,7 +10,7 @@ #include "root_graph_controller.h" #include "graph_view.h" #include "banner_view.h" -#include "../../i18n.h" +#include namespace Graph { diff --git a/apps/graph/graph/curve_parameter_controller.cpp b/apps/graph/graph/curve_parameter_controller.cpp index e5e9da038..2361724e5 100644 --- a/apps/graph/graph/curve_parameter_controller.cpp +++ b/apps/graph/graph/curve_parameter_controller.cpp @@ -1,6 +1,6 @@ #include "curve_parameter_controller.h" #include "graph_controller.h" -#include "../../i18n.h" +#include #include using namespace Shared; diff --git a/apps/graph/list/storage_list_controller.cpp b/apps/graph/list/storage_list_controller.cpp index 3f560440d..aee95cac7 100644 --- a/apps/graph/list/storage_list_controller.cpp +++ b/apps/graph/list/storage_list_controller.cpp @@ -1,6 +1,6 @@ #include "storage_list_controller.h" #include "../app.h" -#include "../../i18n.h" +#include #include #include #include diff --git a/apps/hardware_test/pop_up_controller.cpp b/apps/hardware_test/pop_up_controller.cpp index 60b385232..791846dcf 100644 --- a/apps/hardware_test/pop_up_controller.cpp +++ b/apps/hardware_test/pop_up_controller.cpp @@ -1,5 +1,5 @@ #include "pop_up_controller.h" -#include "../i18n.h" +#include #include "../apps_container.h" #include diff --git a/apps/home/app.cpp b/apps/home/app.cpp index 6404f410a..b7fa2ff0b 100644 --- a/apps/home/app.cpp +++ b/apps/home/app.cpp @@ -1,5 +1,5 @@ #include "app.h" -#include "../i18n.h" +#include #include "../apps_container.h" extern "C" { diff --git a/apps/i18n.py b/apps/i18n.py index f83321a01..93ec034c9 100644 --- a/apps/i18n.py +++ b/apps/i18n.py @@ -116,7 +116,7 @@ def print_header(data, path, locales): def print_implementation(data, path, locales): f = open(path, 'w') f.write("#include \"i18n.h\"\n") - f.write("#include \"global_preferences.h\"\n") + f.write("#include \n") f.write("#include \n\n"); f.write("namespace I18n {\n\n") diff --git a/apps/on_boarding/pop_up_controller.h b/apps/on_boarding/pop_up_controller.h index 52d26b398..38eac9a73 100644 --- a/apps/on_boarding/pop_up_controller.h +++ b/apps/on_boarding/pop_up_controller.h @@ -2,7 +2,7 @@ #define ON_BOARDING_POP_UP_CONTROLLER_H #include -#include "../i18n.h" +#include #include "../shared/message_view.h" #include "../shared/ok_view.h" diff --git a/apps/probability/app.cpp b/apps/probability/app.cpp index fcc3cbef1..ae2e2f693 100644 --- a/apps/probability/app.cpp +++ b/apps/probability/app.cpp @@ -1,5 +1,5 @@ #include "app.h" -#include "../i18n.h" +#include #include "probability_icon.h" #include diff --git a/apps/probability/calculation_cell.cpp b/apps/probability/calculation_cell.cpp index 0caf55d1d..9b18129ac 100644 --- a/apps/probability/calculation_cell.cpp +++ b/apps/probability/calculation_cell.cpp @@ -1,6 +1,6 @@ #include "calculation_cell.h" #include "responder_image_cell.h" -#include "../i18n.h" +#include #include namespace Probability { diff --git a/apps/probability/law/law.h b/apps/probability/law/law.h index 61df4526f..6ebd6f6f3 100644 --- a/apps/probability/law/law.h +++ b/apps/probability/law/law.h @@ -4,7 +4,7 @@ #include #include "../../constant.h" #include "../../shared/curve_view_range.h" -#include "../../i18n.h" +#include namespace Probability { diff --git a/apps/regression/app.cpp b/apps/regression/app.cpp index 88f6d288e..afd5f27e9 100644 --- a/apps/regression/app.cpp +++ b/apps/regression/app.cpp @@ -1,6 +1,6 @@ #include "app.h" #include "regression_icon.h" -#include "../i18n.h" +#include using namespace Shared; diff --git a/apps/regression/initialisation_parameter_controller.h b/apps/regression/initialisation_parameter_controller.h index efc69276e..19ba8b26a 100644 --- a/apps/regression/initialisation_parameter_controller.h +++ b/apps/regression/initialisation_parameter_controller.h @@ -3,7 +3,7 @@ #include #include "store.h" -#include "../i18n.h" +#include namespace Regression { diff --git a/apps/regression/model/model.h b/apps/regression/model/model.h index 3dd12b0c3..86e586ee5 100644 --- a/apps/regression/model/model.h +++ b/apps/regression/model/model.h @@ -2,7 +2,7 @@ #define REGRESSION_MODEL_H #include -#include "../../i18n.h" +#include #include #include #include diff --git a/apps/regression/regression_controller.h b/apps/regression/regression_controller.h index 859c7e6b1..19c462fa3 100644 --- a/apps/regression/regression_controller.h +++ b/apps/regression/regression_controller.h @@ -3,7 +3,7 @@ #include "store.h" #include -#include "../i18n.h" +#include namespace Regression { diff --git a/apps/settings/app.cpp b/apps/settings/app.cpp index 891f2552d..d096c3d90 100644 --- a/apps/settings/app.cpp +++ b/apps/settings/app.cpp @@ -1,6 +1,6 @@ #include "app.h" #include "settings_icon.h" -#include "../i18n.h" +#include namespace Settings { diff --git a/apps/settings/main_controller.cpp b/apps/settings/main_controller.cpp index 97e03a7d3..df748f77e 100644 --- a/apps/settings/main_controller.cpp +++ b/apps/settings/main_controller.cpp @@ -1,6 +1,6 @@ #include "main_controller.h" #include "../global_preferences.h" -#include "../i18n.h" +#include #include using namespace Poincare; diff --git a/apps/shared/expression_field_delegate_app.cpp b/apps/shared/expression_field_delegate_app.cpp index 1549e8a30..84588f838 100644 --- a/apps/shared/expression_field_delegate_app.cpp +++ b/apps/shared/expression_field_delegate_app.cpp @@ -1,6 +1,6 @@ #include "expression_field_delegate_app.h" #include -#include "../i18n.h" +#include #include "../apps_container.h" using namespace Poincare; diff --git a/apps/shared/expression_model_list_controller.h b/apps/shared/expression_model_list_controller.h index 1b67dc22b..f8f910670 100644 --- a/apps/shared/expression_model_list_controller.h +++ b/apps/shared/expression_model_list_controller.h @@ -3,7 +3,7 @@ #include #include "expression_model_store.h" -#include "../i18n.h" +#include namespace Shared { diff --git a/apps/shared/function_list_controller.h b/apps/shared/function_list_controller.h index 24d1cf760..dc74a4058 100644 --- a/apps/shared/function_list_controller.h +++ b/apps/shared/function_list_controller.h @@ -6,7 +6,7 @@ #include "function_app.h" #include "list_parameter_controller.h" #include "expression_model_list_controller.h" -#include "../i18n.h" +#include namespace Shared { diff --git a/apps/shared/initialisation_parameter_controller.h b/apps/shared/initialisation_parameter_controller.h index 929040cfb..83bb27adf 100644 --- a/apps/shared/initialisation_parameter_controller.h +++ b/apps/shared/initialisation_parameter_controller.h @@ -3,7 +3,7 @@ #include #include "interactive_curve_view_range.h" -#include "../i18n.h" +#include namespace Shared { diff --git a/apps/shared/language_controller.cpp b/apps/shared/language_controller.cpp index d277a28f7..682806643 100644 --- a/apps/shared/language_controller.cpp +++ b/apps/shared/language_controller.cpp @@ -1,7 +1,7 @@ #include "language_controller.h" #include "../global_preferences.h" #include "../apps_container.h" -#include "../i18n.h" +#include namespace Shared { diff --git a/apps/shared/language_controller.h b/apps/shared/language_controller.h index 5dda27fac..746e68e1c 100644 --- a/apps/shared/language_controller.h +++ b/apps/shared/language_controller.h @@ -2,7 +2,7 @@ #define SHARED_LANGUAGE_CONTROLLER_H #include -#include "../i18n.h" +#include namespace Shared { diff --git a/apps/shared/list_parameter_controller.h b/apps/shared/list_parameter_controller.h index 8266e5496..4bde78f7f 100644 --- a/apps/shared/list_parameter_controller.h +++ b/apps/shared/list_parameter_controller.h @@ -4,7 +4,7 @@ #include #include "function.h" #include "function_store.h" -#include "../i18n.h" +#include namespace Shared { diff --git a/apps/shared/scrollable_exact_approximate_expressions_view.cpp b/apps/shared/scrollable_exact_approximate_expressions_view.cpp index 3b286e6b1..fc86fcfed 100644 --- a/apps/shared/scrollable_exact_approximate_expressions_view.cpp +++ b/apps/shared/scrollable_exact_approximate_expressions_view.cpp @@ -1,5 +1,5 @@ #include "scrollable_exact_approximate_expressions_view.h" -#include "../i18n.h" +#include #include using namespace Poincare; diff --git a/apps/shared/storage_expression_model_list_controller.h b/apps/shared/storage_expression_model_list_controller.h index 47d225b55..d2bdfb43d 100644 --- a/apps/shared/storage_expression_model_list_controller.h +++ b/apps/shared/storage_expression_model_list_controller.h @@ -3,7 +3,7 @@ #include #include "storage_expression_model_store.h" -#include "../i18n.h" +#include namespace Shared { diff --git a/apps/shared/storage_function_list_controller.h b/apps/shared/storage_function_list_controller.h index 2e48ed3a9..dfc7bcfe7 100644 --- a/apps/shared/storage_function_list_controller.h +++ b/apps/shared/storage_function_list_controller.h @@ -7,7 +7,7 @@ #include "function_title_cell.h" #include "storage_list_parameter_controller.h" #include "storage_expression_model_list_controller.h" -#include "../i18n.h" +#include namespace Shared { diff --git a/apps/shared/storage_list_parameter_controller.h b/apps/shared/storage_list_parameter_controller.h index 46aeb8921..35b56ffdd 100644 --- a/apps/shared/storage_list_parameter_controller.h +++ b/apps/shared/storage_list_parameter_controller.h @@ -3,7 +3,7 @@ #include #include "storage_function_store.h" -#include "../i18n.h" +#include namespace Shared { diff --git a/apps/shared/storage_values_controller.h b/apps/shared/storage_values_controller.h index 1e9fb5629..fa345d8e6 100644 --- a/apps/shared/storage_values_controller.h +++ b/apps/shared/storage_values_controller.h @@ -9,7 +9,7 @@ #include "values_parameter_controller.h" #include "storage_values_function_parameter_controller.h" #include "interval_parameter_controller.h" -#include "../i18n.h" +#include namespace Shared { diff --git a/apps/shared/storage_values_function_parameter_controller.h b/apps/shared/storage_values_function_parameter_controller.h index d41e51073..6d2a4b376 100644 --- a/apps/shared/storage_values_function_parameter_controller.h +++ b/apps/shared/storage_values_function_parameter_controller.h @@ -3,7 +3,7 @@ #include #include "storage_function.h" -#include "../i18n.h" +#include namespace Shared { diff --git a/apps/shared/store_parameter_controller.h b/apps/shared/store_parameter_controller.h index 602ffd7aa..fa3212778 100644 --- a/apps/shared/store_parameter_controller.h +++ b/apps/shared/store_parameter_controller.h @@ -3,7 +3,7 @@ #include #include "double_pair_store.h" -#include "../i18n.h" +#include namespace Shared { diff --git a/apps/shared/text_field_delegate_app.h b/apps/shared/text_field_delegate_app.h index 3bad9e1ac..20e6eb0e8 100644 --- a/apps/shared/text_field_delegate_app.h +++ b/apps/shared/text_field_delegate_app.h @@ -4,7 +4,7 @@ #include #include #include "input_event_handler_delegate_app.h" -#include "../i18n.h" +#include class AppsContainer; diff --git a/apps/shared/values_controller.h b/apps/shared/values_controller.h index 525c6210c..2eca47217 100644 --- a/apps/shared/values_controller.h +++ b/apps/shared/values_controller.h @@ -9,7 +9,7 @@ #include "values_parameter_controller.h" #include "values_function_parameter_controller.h" #include "interval_parameter_controller.h" -#include "../i18n.h" +#include namespace Shared { diff --git a/apps/shared/values_function_parameter_controller.h b/apps/shared/values_function_parameter_controller.h index 7fd5f017f..b6c303d8a 100644 --- a/apps/shared/values_function_parameter_controller.h +++ b/apps/shared/values_function_parameter_controller.h @@ -3,7 +3,7 @@ #include #include "function.h" -#include "../i18n.h" +#include namespace Shared { diff --git a/apps/shared/zoom_parameter_controller.h b/apps/shared/zoom_parameter_controller.h index 186d9a468..13751a1b2 100644 --- a/apps/shared/zoom_parameter_controller.h +++ b/apps/shared/zoom_parameter_controller.h @@ -4,7 +4,7 @@ #include #include "interactive_curve_view_range.h" #include "curve_view.h" -#include "../i18n.h" +#include namespace Shared { diff --git a/apps/shift_alpha_lock_view.h b/apps/shift_alpha_lock_view.h index f96dcfedc..b3b0bd05d 100644 --- a/apps/shift_alpha_lock_view.h +++ b/apps/shift_alpha_lock_view.h @@ -3,7 +3,7 @@ #include #include "lock_view.h" -#include "i18n.h" +#include class ShiftAlphaLockView : public View { public: diff --git a/apps/solver/app.cpp b/apps/solver/app.cpp index f00b7abe0..a27ad587e 100644 --- a/apps/solver/app.cpp +++ b/apps/solver/app.cpp @@ -1,5 +1,5 @@ #include "app.h" -#include "../i18n.h" +#include #include "solver_icon.h" using namespace Shared; diff --git a/apps/solver/equation_models_parameter_controller.cpp b/apps/solver/equation_models_parameter_controller.cpp index 33ecf50d1..d1ab2622c 100644 --- a/apps/solver/equation_models_parameter_controller.cpp +++ b/apps/solver/equation_models_parameter_controller.cpp @@ -3,7 +3,7 @@ #include "../constant.h" #include #include -#include "../i18n.h" +#include using namespace Poincare; diff --git a/apps/solver/interval_controller.cpp b/apps/solver/interval_controller.cpp index 16514c0c9..19d061602 100644 --- a/apps/solver/interval_controller.cpp +++ b/apps/solver/interval_controller.cpp @@ -1,6 +1,6 @@ #include "interval_controller.h" #include "app.h" -#include "../i18n.h" +#include #include #include diff --git a/apps/solver/list_controller.h b/apps/solver/list_controller.h index 9355e9f37..14ca87f87 100644 --- a/apps/solver/list_controller.h +++ b/apps/solver/list_controller.h @@ -8,7 +8,7 @@ #include "equation_store.h" #include "equation_list_view.h" #include "equation_models_parameter_controller.h" -#include "../i18n.h" +#include namespace Solver { diff --git a/apps/solver/solutions_controller.h b/apps/solver/solutions_controller.h index 6ad68bceb..172faf761 100644 --- a/apps/solver/solutions_controller.h +++ b/apps/solver/solutions_controller.h @@ -4,7 +4,7 @@ #include #include "equation_store.h" #include "../shared/scrollable_exact_approximate_expressions_cell.h" -#include "../i18n.h" +#include namespace Solver { diff --git a/apps/statistics/app.cpp b/apps/statistics/app.cpp index 64c935553..787e51ace 100644 --- a/apps/statistics/app.cpp +++ b/apps/statistics/app.cpp @@ -1,6 +1,6 @@ #include "app.h" #include "stat_icon.h" -#include "../i18n.h" +#include using namespace Shared; diff --git a/apps/statistics/box_banner_view.h b/apps/statistics/box_banner_view.h index 9192e8275..a53060061 100644 --- a/apps/statistics/box_banner_view.h +++ b/apps/statistics/box_banner_view.h @@ -3,7 +3,7 @@ #include #include "../shared/banner_view.h" -#include "../i18n.h" +#include namespace Statistics { diff --git a/apps/statistics/histogram_banner_view.h b/apps/statistics/histogram_banner_view.h index dcb3df8f3..161c78a37 100644 --- a/apps/statistics/histogram_banner_view.h +++ b/apps/statistics/histogram_banner_view.h @@ -3,7 +3,7 @@ #include #include "../shared/banner_view.h" -#include "../i18n.h" +#include namespace Statistics { diff --git a/apps/statistics/multiple_data_view_controller.cpp b/apps/statistics/multiple_data_view_controller.cpp index c9687b55c..73ed94fe9 100644 --- a/apps/statistics/multiple_data_view_controller.cpp +++ b/apps/statistics/multiple_data_view_controller.cpp @@ -1,5 +1,5 @@ #include "multiple_data_view_controller.h" -#include "../i18n.h" +#include #include using namespace Shared; diff --git a/apps/title_bar_view.h b/apps/title_bar_view.h index 264be8a96..b5335dc76 100644 --- a/apps/title_bar_view.h +++ b/apps/title_bar_view.h @@ -4,7 +4,7 @@ #include #include "battery_view.h" #include "shift_alpha_lock_view.h" -#include "i18n.h" +#include class TitleBarView : public View { public: diff --git a/apps/usb/usb_connected_controller.cpp b/apps/usb/usb_connected_controller.cpp index a03835dc6..189c060bd 100644 --- a/apps/usb/usb_connected_controller.cpp +++ b/apps/usb/usb_connected_controller.cpp @@ -1,5 +1,5 @@ #include "usb_connected_controller.h" -#include "../i18n.h" +#include namespace USB { diff --git a/apps/variable_box_controller.h b/apps/variable_box_controller.h index f4e986a97..13da1ea3c 100644 --- a/apps/variable_box_controller.h +++ b/apps/variable_box_controller.h @@ -6,7 +6,7 @@ #include #include "shared/global_context.h" #include "variable_box_empty_controller.h" -#include "i18n.h" +#include class VariableBoxController : public NestedMenuController { public: diff --git a/apps/variable_box_empty_controller.cpp b/apps/variable_box_empty_controller.cpp index 741b025ae..0c810bdd8 100644 --- a/apps/variable_box_empty_controller.cpp +++ b/apps/variable_box_empty_controller.cpp @@ -1,7 +1,7 @@ #include "variable_box_empty_controller.h" #include #include "graph/storage_cartesian_function_store.h" -#include "i18n.h" +#include #include using namespace Poincare; From 2af792cf88cba3a7e1bea1c2a6af7a41c9766369 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Tue, 5 Mar 2019 17:25:12 +0100 Subject: [PATCH 351/373] [build] Rename the build folder to scripts --- Makefile | 8 ++++---- {build => scripts}/config.mak | 6 +++--- {build => scripts}/defaults.mak | 0 {build => scripts}/device/gdb_script.gdb | 0 {build => scripts}/device/memory_map.awk | 0 {build => scripts}/device/openocd.cfg | 0 {build => scripts}/platform.blackbox.mak | 0 {build => scripts}/platform.device.mak | 0 {build => scripts}/platform.emscripten.mak | 0 {build => scripts}/platform.simulator.mak | 0 {build => scripts}/scenario/Makefile | 0 {build => scripts}/struct_layout/Makefile | 6 +++--- {build => scripts}/struct_layout/ast_to_json.rb | 0 {build => scripts}/struct_layout/visualization.html | 0 {build => scripts}/targets.blackbox.mak | 0 {build => scripts}/targets.device.mak | 6 +++--- {build => scripts}/targets.emscripten.mak | 0 {build => scripts}/toolchain.afl.mak | 0 {build => scripts}/toolchain.arm-gcc.mak | 0 {build => scripts}/toolchain.arm-llvm.mak | 0 {build => scripts}/toolchain.emscripten.mak | 0 {build => scripts}/toolchain.host-clang.mak | 0 {build => scripts}/toolchain.host-gcc.mak | 0 {build => scripts}/toolchain.mingw.mak | 0 24 files changed, 13 insertions(+), 13 deletions(-) rename {build => scripts}/config.mak (91%) rename {build => scripts}/defaults.mak (100%) rename {build => scripts}/device/gdb_script.gdb (100%) rename {build => scripts}/device/memory_map.awk (100%) rename {build => scripts}/device/openocd.cfg (100%) rename {build => scripts}/platform.blackbox.mak (100%) rename {build => scripts}/platform.device.mak (100%) rename {build => scripts}/platform.emscripten.mak (100%) rename {build => scripts}/platform.simulator.mak (100%) rename {build => scripts}/scenario/Makefile (100%) rename {build => scripts}/struct_layout/Makefile (69%) rename {build => scripts}/struct_layout/ast_to_json.rb (100%) rename {build => scripts}/struct_layout/visualization.html (100%) rename {build => scripts}/targets.blackbox.mak (100%) rename {build => scripts}/targets.device.mak (93%) rename {build => scripts}/targets.emscripten.mak (100%) rename {build => scripts}/toolchain.afl.mak (100%) rename {build => scripts}/toolchain.arm-gcc.mak (100%) rename {build => scripts}/toolchain.arm-llvm.mak (100%) rename {build => scripts}/toolchain.emscripten.mak (100%) rename {build => scripts}/toolchain.host-clang.mak (100%) rename {build => scripts}/toolchain.host-gcc.mak (100%) rename {build => scripts}/toolchain.mingw.mak (100%) diff --git a/Makefile b/Makefile index b626d010b..fa3245c40 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -include build/config.mak +include scripts/config.mak # Disable default Make rules .SUFFIXES: @@ -62,8 +62,8 @@ include python/Makefile include escher/Makefile # Executable Makefiles include apps/Makefile -include build/struct_layout/Makefile -include build/scenario/Makefile +include scripts/struct_layout/Makefile +include scripts/scenario/Makefile include quiz/Makefile # Quiz needs to be included at the end objs = $(call object_for,$(src)) @@ -121,4 +121,4 @@ cowsay_%: .PHONY: clena clena: cowsay_CLENA clean --include build/targets.$(PLATFORM).mak +-include scripts/targets.$(PLATFORM).mak diff --git a/build/config.mak b/scripts/config.mak similarity index 91% rename from build/config.mak rename to scripts/config.mak index 9aed19263..db7ca1277 100644 --- a/build/config.mak +++ b/scripts/config.mak @@ -13,15 +13,15 @@ EPSILON_GETOPT ?= 0 MATRICES_ARE_DEFINED ?=1 ESCHER_LOG_EVENTS_BINARY ?= 0 -include build/defaults.mak -include build/platform.$(PLATFORM).mak +include scripts/defaults.mak +include scripts/platform.$(PLATFORM).mak ifndef USE_LIBA $(error platform.mak should define USE_LIBA) endif ifndef EXE $(error platform.mak should define EXE, the extension for executables) endif -include build/toolchain.$(TOOLCHAIN).mak +include scripts/toolchain.$(TOOLCHAIN).mak SFLAGS += -DDEBUG=$(DEBUG) SFLAGS += -DEPSILON_ONBOARDING_APP=$(EPSILON_ONBOARDING_APP) diff --git a/build/defaults.mak b/scripts/defaults.mak similarity index 100% rename from build/defaults.mak rename to scripts/defaults.mak diff --git a/build/device/gdb_script.gdb b/scripts/device/gdb_script.gdb similarity index 100% rename from build/device/gdb_script.gdb rename to scripts/device/gdb_script.gdb diff --git a/build/device/memory_map.awk b/scripts/device/memory_map.awk similarity index 100% rename from build/device/memory_map.awk rename to scripts/device/memory_map.awk diff --git a/build/device/openocd.cfg b/scripts/device/openocd.cfg similarity index 100% rename from build/device/openocd.cfg rename to scripts/device/openocd.cfg diff --git a/build/platform.blackbox.mak b/scripts/platform.blackbox.mak similarity index 100% rename from build/platform.blackbox.mak rename to scripts/platform.blackbox.mak diff --git a/build/platform.device.mak b/scripts/platform.device.mak similarity index 100% rename from build/platform.device.mak rename to scripts/platform.device.mak diff --git a/build/platform.emscripten.mak b/scripts/platform.emscripten.mak similarity index 100% rename from build/platform.emscripten.mak rename to scripts/platform.emscripten.mak diff --git a/build/platform.simulator.mak b/scripts/platform.simulator.mak similarity index 100% rename from build/platform.simulator.mak rename to scripts/platform.simulator.mak diff --git a/build/scenario/Makefile b/scripts/scenario/Makefile similarity index 100% rename from build/scenario/Makefile rename to scripts/scenario/Makefile diff --git a/build/struct_layout/Makefile b/scripts/struct_layout/Makefile similarity index 69% rename from build/struct_layout/Makefile rename to scripts/struct_layout/Makefile index 1d15f379a..df5ec0241 100644 --- a/build/struct_layout/Makefile +++ b/scripts/struct_layout/Makefile @@ -1,4 +1,4 @@ -products += apps/main.ast build/struct_layout/data.json +products += apps/main.ast scripts/struct_layout/data.json .PHONY: apps_container_struct_layout OPEN = open @@ -11,10 +11,10 @@ ifeq ($(CXX),clang++) %.ast.json: %.ast @echo "JSON $@" - @cat $< | ruby build/struct_layout/ast_to_json.rb AppsContainer > $@ + @cat $< | ruby scripts/struct_layout/ast_to_json.rb AppsContainer > $@ apps_container_struct_layout: apps/main.ast.json - $(OPEN) build/struct_layout/visualization.html + $(OPEN) scripts/struct_layout/visualization.html else diff --git a/build/struct_layout/ast_to_json.rb b/scripts/struct_layout/ast_to_json.rb similarity index 100% rename from build/struct_layout/ast_to_json.rb rename to scripts/struct_layout/ast_to_json.rb diff --git a/build/struct_layout/visualization.html b/scripts/struct_layout/visualization.html similarity index 100% rename from build/struct_layout/visualization.html rename to scripts/struct_layout/visualization.html diff --git a/build/targets.blackbox.mak b/scripts/targets.blackbox.mak similarity index 100% rename from build/targets.blackbox.mak rename to scripts/targets.blackbox.mak diff --git a/build/targets.device.mak b/scripts/targets.device.mak similarity index 93% rename from build/targets.device.mak rename to scripts/targets.device.mak index 5a33eea6f..50d682ae9 100644 --- a/build/targets.device.mak +++ b/scripts/targets.device.mak @@ -25,7 +25,7 @@ products += $(patsubst %.$(EXE),%.map,$(filter %.$(EXE),$(products))) .PHONY: %_run %_run: %.$(EXE) - $(GDB) -x build/device/gdb_script.gdb $< + $(GDB) -x scripts/device/gdb_script.gdb $< %.map: %.elf @echo "LDMAP $@" @@ -34,7 +34,7 @@ products += $(patsubst %.$(EXE),%.map,$(filter %.$(EXE),$(products))) .PHONY: %_memory_map %_memory_map: %.map @echo "========== MEMORY MAP =========" - $(Q) awk -f build/device/memory_map.awk < $< + $(Q) awk -f scripts/device/memory_map.awk < $< @echo "===============================" .PHONY: %_flash @@ -48,7 +48,7 @@ products += $(patsubst %.$(EXE),%.map,$(filter %.$(EXE),$(products))) .PHONY: openocd openocd: - openocd -f build/device/openocd.cfg + openocd -f scripts/device/openocd.cfg ifeq ($(EPSILON_USB_DFU_XIP)$(EPSILON_DEVICE_BENCH),10) flasher.$(EXE): LDFLAGS = --gc-sections -T ion/src/device/usb/flasher.ld diff --git a/build/targets.emscripten.mak b/scripts/targets.emscripten.mak similarity index 100% rename from build/targets.emscripten.mak rename to scripts/targets.emscripten.mak diff --git a/build/toolchain.afl.mak b/scripts/toolchain.afl.mak similarity index 100% rename from build/toolchain.afl.mak rename to scripts/toolchain.afl.mak diff --git a/build/toolchain.arm-gcc.mak b/scripts/toolchain.arm-gcc.mak similarity index 100% rename from build/toolchain.arm-gcc.mak rename to scripts/toolchain.arm-gcc.mak diff --git a/build/toolchain.arm-llvm.mak b/scripts/toolchain.arm-llvm.mak similarity index 100% rename from build/toolchain.arm-llvm.mak rename to scripts/toolchain.arm-llvm.mak diff --git a/build/toolchain.emscripten.mak b/scripts/toolchain.emscripten.mak similarity index 100% rename from build/toolchain.emscripten.mak rename to scripts/toolchain.emscripten.mak diff --git a/build/toolchain.host-clang.mak b/scripts/toolchain.host-clang.mak similarity index 100% rename from build/toolchain.host-clang.mak rename to scripts/toolchain.host-clang.mak diff --git a/build/toolchain.host-gcc.mak b/scripts/toolchain.host-gcc.mak similarity index 100% rename from build/toolchain.host-gcc.mak rename to scripts/toolchain.host-gcc.mak diff --git a/build/toolchain.mingw.mak b/scripts/toolchain.mingw.mak similarity index 100% rename from build/toolchain.mingw.mak rename to scripts/toolchain.mingw.mak From bd6339f9dc584d96d37ecf17ccbef074df78cb08 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Tue, 5 Mar 2019 17:37:18 +0100 Subject: [PATCH 352/373] [make] Rename OUTPUT_DIRECTORY to build_dir --- Makefile | 30 +++++++++++++++--------------- apps/Makefile | 10 +++++----- escher/Makefile | 4 ++-- ion/src/device/Makefile | 8 ++++---- ion/src/device/usb/Makefile | 6 +++--- kandinsky/Makefile | 2 +- python/Makefile | 4 ++-- 7 files changed, 32 insertions(+), 32 deletions(-) diff --git a/Makefile b/Makefile index fa3245c40..0be03da61 100644 --- a/Makefile +++ b/Makefile @@ -3,23 +3,23 @@ include scripts/config.mak # Disable default Make rules .SUFFIXES: -OUTPUT_DIRECTORY = outputs -object_for = $(addprefix $(OUTPUT_DIRECTORY)/,$(addsuffix .o,$(basename $(1)))) +build_dir = build +object_for = $(addprefix $(build_dir)/,$(addsuffix .o,$(basename $(1)))) -default: $(OUTPUT_DIRECTORY)/epsilon.$(EXE) +default: $(build_dir)/epsilon.$(EXE) # Define a standard rule helper # If passed a last parameter value of with_local_version, we also define an -# extra rule that can build source files within the $(OUTPUT_DIRECTORY). This is -# useful for rules that can be applied for intermediate objects (for example, -# when going .png -> .cpp -> .o). +# extra rule that can build source files within the $(build_dir). This is useful +# for rules that can be applied for intermediate objects (for example, when +# going .png -> .cpp -> .o). define rule_for -$(addprefix $$(OUTPUT_DIRECTORY)/,$(strip $(2))): $(strip $(3)) | $$$$(@D)/. - @ echo "$(shell printf "%-8s" $(strip $(1)))$$(@:$$(OUTPUT_DIRECTORY)/%=%)" +$(addprefix $$(build_dir)/,$(strip $(2))): $(strip $(3)) | $$$$(@D)/. + @ echo "$(shell printf "%-8s" $(strip $(1)))$$(@:$$(build_dir)/%=%)" $(Q) $(4) ifeq ($(strip $(5)),with_local_version) -$(addprefix $$(OUTPUT_DIRECTORY)/,$(strip $(2))): $(addprefix $$(OUTPUT_DIRECTORY)/,$(strip $(3))) - @ echo "$(shell printf "%-8s" $(strip $(1)))$$(@:$$(OUTPUT_DIRECTORY)/%=%)" +$(addprefix $$(build_dir)/,$(strip $(2))): $(addprefix $$(build_dir)/,$(strip $(3))) + @ echo "$(shell printf "%-8s" $(strip $(1)))$$(@:$$(build_dir)/%=%)" $(Q) $(4) endif endef @@ -37,8 +37,8 @@ info: # "output/foo/bar.o" because the directory "output/foo" doesn't exist). # We need to mark those directories as precious, otherwise Make will try to get # rid of them upon completion (and fail, since those folders won't be empty). -.PRECIOUS: $(OUTPUT_DIRECTORY)/. $(OUTPUT_DIRECTORY)%/. -$(OUTPUT_DIRECTORY)/. $(OUTPUT_DIRECTORY)%/.: +.PRECIOUS: $(build_dir)/. $(build_dir)%/. +$(build_dir)/. $(build_dir)%/.: $(Q) mkdir -p $(dir $@) # To make objects dependent on their directory, we need a second expansion @@ -75,8 +75,8 @@ objs = $(call object_for,$(src)) -include $(objs:.o=.d) .SECONDARY: $(objs) -$(OUTPUT_DIRECTORY)/epsilon.$(EXE): $(objs) -$(OUTPUT_DIRECTORY)/test.$(EXE): $(objs) +$(build_dir)/epsilon.$(EXE): $(objs) +$(build_dir)/test.$(EXE): $(objs) # Define standard compilation rules @@ -105,7 +105,7 @@ $(eval $(call rule_for, \ .PHONY: clean clean: @echo "CLEAN" - $(Q) rm -rf $(OUTPUT_DIRECTORY) + $(Q) rm -rf $(build_dir) .PHONY: cowsay_% cowsay_%: diff --git a/apps/Makefile b/apps/Makefile index 6c0d0a4cf..3b247ce34 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -47,7 +47,7 @@ $(call object_for,apps/apps_container_storage.cpp apps/main.cpp): CXXFLAGS += $( # I18n file generation # The header is refered to as so make sure it's findable this way -SFLAGS += -I$(OUTPUT_DIRECTORY) +SFLAGS += -I$(build_dir) i18n_files += $(addprefix apps/language_,$(addsuffix .universal.i18n, $(EPSILON_I18N))) i18n_files += $(addprefix apps/,\ @@ -81,9 +81,9 @@ $(eval $(call rule_for, \ # by the object_for function. app_src += apps/i18n.py -$(OUTPUT_DIRECTORY)/apps/i18n.h: $(OUTPUT_DIRECTORY)/apps/i18n.cpp +$(build_dir)/apps/i18n.h: $(build_dir)/apps/i18n.cpp -$(call object_for,$(app_src)): $(OUTPUT_DIRECTORY)/apps/i18n.h +$(call object_for,$(app_src)): $(build_dir)/apps/i18n.h # Handle PNG files @@ -96,8 +96,8 @@ $(eval $(call depends_on_image,apps/title_bar_view.cpp,apps/exam_icon.png)) # As a shortcut, we simply say that every app file depends on every image. In # practice, this forces all the images to be before the app. -#app_image_objs := $(OUTPUT_DIRECTORY)/$(app_images:.png=.o) -#.SECONDARY: $(OUTPUT_DIRECTORY)/$(app_images:.png=.cpp) +#app_image_objs := $(build_dir)/$(app_images:.png=.o) +#.SECONDARY: $(build_dir)/$(app_images:.png=.cpp) #$(app_objs): $(app_image_objs) #app_image_src := $(app_images:.png=.cpp) diff --git a/escher/Makefile b/escher/Makefile index 12aee399e..9f0607e99 100644 --- a/escher/Makefile +++ b/escher/Makefile @@ -95,9 +95,9 @@ $(eval $(call rule_for, \ $$(HOSTCC) -std=c99 `libpng-config --cflags` $$^ `libpng-config --ldflags` -o $$@ \ )) -INLINER := $(OUTPUT_DIRECTORY)/escher/image/inliner +INLINER := $(build_dir)/escher/image/inliner -.PRECIOUS: $(OUTPUT_DIRECTORY)/%.h $(OUTPUT_DIRECTORY)/%.cpp +.PRECIOUS: $(build_dir)/%.h $(build_dir)/%.cpp $(eval $(call rule_for, \ INLINER, \ %.h %.cpp, \ diff --git a/ion/src/device/Makefile b/ion/src/device/Makefile index d6f784acc..ca71adb6c 100644 --- a/ion/src/device/Makefile +++ b/ion/src/device/Makefile @@ -41,10 +41,10 @@ src += $(addprefix ion/src/device/, \ ifneq ($(DEBUG),1) ifneq ($(COMPILER),llvm) -$(OUTPUT_DIRECTORY)/ion/src/device/led.o: SFLAGS+=-O3 -$(OUTPUT_DIRECTORY)/ion/src/device/console.o: SFLAGS+=-O3 -$(OUTPUT_DIRECTORY)/ion/src/device/display.o: SFLAGS+=-O3 -$(OUTPUT_DIRECTORY)/ion/src/device/swd.o: SFLAGS+=-O3 +$(build_dir)/ion/src/device/led.o: SFLAGS+=-O3 +$(build_dir)/ion/src/device/console.o: SFLAGS+=-O3 +$(build_dir)/ion/src/device/display.o: SFLAGS+=-O3 +$(build_dir)/ion/src/device/swd.o: SFLAGS+=-O3 endif endif diff --git a/ion/src/device/usb/Makefile b/ion/src/device/usb/Makefile index aca2218de..eb539a3ad 100644 --- a/ion/src/device/usb/Makefile +++ b/ion/src/device/usb/Makefile @@ -52,8 +52,8 @@ dfu_src += ion/src/device/base64.cpp dfu_src += ion/src/device/flash.cpp dfu_src += ion/src/device/timing.cpp -$(OUTPUT_DIRECTORY)/ion/src/device/usb/dfu.elf: LDSCRIPT = ion/src/device/usb/dfu.ld -$(OUTPUT_DIRECTORY)/ion/src/device/usb/dfu.elf: $(call object_for,$(usb_src)) $(call object_for,$(dfu_src)) +$(build_dir)/ion/src/device/usb/dfu.elf: LDSCRIPT = ion/src/device/usb/dfu.ld +$(build_dir)/ion/src/device/usb/dfu.elf: $(call object_for,$(usb_src)) $(call object_for,$(dfu_src)) # This command embeds a binary file into an object one. # This allows us to embed standalone code (the dfu routines) into the final @@ -62,7 +62,7 @@ $(OUTPUT_DIRECTORY)/ion/src/device/usb/dfu.elf: $(call object_for,$(usb_src)) $( # and end), but prefixes them with a mangled file path. To have consistent names # we simply "cd" into the directory. This assumes input and output lives in the # same directory. -$(OUTPUT_DIRECTORY)/ion/src/device/usb/dfu.o: $(OUTPUT_DIRECTORY)/ion/src/device/usb/dfu.bin +$(build_dir)/ion/src/device/usb/dfu.o: $(build_dir)/ion/src/device/usb/dfu.bin @echo "OBJCOPY $@" $(Q) cd $(dir $<) ; $(OBJCOPY) -I binary -O elf32-littlearm -B arm --rename-section .data=.rodata --redefine-sym _binary_dfu_bin_start=_dfu_bootloader_flash_start --redefine-sym _binary_dfu_bin_end=_dfu_bootloader_flash_end $(notdir $<) $(notdir $@) diff --git a/kandinsky/Makefile b/kandinsky/Makefile index d9d3793ea..7e7ab6a48 100644 --- a/kandinsky/Makefile +++ b/kandinsky/Makefile @@ -41,7 +41,7 @@ $(eval $(call rule_for, \ $$(HOSTCC) $$(RASTERIZER_CFLAGS) $$^ $$(RASTERIZER_LDFLAGS) -o $$@ \ )) -RASTERIZER := $(OUTPUT_DIRECTORY)/kandinsky/fonts/rasterizer +RASTERIZER := $(build_dir)/kandinsky/fonts/rasterizer $(eval $(call rule_for, \ RASTER, \ diff --git a/python/Makefile b/python/Makefile index 35c23812c..ee277e8d6 100644 --- a/python/Makefile +++ b/python/Makefile @@ -1,6 +1,6 @@ SFLAGS += -Ipython/src SFLAGS += -Ipython/port -SFLAGS += -I$(OUTPUT_DIRECTORY)/python/port +SFLAGS += -I$(build_dir)/python/port # How to maintain this Makefile # - Copy PY_CORE_O_BASENAME from py.mk into py_objs @@ -177,6 +177,6 @@ $(eval $(call rule_for, \ $$(PYTHON) python/src/py/makeqstrdata.py $$< > $$@ \ )) -$(call object_for,$(python_src)): $(OUTPUT_DIRECTORY)/python/port/genhdr/qstrdefs.generated.h +$(call object_for,$(python_src)): $(build_dir)/python/port/genhdr/qstrdefs.generated.h src += $(python_src) From ef3f5b877c10599397d422f817fedc8a12dabcf5 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Tue, 5 Mar 2019 17:38:46 +0100 Subject: [PATCH 353/373] [apps] Delete the long-dead PicView app --- apps/apps_container.h | 8 -------- apps/picview/Makefile | 18 ------------------ apps/picview/pic_view.cpp | 14 -------------- apps/picview/pic_view.h | 12 ------------ apps/picview/picview_app.cpp | 7 ------- apps/picview/picview_app.h | 14 -------------- apps/picview/picview_controller.cpp | 18 ------------------ apps/picview/picview_controller.h | 15 --------------- 8 files changed, 106 deletions(-) delete mode 100644 apps/picview/Makefile delete mode 100644 apps/picview/pic_view.cpp delete mode 100644 apps/picview/pic_view.h delete mode 100644 apps/picview/picview_app.cpp delete mode 100644 apps/picview/picview_app.h delete mode 100644 apps/picview/picview_controller.cpp delete mode 100644 apps/picview/picview_controller.h diff --git a/apps/apps_container.h b/apps/apps_container.h index cda82c429..5f23fbd1a 100644 --- a/apps/apps_container.h +++ b/apps/apps_container.h @@ -16,11 +16,6 @@ #include "backlight_dimming_timer.h" #include "shared/global_context.h" -#define USE_PIC_VIEW_APP 0 -#if USE_PIC_VIEW_APP -#include "picview/picview_app.h" -#endif - #ifdef EPSILON_BOOT_PROMPT #include "on_boarding/pop_up_controller.h" #endif @@ -70,9 +65,6 @@ private: AppsWindow m_window; EmptyBatteryWindow m_emptyBatteryWindow; -#if USE_PIC_VIEW_APP - PicViewApp m_picViewApp; -#endif Shared::GlobalContext m_globalContext; MathToolbox m_mathToolbox; VariableBoxController m_variableBoxController; diff --git a/apps/picview/Makefile b/apps/picview/Makefile deleted file mode 100644 index f08668d38..000000000 --- a/apps/picview/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -app_objs += $(addprefix apps/picview/,\ - pic_view.o\ - picview_app.o\ - picview_controller.o\ -) - -apps/picview/pic_view.cpp: apps/picview/image.c - -apps/picview/image.c: apps/picview/image.raw - @echo "RAW2C $@" - @echo "const /* Needed otherwise the image will eat up all RAM */" > $@ - @xxd -i $^ >> $@ - -apps/picview/image.raw: apps/picview/image.png - @echo "PNG2RAW $@" - @ffmpeg -loglevel panic -vcodec png -i $^ -vcodec rawvideo -f rawvideo -pix_fmt rgb565 $@ - -products += $(addprefix apps/picview/, image.raw image.c) diff --git a/apps/picview/pic_view.cpp b/apps/picview/pic_view.cpp deleted file mode 100644 index a12779f97..000000000 --- a/apps/picview/pic_view.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "pic_view.h" -#include - -PicView::PicView() : - View() { -} - -#include "image.c" - -void PicView::drawRect(KDContext * ctx, KDRect rect) const { - KDColor * pixels = (KDColor *)apps_picview_image_raw; - assert(apps_picview_image_raw_len == bounds().width() * bounds().height() * sizeof(KDColor)); - ctx->fillRectWithPixels(bounds(), pixels, nullptr); -} diff --git a/apps/picview/pic_view.h b/apps/picview/pic_view.h deleted file mode 100644 index 2beb68f96..000000000 --- a/apps/picview/pic_view.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef PICVIEW_PIC_VIEW_H -#define PICVIEW_PIC_VIEW_H - -#include - -class PicView : public View { -public: - PicView(); - void drawRect(KDContext * ctx, KDRect rect) const override; -}; - -#endif diff --git a/apps/picview/picview_app.cpp b/apps/picview/picview_app.cpp deleted file mode 100644 index 09e94215a..000000000 --- a/apps/picview/picview_app.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "picview_app.h" - -PicViewApp::PicViewApp(Container * container) : - ::App(container, &m_picViewController), - m_picViewController(PicViewController(&m_modalViewController)) -{ -} diff --git a/apps/picview/picview_app.h b/apps/picview/picview_app.h deleted file mode 100644 index 8040b0f25..000000000 --- a/apps/picview/picview_app.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef PICVIEW_PICVIEW_APP_H -#define PICVIEW_PICVIEW_APP_H - -#include -#include "picview_controller.h" - -class PicViewApp : public App { -public: - PicViewApp(Container * container); -private: - PicViewController m_picViewController; -}; - -#endif diff --git a/apps/picview/picview_controller.cpp b/apps/picview/picview_controller.cpp deleted file mode 100644 index b4c6610ea..000000000 --- a/apps/picview/picview_controller.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "picview_controller.h" - -PicViewController::PicViewController(Responder * parentResponder) : - ViewController(parentResponder), - m_view(PicView()) -{ -} - -View * PicViewController::view() { - return &m_view; -} - -/* - -const char * PicViewController::title() { - return "PicView"; -} -*/ diff --git a/apps/picview/picview_controller.h b/apps/picview/picview_controller.h deleted file mode 100644 index 846596aa2..000000000 --- a/apps/picview/picview_controller.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef PICVIEW_PICVIEW_CONTROLLER_H -#define PICVIEW_PICVIEW_CONTROLLER_H - -#include -#include "pic_view.h" - -class PicViewController : public ViewController { -public: - PicViewController(Responder * parentResponder); - View * view() override; -private: - PicView m_view; -}; - -#endif From 0c83253d2ef0db48fbb6c2dcfc30e53c0af08ed6 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Tue, 5 Mar 2019 22:03:05 +0100 Subject: [PATCH 354/373] [scripts] Use BUILD_DIR instead of build_dir --- .gitignore | 2 +- Makefile | 25 ++++++++++++------------- apps/Makefile | 10 +++++----- escher/Makefile | 4 ++-- ion/src/device/Makefile | 8 ++++---- ion/src/device/usb/Makefile | 6 +++--- kandinsky/Makefile | 2 +- python/Makefile | 4 ++-- scripts/defaults.mak | 2 ++ 9 files changed, 32 insertions(+), 31 deletions(-) diff --git a/.gitignore b/.gitignore index 2e261bfd8..a49e8c8c0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ # Quiz output quiz/src/symbols.c -outputs +build diff --git a/Makefile b/Makefile index 0be03da61..4c145c3b0 100644 --- a/Makefile +++ b/Makefile @@ -3,23 +3,22 @@ include scripts/config.mak # Disable default Make rules .SUFFIXES: -build_dir = build -object_for = $(addprefix $(build_dir)/,$(addsuffix .o,$(basename $(1)))) +object_for = $(addprefix $(BUILD_DIR)/,$(addsuffix .o,$(basename $(1)))) -default: $(build_dir)/epsilon.$(EXE) +default: $(BUILD_DIR)/epsilon.$(EXE) # Define a standard rule helper # If passed a last parameter value of with_local_version, we also define an -# extra rule that can build source files within the $(build_dir). This is useful +# extra rule that can build source files within the $(BUILD_DIR). This is useful # for rules that can be applied for intermediate objects (for example, when # going .png -> .cpp -> .o). define rule_for -$(addprefix $$(build_dir)/,$(strip $(2))): $(strip $(3)) | $$$$(@D)/. - @ echo "$(shell printf "%-8s" $(strip $(1)))$$(@:$$(build_dir)/%=%)" +$(addprefix $$(BUILD_DIR)/,$(strip $(2))): $(strip $(3)) | $$$$(@D)/. + @ echo "$(shell printf "%-8s" $(strip $(1)))$$(@:$$(BUILD_DIR)/%=%)" $(Q) $(4) ifeq ($(strip $(5)),with_local_version) -$(addprefix $$(build_dir)/,$(strip $(2))): $(addprefix $$(build_dir)/,$(strip $(3))) - @ echo "$(shell printf "%-8s" $(strip $(1)))$$(@:$$(build_dir)/%=%)" +$(addprefix $$(BUILD_DIR)/,$(strip $(2))): $(addprefix $$(BUILD_DIR)/,$(strip $(3))) + @ echo "$(shell printf "%-8s" $(strip $(1)))$$(@:$$(BUILD_DIR)/%=%)" $(Q) $(4) endif endef @@ -37,8 +36,8 @@ info: # "output/foo/bar.o" because the directory "output/foo" doesn't exist). # We need to mark those directories as precious, otherwise Make will try to get # rid of them upon completion (and fail, since those folders won't be empty). -.PRECIOUS: $(build_dir)/. $(build_dir)%/. -$(build_dir)/. $(build_dir)%/.: +.PRECIOUS: $(BUILD_DIR)/. $(BUILD_DIR)%/. +$(BUILD_DIR)/. $(BUILD_DIR)%/.: $(Q) mkdir -p $(dir $@) # To make objects dependent on their directory, we need a second expansion @@ -75,8 +74,8 @@ objs = $(call object_for,$(src)) -include $(objs:.o=.d) .SECONDARY: $(objs) -$(build_dir)/epsilon.$(EXE): $(objs) -$(build_dir)/test.$(EXE): $(objs) +$(BUILD_DIR)/epsilon.$(EXE): $(objs) +$(BUILD_DIR)/test.$(EXE): $(objs) # Define standard compilation rules @@ -105,7 +104,7 @@ $(eval $(call rule_for, \ .PHONY: clean clean: @echo "CLEAN" - $(Q) rm -rf $(build_dir) + $(Q) rm -rf $(BUILD_DIR) .PHONY: cowsay_% cowsay_%: diff --git a/apps/Makefile b/apps/Makefile index 3b247ce34..d47845f1a 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -47,7 +47,7 @@ $(call object_for,apps/apps_container_storage.cpp apps/main.cpp): CXXFLAGS += $( # I18n file generation # The header is refered to as so make sure it's findable this way -SFLAGS += -I$(build_dir) +SFLAGS += -I$(BUILD_DIR) i18n_files += $(addprefix apps/language_,$(addsuffix .universal.i18n, $(EPSILON_I18N))) i18n_files += $(addprefix apps/,\ @@ -81,9 +81,9 @@ $(eval $(call rule_for, \ # by the object_for function. app_src += apps/i18n.py -$(build_dir)/apps/i18n.h: $(build_dir)/apps/i18n.cpp +$(BUILD_DIR)/apps/i18n.h: $(BUILD_DIR)/apps/i18n.cpp -$(call object_for,$(app_src)): $(build_dir)/apps/i18n.h +$(call object_for,$(app_src)): $(BUILD_DIR)/apps/i18n.h # Handle PNG files @@ -96,8 +96,8 @@ $(eval $(call depends_on_image,apps/title_bar_view.cpp,apps/exam_icon.png)) # As a shortcut, we simply say that every app file depends on every image. In # practice, this forces all the images to be before the app. -#app_image_objs := $(build_dir)/$(app_images:.png=.o) -#.SECONDARY: $(build_dir)/$(app_images:.png=.cpp) +#app_image_objs := $(BUILD_DIR)/$(app_images:.png=.o) +#.SECONDARY: $(BUILD_DIR)/$(app_images:.png=.cpp) #$(app_objs): $(app_image_objs) #app_image_src := $(app_images:.png=.cpp) diff --git a/escher/Makefile b/escher/Makefile index 9f0607e99..91799fdf4 100644 --- a/escher/Makefile +++ b/escher/Makefile @@ -95,9 +95,9 @@ $(eval $(call rule_for, \ $$(HOSTCC) -std=c99 `libpng-config --cflags` $$^ `libpng-config --ldflags` -o $$@ \ )) -INLINER := $(build_dir)/escher/image/inliner +INLINER := $(BUILD_DIR)/escher/image/inliner -.PRECIOUS: $(build_dir)/%.h $(build_dir)/%.cpp +.PRECIOUS: $(BUILD_DIR)/%.h $(BUILD_DIR)/%.cpp $(eval $(call rule_for, \ INLINER, \ %.h %.cpp, \ diff --git a/ion/src/device/Makefile b/ion/src/device/Makefile index ca71adb6c..d40d8aa51 100644 --- a/ion/src/device/Makefile +++ b/ion/src/device/Makefile @@ -41,10 +41,10 @@ src += $(addprefix ion/src/device/, \ ifneq ($(DEBUG),1) ifneq ($(COMPILER),llvm) -$(build_dir)/ion/src/device/led.o: SFLAGS+=-O3 -$(build_dir)/ion/src/device/console.o: SFLAGS+=-O3 -$(build_dir)/ion/src/device/display.o: SFLAGS+=-O3 -$(build_dir)/ion/src/device/swd.o: SFLAGS+=-O3 +$(BUILD_DIR)/ion/src/device/led.o: SFLAGS+=-O3 +$(BUILD_DIR)/ion/src/device/console.o: SFLAGS+=-O3 +$(BUILD_DIR)/ion/src/device/display.o: SFLAGS+=-O3 +$(BUILD_DIR)/ion/src/device/swd.o: SFLAGS+=-O3 endif endif diff --git a/ion/src/device/usb/Makefile b/ion/src/device/usb/Makefile index eb539a3ad..3aaa4c5ac 100644 --- a/ion/src/device/usb/Makefile +++ b/ion/src/device/usb/Makefile @@ -52,8 +52,8 @@ dfu_src += ion/src/device/base64.cpp dfu_src += ion/src/device/flash.cpp dfu_src += ion/src/device/timing.cpp -$(build_dir)/ion/src/device/usb/dfu.elf: LDSCRIPT = ion/src/device/usb/dfu.ld -$(build_dir)/ion/src/device/usb/dfu.elf: $(call object_for,$(usb_src)) $(call object_for,$(dfu_src)) +$(BUILD_DIR)/ion/src/device/usb/dfu.elf: LDSCRIPT = ion/src/device/usb/dfu.ld +$(BUILD_DIR)/ion/src/device/usb/dfu.elf: $(call object_for,$(usb_src)) $(call object_for,$(dfu_src)) # This command embeds a binary file into an object one. # This allows us to embed standalone code (the dfu routines) into the final @@ -62,7 +62,7 @@ $(build_dir)/ion/src/device/usb/dfu.elf: $(call object_for,$(usb_src)) $(call ob # and end), but prefixes them with a mangled file path. To have consistent names # we simply "cd" into the directory. This assumes input and output lives in the # same directory. -$(build_dir)/ion/src/device/usb/dfu.o: $(build_dir)/ion/src/device/usb/dfu.bin +$(BUILD_DIR)/ion/src/device/usb/dfu.o: $(BUILD_DIR)/ion/src/device/usb/dfu.bin @echo "OBJCOPY $@" $(Q) cd $(dir $<) ; $(OBJCOPY) -I binary -O elf32-littlearm -B arm --rename-section .data=.rodata --redefine-sym _binary_dfu_bin_start=_dfu_bootloader_flash_start --redefine-sym _binary_dfu_bin_end=_dfu_bootloader_flash_end $(notdir $<) $(notdir $@) diff --git a/kandinsky/Makefile b/kandinsky/Makefile index 7e7ab6a48..9705de6fe 100644 --- a/kandinsky/Makefile +++ b/kandinsky/Makefile @@ -41,7 +41,7 @@ $(eval $(call rule_for, \ $$(HOSTCC) $$(RASTERIZER_CFLAGS) $$^ $$(RASTERIZER_LDFLAGS) -o $$@ \ )) -RASTERIZER := $(build_dir)/kandinsky/fonts/rasterizer +RASTERIZER := $(BUILD_DIR)/kandinsky/fonts/rasterizer $(eval $(call rule_for, \ RASTER, \ diff --git a/python/Makefile b/python/Makefile index ee277e8d6..1072474dd 100644 --- a/python/Makefile +++ b/python/Makefile @@ -1,6 +1,6 @@ SFLAGS += -Ipython/src SFLAGS += -Ipython/port -SFLAGS += -I$(build_dir)/python/port +SFLAGS += -I$(BUILD_DIR)/python/port # How to maintain this Makefile # - Copy PY_CORE_O_BASENAME from py.mk into py_objs @@ -177,6 +177,6 @@ $(eval $(call rule_for, \ $$(PYTHON) python/src/py/makeqstrdata.py $$< > $$@ \ )) -$(call object_for,$(python_src)): $(build_dir)/python/port/genhdr/qstrdefs.generated.h +$(call object_for,$(python_src)): $(BUILD_DIR)/python/port/genhdr/qstrdefs.generated.h src += $(python_src) diff --git a/scripts/defaults.mak b/scripts/defaults.mak index e7b364888..467083951 100644 --- a/scripts/defaults.mak +++ b/scripts/defaults.mak @@ -33,3 +33,5 @@ ifeq ("$(origin V)", "command line") Q= endif endif + +BUILD_DIR = build/$(PLATFORM) From 414f76b70b639c6080b1c27c5d001b4dcc7bc0a9 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Tue, 5 Mar 2019 22:03:26 +0100 Subject: [PATCH 355/373] [scripts] Fix blackbox, emscripten, and simulator --- ion/src/blackbox/Makefile | 52 ++++++++++++++++++------------------- ion/src/emscripten/Makefile | 38 +++++++++++++-------------- ion/src/simulator/Makefile | 48 +++++++++++++++------------------- 3 files changed, 66 insertions(+), 72 deletions(-) diff --git a/ion/src/blackbox/Makefile b/ion/src/blackbox/Makefile index 931d9f7b2..6835cf65a 100644 --- a/ion/src/blackbox/Makefile +++ b/ion/src/blackbox/Makefile @@ -1,33 +1,33 @@ -objs += $(addprefix ion/src/blackbox/, \ - boot.o \ - ion.o \ - display.o \ - events.o \ +src += $(addprefix ion/src/blackbox/, \ + boot.cpp \ + ion.cpp \ + display.cpp \ + events.cpp \ ) -objs += $(addprefix ion/src/shared/, \ - console_line.o \ - console_stdio.o \ - crc32.o \ - crc32_padded.o \ - events.o \ - power.o \ - random.o \ - timing.o \ - dummy/backlight.o \ - dummy/battery.o \ - dummy/events_modifier.o \ - dummy/fcc_id.o \ - dummy/led.o \ - dummy/keyboard.o \ - dummy/serial_number.o \ - dummy/stack.o \ - dummy/usb.o \ +src += $(addprefix ion/src/shared/, \ + console_line.cpp \ + console_stdio.cpp \ + crc32.cpp \ + crc32_padded.cpp \ + events.cpp \ + power.cpp \ + random.cpp \ + timing.cpp \ + dummy/backlight.cpp \ + dummy/battery.cpp \ + dummy/events_modifier.cpp \ + dummy/fcc_id.cpp \ + dummy/led.cpp \ + dummy/keyboard.cpp \ + dummy/serial_number.cpp \ + dummy/stack.cpp \ + dummy/usb.cpp \ ) -ion/src/shared/log_printf.o: SFLAGS=-Iion/include -ion/src/shared/console_stdio.o: SFLAGS=-Iion/include -ion/src/shared/events_stdin.o: SFLAGS=-Iion/include +$(call object_for,ion/src/shared/log_printf.cpp): SFLAGS=-Iion/include +$(call object_for,ion/src/shared/console_stdio.cpp): SFLAGS=-Iion/include +$(call object_for,ion/src/shared/events_stdin.cpp): SFLAGS=-Iion/include SFLAGS += `libpng-config --cflags` LDFLAGS += `libpng-config --ldflags` diff --git a/ion/src/emscripten/Makefile b/ion/src/emscripten/Makefile index 69b2d5d1f..c697a08cd 100644 --- a/ion/src/emscripten/Makefile +++ b/ion/src/emscripten/Makefile @@ -1,22 +1,22 @@ -objs += $(addprefix ion/src/emscripten/, \ - display.o \ - events_keyboard.o \ - main.o \ +src += $(addprefix ion/src/emscripten/, \ + display.cpp \ + events_keyboard.cpp \ + main.cpp \ ) -objs += $(addprefix ion/src/shared/, \ - crc32.o \ - crc32_padded.o \ - events.o \ - events_modifier.o \ - power.o \ - random.o \ - timing.o \ - dummy/backlight.o \ - dummy/battery.o \ - dummy/fcc_id.o \ - dummy/led.o \ - dummy/serial_number.o \ - dummy/stack.o \ - dummy/usb.o \ +src += $(addprefix ion/src/shared/, \ + crc32.cpp \ + crc32_padded.cpp \ + events.cpp \ + events_modifier.cpp \ + power.cpp \ + random.cpp \ + timing.cpp \ + dummy/backlight.cpp \ + dummy/battery.cpp \ + dummy/fcc_id.cpp \ + dummy/led.cpp \ + dummy/serial_number.cpp \ + dummy/stack.cpp \ + dummy/usb.cpp \ ) diff --git a/ion/src/simulator/Makefile b/ion/src/simulator/Makefile index dc4a9d250..341258950 100644 --- a/ion/src/simulator/Makefile +++ b/ion/src/simulator/Makefile @@ -1,34 +1,28 @@ -objs += $(addprefix ion/src/simulator/, \ - init.o\ +src += $(addprefix ion/src/simulator/, \ + init.cpp \ ) -objs += $(addprefix ion/src/simulator/boot/, main.o) -objs += $(addprefix ion/src/simulator/display/, fltklcd.o) -objs += $(addprefix ion/src/simulator/keyboard/, fltkkbd.o) +src += $(addprefix ion/src/simulator/boot/, main.cpp) +src += $(addprefix ion/src/simulator/display/, fltklcd.cpp) +src += $(addprefix ion/src/simulator/keyboard/, fltkkbd.cpp) -objs += $(addprefix ion/src/shared/, \ - crc32.o \ - crc32_padded.o \ - console_line.o \ - console_stdio.o \ - events_modifier.o \ - power.o \ - random.o \ - timing.o \ - dummy/backlight.o \ - dummy/battery.o \ - dummy/fcc_id.o \ - dummy/led.o \ - dummy/serial_number.o \ - dummy/stack.o \ - dummy/usb.o \ +src += $(addprefix ion/src/shared/, \ + crc32.cpp \ + crc32_padded.cpp \ + console_line.cpp \ + console_stdio.cpp \ + events_modifier.cpp \ + power.cpp \ + random.cpp \ + timing.cpp \ + dummy/backlight.cpp \ + dummy/battery.cpp \ + dummy/fcc_id.cpp \ + dummy/led.cpp \ + dummy/serial_number.cpp \ + dummy/stack.cpp \ + dummy/usb.cpp \ ) SFLAGS += `fltk-config --cflags` LDFLAGS += `fltk-config --ldflags` - -.PHONY: %_memory_map -%_memory_map: - @echo "========== MEMORY MAP =========" - @echo "No memory map on simulator." - @echo "===============================" From 4eb641695b51054e02026d2e6129c7366e471c86 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Tue, 5 Mar 2019 22:30:04 +0100 Subject: [PATCH 356/373] [scripts] Fix the quiz build --- quiz/Makefile | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/quiz/Makefile b/quiz/Makefile index a4974c936..57984d4c1 100644 --- a/quiz/Makefile +++ b/quiz/Makefile @@ -1,18 +1,23 @@ SFLAGS += -Iquiz/include QUIZ_USE_CONSOLE ?= 0 -quiz/src/runner.o: SFLAGS += -DQUIZ_USE_CONSOLE=$(QUIZ_USE_CONSOLE) +$(call object_for,quiz/src/runner.cpp): SFLAGS += -DQUIZ_USE_CONSOLE=$(QUIZ_USE_CONSOLE) -symbols_file = $(addprefix quiz/src/, symbols.c) -products += $(symbols_file) +symbols_file = $(BUILD_DIR)/quiz/src/symbols.c $(symbols_file): $(tests) @echo "AWK $@" $(Q) awk -f quiz/src/symbols.awk $(tests) > $@ -runner_objs += $(addprefix quiz/src/, runner.o assertions.o symbols.o i18n.o) -test_objs += $(subst .c,.o, $(subst .cpp,.o,$(tests))) +runner_src += $(addprefix quiz/src/, \ + assertions.cpp \ + i18n.cpp \ + runner.cpp \ +) -test.$(EXE): $(runner_objs) $(test_objs) +runner_src += $(symbols_file) -products += test.$(EXE) $(runner_objs) $(test_objs) +runner_objs = $(call object_for,$(runner_src)) +$(runner_objs): SFLAGS += -Iquiz/src + +test.$(EXE): $(runner_objs) $(call object_for,$(tests)) From 3cb458076921db9ebc812f1f5e9676224f6481b0 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Wed, 6 Mar 2019 09:49:45 +0100 Subject: [PATCH 357/373] [scripts] Get rid of "products" --- ion/src/device/usb/Makefile | 2 -- ion/src/shared/tools/Makefile | 4 +--- scripts/targets.blackbox.mak | 22 ++++++++++------------ scripts/targets.device.mak | 12 +++--------- scripts/targets.emscripten.mak | 8 +++----- 5 files changed, 17 insertions(+), 31 deletions(-) diff --git a/ion/src/device/usb/Makefile b/ion/src/device/usb/Makefile index 3aaa4c5ac..f15b64bc5 100644 --- a/ion/src/device/usb/Makefile +++ b/ion/src/device/usb/Makefile @@ -69,6 +69,4 @@ $(BUILD_DIR)/ion/src/device/usb/dfu.o: $(BUILD_DIR)/ion/src/device/usb/dfu.bin src += ion/src/device/usb/dfu.cpp src += ion/src/device/usb/dfu_relocated.cpp -#products += $(usb_objs) $(addprefix ion/src/device/usb/dfu, .elf .bin) - endif diff --git a/ion/src/shared/tools/Makefile b/ion/src/shared/tools/Makefile index 27b59a6ee..081339af1 100644 --- a/ion/src/shared/tools/Makefile +++ b/ion/src/shared/tools/Makefile @@ -1,5 +1,3 @@ -ion/src/shared/tools/event_%: ion/src/shared/tools/event_%.cpp ion/src/shared/events.cpp +$(BUILD_DIR)/ion/src/shared/tools/event_%: ion/src/shared/tools/event_%.cpp ion/src/shared/events.cpp @echo "HOSTCXX $@" @$(HOSTCXX) -std=c++11 -Iion/include -DDEBUG=1 $^ -o $@ - -products += $(addprefix ion/src/shared/tools/, event_filter event_generator event_parser event_printer) diff --git a/scripts/targets.blackbox.mak b/scripts/targets.blackbox.mak index 858a22887..9d4241003 100644 --- a/scripts/targets.blackbox.mak +++ b/scripts/targets.blackbox.mak @@ -1,20 +1,18 @@ # Compare -products += $(wildcard ion/src/blackbox/library_*.o) - -ion/src/blackbox/library_%.o: SFLAGS += -D EPSILON_LIB_PREFIX=$(*F) -ion/src/blackbox/library_%.o: ion/src/blackbox/library.cpp +$(BUILD_DIR)/ion/src/blackbox/library_%.o: SFLAGS += -D EPSILON_LIB_PREFIX=$(*F) +$(BUILD_DIR)/ion/src/blackbox/library_%.o: ion/src/blackbox/library.cpp @echo "CXX $@" $(Q) $(CXX) $(SFLAGS) $(CXXFLAGS) -c $< -o $@ -libepsilon_objs = $(filter-out $(addprefix ion/src/blackbox/,boot.o events.o),$(objs)) +libepsilon_src = $(filter-out $(addprefix ion/src/blackbox/,boot.cpp events.cpp),$(src)) -libepsilon_%.o: LDFLAGS += -exported_symbols_list ion/src/blackbox/lib_export_list.txt -libepsilon_%.o: $(libepsilon_objs) $(app_objs) $(app_image_objs) ion/src/blackbox/library_%.o +$(BUILD_DIR)/libepsilon_%.o: LDFLAGS += -exported_symbols_list ion/src/blackbox/lib_export_list.txt +$(BUILD_DIR)/libepsilon_%.o: $(call object_for,$(libepsilon_src)) $(call object_for,$(app_src)) $(BUILD_DIR)/ion/src/blackbox/library_%.o @echo "LD $@" $(Q) $(LD) $^ $(LDFLAGS) -r -s -o $@ -compare: ion/src/blackbox/compare.o +$(BUILD_DIR)/compare: $(call object_for,ion/src/blackbox/compare.cpp) @echo "LD $@" $(Q) $(LD) $^ libepsilon_first.o libepsilon_second.o $(LDFLAGS) -L. -o $@ @@ -41,9 +39,9 @@ integration_tests: $(scenarios:.esc=.run) # Fuzzing .PHONY: epsilon_fuzz ifeq ($(TOOLCHAIN),afl) -epsilon_fuzz: epsilon.$(EXE) +epsilon_fuzz: $(BUILD_DIR)/epsilon.$(EXE) @echo "FUZZ $<" - @afl-fuzz -i tests -o afl ./epsilon.$(EXE) + @afl-fuzz -i tests -o afl $(BUILD_DIR)/epsilon.$(EXE) else epsilon_fuzz: @echo "Fuzzing requires TOOLCHAIN=afl" @@ -51,9 +49,9 @@ endif .PHONY: compare_fuzz ifeq ($(TOOLCHAIN),afl) -compare_fuzz: compare +compare_fuzz: $(BUILD_DIR)/compare @echo "FUZZ $<" - @afl-fuzz -t 3000 -i tests -o afl ./compare + @afl-fuzz -t 3000 -i tests -o afl $(BUILD_DIR)/compare else compare_fuzz: @echo "Fuzzing requires TOOLCHAIN=afl" diff --git a/scripts/targets.device.mak b/scripts/targets.device.mak index 50d682ae9..d94372a59 100644 --- a/scripts/targets.device.mak +++ b/scripts/targets.device.mak @@ -1,7 +1,3 @@ -products += $(patsubst %.$(EXE),%.hex,$(filter %.$(EXE),$(products))) -products += $(patsubst %.$(EXE),%.bin,$(filter %.$(EXE),$(products))) -products += $(patsubst %.$(EXE),%.map,$(filter %.$(EXE),$(products))) - %.hex: %.$(EXE) @echo "OBJCOPY $@" $(Q) $(OBJCOPY) -O ihex $< $@ @@ -51,11 +47,9 @@ openocd: openocd -f scripts/device/openocd.cfg ifeq ($(EPSILON_USB_DFU_XIP)$(EPSILON_DEVICE_BENCH),10) -flasher.$(EXE): LDFLAGS = --gc-sections -T ion/src/device/usb/flasher.ld -flasher.$(EXE): $(objs) $(usb_objs) ion/src/device/usb/flasher.o +$(BUILD_DIR)/flasher.$(EXE): LDFLAGS = --gc-sections -T ion/src/device/usb/flasher.ld +$(BUILD_DIR)/flasher.$(EXE): $(objs) $(usb_objs) ion/src/device/usb/flasher.o else -flasher.$(EXE): +$(BUILD_DIR)/flasher.$(EXE): @echo "Error: flasher.elf requires EPSILON_DEVICE_BENCH=0 EPSILON_USB_DFU_XIP=1" endif - -products += flasher.$(EXE) flasher.bin diff --git a/scripts/targets.emscripten.mak b/scripts/targets.emscripten.mak index 6d651eabb..7c9900fe0 100644 --- a/scripts/targets.emscripten.mak +++ b/scripts/targets.emscripten.mak @@ -1,7 +1,7 @@ -epsilon.packed.js: LDFLAGS += --memory-init-file 0 -epsilon.packed.js: $(objs) $(app_objs) $(app_image_objs) +$(BUILD_DIR)/epsilon.packed.js: LDFLAGS += --memory-init-file 0 +$(BUILD_DIR)epsilon.packed.js: $(objs) $(app_objs) $(app_image_objs) -simulator.zip: epsilon.packed.js +$(BUILD_DIR)/simulator.zip: epsilon.packed.js @rm -rf $(basename $@) @mkdir $(basename $@) @cp epsilon.packed.js $(basename $@)/epsilon.js @@ -10,5 +10,3 @@ simulator.zip: epsilon.packed.js @echo "ZIP $@" @zip -r -9 $@ $(basename $@) > /dev/null @rm -rf $(basename $@) - -products += $(addprefix epsilon,.js .js.mem) epsilon.packed.js simulator.zip From 4aebba88dd20d78958cd68beb811f144c6d1f09b Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Wed, 6 Mar 2019 10:02:59 +0100 Subject: [PATCH 358/373] [scripts] Define shortcut commands for test.elf and epsilon.elf --- Makefile | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 4c145c3b0..117c0dc01 100644 --- a/Makefile +++ b/Makefile @@ -66,6 +66,7 @@ include scripts/scenario/Makefile include quiz/Makefile # Quiz needs to be included at the end objs = $(call object_for,$(src)) +.SECONDARY: $(objs) # Load source-based dependencies # Compilers can generate Makefiles that states the dependencies of a given @@ -73,9 +74,19 @@ objs = $(call object_for,$(src)) # but allows correct yet optimal incremental builds. -include $(objs:.o=.d) -.SECONDARY: $(objs) -$(BUILD_DIR)/epsilon.$(EXE): $(objs) -$(BUILD_DIR)/test.$(EXE): $(objs) +# Define rules for executables +# Those can be built directly with make executable.exe as a shortcut. They also +# depends on $(objs) + +executables = epsilon test + +define rules_for_executable +$$(BUILD_DIR)/$(1).$$(EXE): $$(objs) +.PHONY: $(1).$$(EXE) +$(1).$$(EXE): $$(BUILD_DIR)/$(1).$$(EXE) +endef + +$(foreach executable,$(executables),$(eval $(call rules_for_executable,$(executable)))) # Define standard compilation rules From 160f202860acf75e1d2a2384815bc77f68f8d180 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Wed, 6 Mar 2019 10:12:31 +0100 Subject: [PATCH 359/373] [scripts] Prevent mixing implicit and normal rules --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 117c0dc01..7bf60b37a 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,9 @@ info: # We need to mark those directories as precious, otherwise Make will try to get # rid of them upon completion (and fail, since those folders won't be empty). .PRECIOUS: $(BUILD_DIR)/. $(BUILD_DIR)%/. -$(BUILD_DIR)/. $(BUILD_DIR)%/.: +$(BUILD_DIR)/.: + $(Q) mkdir -p $(dir $@) +$(BUILD_DIR)%/.: $(Q) mkdir -p $(dir $@) # To make objects dependent on their directory, we need a second expansion From 69b1d37e6494bda1e87cc3bd0da01cbbf5da7510 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Wed, 6 Mar 2019 10:47:41 +0100 Subject: [PATCH 360/373] [scripts] Fix the Travis build --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index dd49009c1..e6765d5e1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,4 +23,4 @@ os: linux script: - set -e - make clean && make epsilon.$EXT test.$EXT -- if [ "$PLATFORM" = "blackbox" ]; then ./test.$EXT; PLATFORM=blackbox make integration_tests; fi +- if [ "$PLATFORM" = "blackbox" ]; then build/blackbox/test.$EXT; PLATFORM=blackbox make integration_tests; fi From 219fdcbdc6f66b5dbbdd3332c035bcc0b9e5553a Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Wed, 6 Mar 2019 11:39:19 +0100 Subject: [PATCH 361/373] [scripts] Correctly build the test runner --- Makefile | 2 ++ apps/Makefile | 37 ++++++++++--------------------------- quiz/Makefile | 2 +- 3 files changed, 13 insertions(+), 28 deletions(-) diff --git a/Makefile b/Makefile index 7bf60b37a..896c66470 100644 --- a/Makefile +++ b/Makefile @@ -88,6 +88,8 @@ $$(BUILD_DIR)/$(1).$$(EXE): $$(objs) $(1).$$(EXE): $$(BUILD_DIR)/$(1).$$(EXE) endef +$(BUILD_DIR)/epsilon.$(EXE): $(call object_for,$(app_src)) + $(foreach executable,$(executables),$(eval $(call rules_for_executable,$(executable)))) # Define standard compilation rules diff --git a/apps/Makefile b/apps/Makefile index d47845f1a..451c0e075 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -21,9 +21,7 @@ app_src += $(addprefix apps/,\ empty_battery_window.cpp \ exam_pop_up_controller.cpp \ global_preferences.cpp \ - i18n.cpp \ lock_view.cpp \ - main.cpp \ math_toolbox.cpp \ shift_alpha_lock_view.cpp \ suspend_timer.cpp \ @@ -76,11 +74,6 @@ $(eval $(call rule_for, \ $$(PYTHON) apps/i18n.py --header $$(subst .cpp,.h,$$@) --implementation $$@ --locales $$(EPSILON_I18N) --files $$^ \ )) -# Make sure apps/i18n.o is built -# The extension added to app_src doesn't really matter since it'll be processed -# by the object_for function. -app_src += apps/i18n.py - $(BUILD_DIR)/apps/i18n.h: $(BUILD_DIR)/apps/i18n.cpp $(call object_for,$(app_src)): $(BUILD_DIR)/apps/i18n.h @@ -89,27 +82,17 @@ $(call object_for,$(app_src)): $(BUILD_DIR)/apps/i18n.h $(eval $(call depends_on_image,apps/title_bar_view.cpp,apps/exam_icon.png)) +# Handle epsilon-only sources +# Other executables may want to do their own i18n and main. That's the case for +# the test runner. Let's add those files to a specific epsilon-only src. When +# building apps/i18n.o, the extension doesn't really matter since it'll be +# processed by the object_for function. -# Tracking which source file uses which image is painful. But we need to ensure -# that a .png file has been inlined before building any source file that uses -# said image (because it will expect the ".h" file to be there). -# As a shortcut, we simply say that every app file depends on every image. In -# practice, this forces all the images to be before the app. +epsilon_src += $(addprefix apps/, \ + main.cpp \ + i18n.py \ +) -#app_image_objs := $(BUILD_DIR)/$(app_images:.png=.o) -#.SECONDARY: $(BUILD_DIR)/$(app_images:.png=.cpp) -#$(app_objs): $(app_image_objs) -#app_image_src := $(app_images:.png=.cpp) - -#epsilon.$(EXE): $(app_objs) $(app_image_objs) -#app_objs = $(call object_for,$(app_src)) - -#epsilon.$(EXE): $(app_objs) +$(BUILD_DIR)/epsilon.$(EXE): $(call object_for,$(epsilon_src)) src += $(app_src) -#$(app_image_src) - -TO_REMOVE := apps/main.o apps/i18n.o -TMP := $(app_objs) $(app_image_objs) -VAR := $(filter-out $(TO_REMOVE), $(TMP)) -test.$(EXE): $(VAR) diff --git a/quiz/Makefile b/quiz/Makefile index 57984d4c1..45129c49c 100644 --- a/quiz/Makefile +++ b/quiz/Makefile @@ -20,4 +20,4 @@ runner_src += $(symbols_file) runner_objs = $(call object_for,$(runner_src)) $(runner_objs): SFLAGS += -Iquiz/src -test.$(EXE): $(runner_objs) $(call object_for,$(tests)) +$(BUILD_DIR)/test.$(EXE): $(runner_objs) $(call object_for,$(tests)) From 6e3ce5d29502f6c2459627d14e2c442241bf5bb4 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Wed, 6 Mar 2019 13:57:01 +0100 Subject: [PATCH 362/373] [scripts] Make sure to build i18n.h --- Makefile | 2 -- apps/Makefile | 6 ++---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 896c66470..7bf60b37a 100644 --- a/Makefile +++ b/Makefile @@ -88,8 +88,6 @@ $$(BUILD_DIR)/$(1).$$(EXE): $$(objs) $(1).$$(EXE): $$(BUILD_DIR)/$(1).$$(EXE) endef -$(BUILD_DIR)/epsilon.$(EXE): $(call object_for,$(app_src)) - $(foreach executable,$(executables),$(eval $(call rules_for_executable,$(executable)))) # Define standard compilation rules diff --git a/apps/Makefile b/apps/Makefile index 451c0e075..d3cb9321f 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -40,8 +40,6 @@ epsilon_app_names = '$(foreach i,${EPSILON_APPS},"$(i)", )' $(call object_for,apps/apps_container_storage.cpp apps/main.cpp): CXXFLAGS += $(snapshot_includes) -DAPPS_CONTAINER_APPS_DECLARATION="$(apps_declaration)" -DAPPS_CONTAINER_SNAPSHOT_DECLARATIONS="$(snapshots_declaration)" -DAPPS_CONTAINER_SNAPSHOT_CONSTRUCTORS="$(snapshots_construction)" -DAPPS_CONTAINER_SNAPSHOT_LIST="$(snapshots_list)" -DAPPS_CONTAINER_SNAPSHOT_COUNT=$(snapshots_count) -DEPSILON_APPS_NAMES=$(epsilon_app_names) - - # I18n file generation # The header is refered to as so make sure it's findable this way @@ -76,8 +74,6 @@ $(eval $(call rule_for, \ $(BUILD_DIR)/apps/i18n.h: $(BUILD_DIR)/apps/i18n.cpp -$(call object_for,$(app_src)): $(BUILD_DIR)/apps/i18n.h - # Handle PNG files $(eval $(call depends_on_image,apps/title_bar_view.cpp,apps/exam_icon.png)) @@ -93,6 +89,8 @@ epsilon_src += $(addprefix apps/, \ i18n.py \ ) +$(call object_for,$(app_src) $(epsilon_src)): $(BUILD_DIR)/apps/i18n.h + $(BUILD_DIR)/epsilon.$(EXE): $(call object_for,$(epsilon_src)) src += $(app_src) From c286f4fd62752afc4eece6332280abf299cd11e8 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Wed, 6 Mar 2019 13:57:24 +0100 Subject: [PATCH 363/373] [scripts] Work around command-line length limit on windows --- scripts/toolchain.mingw.mak | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/scripts/toolchain.mingw.mak b/scripts/toolchain.mingw.mak index 50004be72..fb2d1b3c8 100644 --- a/scripts/toolchain.mingw.mak +++ b/scripts/toolchain.mingw.mak @@ -5,3 +5,14 @@ EXE = exe SFLAGS += -D_USE_MATH_DEFINES LDFLAGS += -static -mwindows + +# Work around command-line length limit +# On Msys2 the max command line is 32 000 characters. Our standard LD command +# can be longer than that because we have quite a lot of object files. To work +# around this issue, we write the object list in a "target.objs" file, and tell +# the linker to read its arguments from this file. +$(BUILD_DIR)/%.$(EXE): + $(Q) echo $^ > $@.objs + @echo "LD $(@:$(BUILD_DIR)/%=%)" + $(Q) $(LD) @$@.objs $(LDFLAGS) -o $@ + $(Q) rm $@.objs From d7975cfa7f1cb79df92a22b199a8ac81c97d7ee3 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Wed, 6 Mar 2019 14:03:46 +0100 Subject: [PATCH 364/373] [scripts] Make sure apps have all their prerequisites --- apps/Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/Makefile b/apps/Makefile index d3cb9321f..34eeb7463 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -89,7 +89,10 @@ epsilon_src += $(addprefix apps/, \ i18n.py \ ) -$(call object_for,$(app_src) $(epsilon_src)): $(BUILD_DIR)/apps/i18n.h +all_app_src = $(app_src) $(epsilon_src) + +$(call object_for,$(all_app_src)): $(BUILD_DIR)/apps/i18n.h +$(call object_for,$(all_app_src)): $(BUILD_DIR)/python/port/genhdr/qstrdefs.generated.h $(BUILD_DIR)/epsilon.$(EXE): $(call object_for,$(epsilon_src)) From 9eb672bb5f1673f5741ce43c1834c5147f7f5c6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 11 Mar 2019 12:14:22 +0100 Subject: [PATCH 365/373] [apps/shared] Fix ExpressionFieldDelegateApp::layoutFieldDidReceiveEvent Layouts have two potential serializations. For example, HorizontalLayout(CharLayout(2), CharLayout(a)) can be serialized as: "2a" and "2*a". In layoutFieldDidReceiveEvent, we want to check that the longest serialisation is bounded by maxBufferSize. (We could have used Layout::serializeParsedExpression but we don't to avoid parsing the expression twice) --- apps/shared/expression_field_delegate_app.cpp | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/apps/shared/expression_field_delegate_app.cpp b/apps/shared/expression_field_delegate_app.cpp index 84588f838..95dd683bf 100644 --- a/apps/shared/expression_field_delegate_app.cpp +++ b/apps/shared/expression_field_delegate_app.cpp @@ -23,8 +23,14 @@ bool ExpressionFieldDelegateApp::layoutFieldDidReceiveEvent(LayoutField * layout layoutField->app()->displayWarning(I18n::Message::SyntaxError); return true; } - char buffer[TextField::maxBufferSize()]; - int bufferSize = TextField::maxBufferSize(); + /* An acceptable layout has to be parsable and serialized in a fixed-size + * buffer. We check all that here. */ + /* Step 1: Simple layout serialisation. Resulting texts can be parsed but + * not displayed, like: + * - 2a + * - log_{2}(x) */ + constexpr int bufferSize = TextField::maxBufferSize(); + char buffer[bufferSize]; int length = layoutField->layout().serializeForParsing(buffer, bufferSize); if (length >= bufferSize-1) { /* If the buffer is totally full, it is VERY likely that writeTextInBuffer @@ -32,7 +38,24 @@ bool ExpressionFieldDelegateApp::layoutFieldDidReceiveEvent(LayoutField * layout displayWarning(I18n::Message::SyntaxError); return true; } - if (!isAcceptableText(buffer)) { + // Step 2: Parsing + Poincare::Expression e = Poincare::Expression::Parse(buffer); + if (e.isUninitialized()) { + // Unparsable expression + displayWarning(I18n::Message::SyntaxError); + return true; + } + /* Step 3: Expression serialization. Tesulting texts are parseable and + * displayable, like: + * - 2*a + * - log(x,2) */ + length = e.serialize(buffer, bufferSize, Poincare::Preferences::sharedPreferences()->displayMode()); + if (length >= bufferSize-1) { + // Same comment as before + displayWarning(I18n::Message::SyntaxError); + return true; + } + if (!isAcceptableExpression(e)) { displayWarning(I18n::Message::SyntaxError); return true; } From dcd83923ef6ec71e2e7bdc583c88dcd75e61a3e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 11 Mar 2019 12:15:29 +0100 Subject: [PATCH 366/373] [scripts] Fix the emscripten simulator.zip build --- scripts/targets.emscripten.mak | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/targets.emscripten.mak b/scripts/targets.emscripten.mak index 7c9900fe0..436890c53 100644 --- a/scripts/targets.emscripten.mak +++ b/scripts/targets.emscripten.mak @@ -1,12 +1,12 @@ $(BUILD_DIR)/epsilon.packed.js: LDFLAGS += --memory-init-file 0 -$(BUILD_DIR)epsilon.packed.js: $(objs) $(app_objs) $(app_image_objs) +$(BUILD_DIR)/epsilon.packed.js: $(objs) $(call object_for,$(epsilon_src)) -$(BUILD_DIR)/simulator.zip: epsilon.packed.js +$(BUILD_DIR)/simulator.zip: $(BUILD_DIR)/epsilon.packed.js @rm -rf $(basename $@) - @mkdir $(basename $@) - @cp epsilon.packed.js $(basename $@)/epsilon.js + @mkdir -p $(basename $@) + @cp $^ $(basename $@)/epsilon.js @cp ion/src/emscripten/background.jpg $(basename $@)/ @cp ion/src/emscripten/simulator.html $(basename $@)/ @echo "ZIP $@" - @zip -r -9 $@ $(basename $@) > /dev/null + @zip -r -9 -j $@ $(basename $@) > /dev/null @rm -rf $(basename $@) From 43bd5e70443b217019b9ee3e476d27e4887f074c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 11 Mar 2019 16:15:38 +0100 Subject: [PATCH 367/373] [scripts] Fix PLATFORM=device build --- scripts/platform.device.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/platform.device.mak b/scripts/platform.device.mak index 4c6be1d4c..ed95acbfc 100644 --- a/scripts/platform.device.mak +++ b/scripts/platform.device.mak @@ -6,4 +6,4 @@ EPSILON_BOOT_PROMPT = update EPSILON_DEVICE_BENCH ?= 1 SFLAGS += -DEPSILON_DEVICE_BENCH=$(EPSILON_DEVICE_BENCH) -python/port/port.o: CXXFLAGS += -DMP_PORT_USE_STACK_SYMBOLS=1 +$(BUILD_DIR)/python/port/port.o: CXXFLAGS += -DMP_PORT_USE_STACK_SYMBOLS=1 From 147c1b4592b9f1d24680747469ebeba08df372de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 11 Mar 2019 13:51:01 +0100 Subject: [PATCH 368/373] [python/turtle] Make the turtle faster on emscripten It was slower than on the calculator --- python/port/mod/turtle/turtle.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/python/port/mod/turtle/turtle.cpp b/python/port/mod/turtle/turtle.cpp index 48d66c173..cb7cbb51e 100644 --- a/python/port/mod/turtle/turtle.cpp +++ b/python/port/mod/turtle/turtle.cpp @@ -323,11 +323,24 @@ bool Turtle::draw(bool force) { m_drawn = true; } - if (m_mileage > 1000) { + /* We sleep every time the turtle walks a mileageLimit amount, to allow user + * interruptions. The length of each sleep is determined by the speed of the + * turtle. + * With emscripten, sleep gives control to the web browser, which decides when + * to return from sleep: this makes the turtle significantly slower on the web + * emulator than on the calculator. We thus decided to sleep less often on the + * emscripten platform. */ +#if __EMSCRIPTEN__ + constexpr KDCoordinate mileageLimit = 10000; +#else + constexpr KDCoordinate mileageLimit = 1000; +#endif + + if (m_mileage > mileageLimit) { if (micropython_port_interruptible_msleep(1 + (m_speed == 0 ? 0 : 3 * (k_maxSpeed - m_speed)))) { return true; } - m_mileage -= 1000; + m_mileage -= mileageLimit; } return false; } From ddb22ba1a28ef11ca34cf7930b36343ecc4b1845 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 11 Mar 2019 14:50:42 +0100 Subject: [PATCH 369/373] [python/turtle] Fix drawing of diagonal lines --- python/port/mod/turtle/turtle.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/python/port/mod/turtle/turtle.cpp b/python/port/mod/turtle/turtle.cpp index cb7cbb51e..20e9c15cd 100644 --- a/python/port/mod/turtle/turtle.cpp +++ b/python/port/mod/turtle/turtle.cpp @@ -94,8 +94,20 @@ bool Turtle::goTo(mp_float_t x, mp_float_t y) { mp_float_t oldy = m_y; mp_float_t xLength = absF(std::floor(x) - std::floor(oldx)); mp_float_t yLength = absF(std::floor(y) - std::floor(oldy)); - bool principalDirectionIsX = xLength >= yLength; - mp_float_t length = principalDirectionIsX ? xLength : yLength; + + enum PrincipalDirection { + None = 0, + X = 1, + Y = 2 + }; + + PrincipalDirection principalDirection = xLength > yLength ? + PrincipalDirection::X : + (xLength == yLength ? + PrincipalDirection::None : + PrincipalDirection::Y); + + mp_float_t length = principalDirection == PrincipalDirection::X ? xLength : yLength; if (length > 1) { // Tweening function @@ -106,8 +118,8 @@ bool Turtle::goTo(mp_float_t x, mp_float_t y) { * the computation of the position on the principal coordinate is done * using a barycenter, roundings might skip some pixels, which results in * a dotted line. */ - mp_float_t currentX = principalDirectionIsX ? oldx + (x > oldx ? i : -i) : x * progress + oldx * (1 - progress); - mp_float_t currentY = principalDirectionIsX ? y * progress + oldy * (1 - progress) : oldy + (y > oldy ? i : -i); + mp_float_t currentX = principalDirection == PrincipalDirection::Y ? x * progress + oldx * (1 - progress) : oldx + (x > oldx ? i : -i); + mp_float_t currentY = principalDirection == PrincipalDirection::X ? y * progress + oldy * (1 - progress) : oldy + (y > oldy ? i : -i); if (dot(currentX, currentY) || draw(false)) { // Keyboard interruption. Return now to let MicroPython process it. return true; From 2a34f955ca83973388bca5859c11e490efaf4d21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 11 Mar 2019 15:25:24 +0100 Subject: [PATCH 370/373] [python/turtle] Fix some turtle jumps There was a drawing glitch for instance when doing goto(100,100). It was due to the tutle mileage being overflowed. --- python/port/mod/turtle/turtle.cpp | 25 +++++++++---------------- python/port/mod/turtle/turtle.h | 16 +++++++++++++++- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/python/port/mod/turtle/turtle.cpp b/python/port/mod/turtle/turtle.cpp index 20e9c15cd..0b7dcad89 100644 --- a/python/port/mod/turtle/turtle.cpp +++ b/python/port/mod/turtle/turtle.cpp @@ -335,24 +335,11 @@ bool Turtle::draw(bool force) { m_drawn = true; } - /* We sleep every time the turtle walks a mileageLimit amount, to allow user - * interruptions. The length of each sleep is determined by the speed of the - * turtle. - * With emscripten, sleep gives control to the web browser, which decides when - * to return from sleep: this makes the turtle significantly slower on the web - * emulator than on the calculator. We thus decided to sleep less often on the - * emscripten platform. */ -#if __EMSCRIPTEN__ - constexpr KDCoordinate mileageLimit = 10000; -#else - constexpr KDCoordinate mileageLimit = 1000; -#endif - - if (m_mileage > mileageLimit) { + if (m_mileage > k_mileageLimit) { if (micropython_port_interruptible_msleep(1 + (m_speed == 0 ? 0 : 3 * (k_maxSpeed - m_speed)))) { return true; } - m_mileage -= mileageLimit; + m_mileage -= k_mileageLimit; } return false; } @@ -360,6 +347,7 @@ bool Turtle::draw(bool force) { bool Turtle::dot(mp_float_t x, mp_float_t y) { MicroPython::ExecutionEnvironment::currentExecutionEnvironment()->displaySandbox(); + // Draw the dot if the pen is down if (m_penDown && hasDotBuffers()) { KDContext * ctx = KDIonContext::sharedContext(); KDRect rect( @@ -369,7 +357,12 @@ bool Turtle::dot(mp_float_t x, mp_float_t y) { ctx->blendRectWithMask(rect, m_color, m_dotMask, m_dotWorkingPixelBuffer); } - m_mileage += sqrt((x - m_x) * (x - m_x) + (y - m_y) * (y - m_y)) * 1000; + /* Increase the turtle's mileage. We need to make sure the mileage is not + * overflowed, otherwise we might skip some msleeps in draw. */ + uint16_t additionalMileage = sqrt((x - m_x) * (x - m_x) + (y - m_y) * (y - m_y)) * 1000; + m_mileage = ((m_mileage > k_mileageLimit) + && ((m_mileage + additionalMileage) < k_mileageLimit)) ? + k_mileageLimit + 1 : m_mileage + additionalMileage; m_x = x; m_y = y; diff --git a/python/port/mod/turtle/turtle.h b/python/port/mod/turtle/turtle.h index 2b9d83b9c..87aa58e8f 100644 --- a/python/port/mod/turtle/turtle.h +++ b/python/port/mod/turtle/turtle.h @@ -154,7 +154,21 @@ private: uint8_t m_speed; // Speed is between 0 and 10 KDCoordinate m_penSize; - KDCoordinate m_mileage; + + /* We sleep every time the turtle walks a mileageLimit amount, to allow user + * interruptions. The length of each sleep is determined by the speed of the + * turtle. + * With emscripten, sleep gives control to the web browser, which decides when + * to return from sleep: this makes the turtle significantly slower on the web + * emulator than on the calculator. We thus decided to sleep less often on the + * emscripten platform. */ +#if __EMSCRIPTEN__ + static constexpr uint16_t k_mileageLimit = 10000; +#else + static constexpr uint16_t k_mileageLimit = 1000; +#endif + + uint16_t m_mileage; bool m_drawn; }; From e40e626eec705f8eaa2608b85547a71213f440fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 12 Mar 2019 15:45:58 +0100 Subject: [PATCH 371/373] [graph] Values tab: select the right cell of the values table when displaying/undisplaying the derivative column --- .../values/storage_function_parameter_controller.cpp | 8 ++++---- apps/graph/values/storage_function_parameter_controller.h | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/graph/values/storage_function_parameter_controller.cpp b/apps/graph/values/storage_function_parameter_controller.cpp index 667ab51a0..737cafada 100644 --- a/apps/graph/values/storage_function_parameter_controller.cpp +++ b/apps/graph/values/storage_function_parameter_controller.cpp @@ -19,7 +19,9 @@ bool StorageFunctionParameterController::handleEvent(Ion::Events::Event event) { switch (selectedRow()) { case 0: { - function()->setDisplayDerivative(!function()->displayDerivative()); + bool isDisplayingDerivative = function()->displayDerivative(); + function()->setDisplayDerivative(!isDisplayingDerivative); + m_valuesController->selectCellAtLocation(isDisplayingDerivative ? m_selectedFunctionColumn : m_selectedFunctionColumn + 1, m_valuesController->selectedRow()); m_selectableTableView.reloadData(); return true; } @@ -57,9 +59,7 @@ int StorageFunctionParameterController::reusableCellCount() { void StorageFunctionParameterController::viewWillAppear() { StorageValuesFunctionParameterController::viewWillAppear(); - if (function()->displayDerivative()) { - m_valuesController->selectCellAtLocation(m_valuesController->selectedColumn()+1, m_valuesController->selectedRow()); - } + m_selectedFunctionColumn = m_valuesController->selectedColumn(); } void StorageFunctionParameterController::willDisplayCellForIndex(HighlightCell * cell, int index) { diff --git a/apps/graph/values/storage_function_parameter_controller.h b/apps/graph/values/storage_function_parameter_controller.h index 205320927..c629c73b6 100644 --- a/apps/graph/values/storage_function_parameter_controller.h +++ b/apps/graph/values/storage_function_parameter_controller.h @@ -27,6 +27,8 @@ private: #endif MessageTableCellWithSwitch m_displayDerivativeColumn; StorageValuesController * m_valuesController; + // Index of the column corresponding to the function in the values controller + int m_selectedFunctionColumn; }; } From 2658015cdaa56c0eda848a354d564f6eb18076e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 12 Mar 2019 18:15:37 +0100 Subject: [PATCH 372/373] [poincare] Fix mis-implementation of (a^b)^c -> a^(b*c) which is applied if: - a > 0 - in Real: when b and c are integers - in other modes: when c is integer --- poincare/src/power.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 4c90df701..91302c26b 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -580,12 +580,13 @@ Expression Power::shallowReduce(Context & context, Preferences::ComplexFormat co if (childAtIndex(0).type() == ExpressionNode::Type::Power) { Power p = childAtIndex(0).convert(); // Check if a > 0 or c is Integer - if (p.childAtIndex(0).sign(&context) == ExpressionNode::Sign::Positive - || (childAtIndex(1).type() == ExpressionNode::Type::Rational - && childAtIndex(1).convert().integerDenominator().isOne())) - { + bool aPositive = p.childAtIndex(0).sign(&context) == ExpressionNode::Sign::Positive; + bool cInteger = (childAtIndex(1).type() == ExpressionNode::Type::Rational + && childAtIndex(1).convert().integerDenominator().isOne()); + if (aPositive || cInteger) { // Check that the complex format is not Real or that b is an integer - if (complexFormat != Preferences::ComplexFormat::Real || (p.childAtIndex(1).type() == ExpressionNode::Type::Rational && p.childAtIndex(1).convert().integerDenominator().isOne())) { + bool bInteger = (p.childAtIndex(1).type() == ExpressionNode::Type::Rational && p.childAtIndex(1).convert().integerDenominator().isOne()); + if (aPositive || complexFormat != Preferences::ComplexFormat::Real || bInteger) { return simplifyPowerPower(context, complexFormat, angleUnit, target); } } From caef2e8c6fa246205cc829d623f15a8dd5b1505b Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Wed, 13 Mar 2019 10:18:17 +0100 Subject: [PATCH 373/373] Add GitHub issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 25 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 22 ++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..c9f1c1e8d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,25 @@ +--- +name: Bug report +about: Epsilon is not working like it should? Let us know! +labels: 'bug' + +--- +#### Describe the bug +A clear and concise description of what the bug is. Please describe a **single** bug per issue. Feel free to create multiple issues though! + +#### Screenshots +Please provide at least one screenshot of the issue happening. This is by far the best way to quickly show any issue! To attach a screenshot, just go to our [online simulator](https://www.numworks.com/simulator), navigate to reproduce your issue, and click the "screenshot" button. Then drag'n'drop the file here! + +#### To Reproduce +Steps to reproduce the behavior: +1. Go to the '...' app +2. Type '....' +3. Scroll down to '....' +4. See error + +#### Expected behavior +A clear and concise description of what you expected to happen. + +#### Environment + - Epsilon version (Settings > About > Software version). + - The platform(s) on which the problem happens: online simulator, actual device, etc... diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..6bc39c490 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,22 @@ +--- +name: Feature request +about: Suggest an idea for an improvement of Epsilon +labels: 'enhancement' + +--- +#### Problem you'd like to fix +Is your feature request related to a problem? Please provide a clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +Please describe a **single** improvement per issue. Feel free to open multiple issues though! + +#### Screenshots +If possible, please attach a screenshot. You can go on our [online simulator](https://www.numworks.com/simulator), use the screenshot button, and drag'n'drop the file here. + +#### Describe the solution you'd like +A clear and concise description of what you want to happen. + +#### Describe alternatives you've considered +A clear and concise description of any alternative solutions or features you've considered. + +#### Additional context +Add any other context or screenshots about the feature request here.