From f73ddcd08f8bc751232296f488f3b1b494fabbeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 31 Jul 2017 14:35:57 +0200 Subject: [PATCH] [poincare] Evaluation return numerical matrix Change-Id: I58dbc93ad22a086580a77318b2524db9c70e47d2 --- apps/calculation/calculation.cpp | 2 +- apps/calculation/calculation.h | 4 +- apps/calculation/local_context.cpp | 6 +- apps/calculation/local_context.h | 6 +- apps/sequence/local_context.cpp | 5 +- apps/sequence/local_context.h | 2 +- apps/variable_box_controller.cpp | 16 +- apps/variable_box_controller.h | 2 +- apps/variable_box_leaf_cell.cpp | 2 +- apps/variable_box_leaf_cell.h | 2 +- poincare/Makefile | 4 + poincare/include/poincare.h | 4 + poincare/include/poincare/absolute_value.h | 2 +- poincare/include/poincare/addition.h | 8 +- poincare/include/poincare/arc_cosine.h | 2 +- poincare/include/poincare/arc_sine.h | 2 +- poincare/include/poincare/arc_tangent.h | 2 +- poincare/include/poincare/binary_operation.h | 15 +- .../include/poincare/binomial_coefficient.h | 2 +- poincare/include/poincare/ceiling.h | 2 +- poincare/include/poincare/complex.h | 34 +- poincare/include/poincare/complex_argument.h | 2 +- poincare/include/poincare/complex_matrix.h | 33 ++ .../include/poincare/confidence_interval.h | 3 +- poincare/include/poincare/conjugate.h | 3 +- poincare/include/poincare/context.h | 6 +- poincare/include/poincare/cosine.h | 7 +- poincare/include/poincare/derivative.h | 2 +- poincare/include/poincare/determinant.h | 2 +- poincare/include/poincare/division_quotient.h | 2 +- .../include/poincare/division_remainder.h | 2 +- poincare/include/poincare/evaluation.h | 28 ++ poincare/include/poincare/expression.h | 11 +- poincare/include/poincare/expression_matrix.h | 33 ++ poincare/include/poincare/factorial.h | 2 +- poincare/include/poincare/floor.h | 2 +- poincare/include/poincare/frac_part.h | 2 +- poincare/include/poincare/fraction.h | 10 +- poincare/include/poincare/function.h | 7 +- poincare/include/poincare/global_context.h | 11 +- .../include/poincare/great_common_divisor.h | 2 +- .../include/poincare/hyperbolic_arc_cosine.h | 3 +- .../include/poincare/hyperbolic_arc_sine.h | 2 +- .../include/poincare/hyperbolic_arc_tangent.h | 2 +- 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 | 2 +- poincare/include/poincare/integer.h | 3 +- poincare/include/poincare/integral.h | 2 +- .../include/poincare/least_common_multiple.h | 2 +- poincare/include/poincare/list_data.h | 1 + poincare/include/poincare/logarithm.h | 3 +- poincare/include/poincare/matrix.h | 31 +- poincare/include/poincare/matrix_data.h | 3 +- poincare/include/poincare/matrix_dimension.h | 3 +- poincare/include/poincare/matrix_inverse.h | 3 +- poincare/include/poincare/matrix_trace.h | 2 +- poincare/include/poincare/matrix_transpose.h | 3 +- poincare/include/poincare/multiplication.h | 12 +- .../include/poincare/naperian_logarithm.h | 2 +- poincare/include/poincare/nth_root.h | 4 +- poincare/include/poincare/opposite.h | 6 +- poincare/include/poincare/parenthesis.h | 3 +- .../include/poincare/permute_coefficient.h | 2 +- poincare/include/poincare/power.h | 12 +- .../include/poincare/prediction_interval.h | 3 +- poincare/include/poincare/product.h | 3 +- poincare/include/poincare/reel_part.h | 2 +- poincare/include/poincare/round.h | 2 +- poincare/include/poincare/sequence.h | 6 +- poincare/include/poincare/sine.h | 7 +- poincare/include/poincare/square_root.h | 3 +- poincare/include/poincare/store.h | 3 +- poincare/include/poincare/subtraction.h | 8 +- poincare/include/poincare/sum.h | 3 +- poincare/include/poincare/symbol.h | 3 +- poincare/include/poincare/tangent.h | 4 +- .../include/poincare/trigonometric_function.h | 7 +- poincare/include/poincare/variable_context.h | 4 +- poincare/src/absolute_value.cpp | 14 +- poincare/src/addition.cpp | 26 +- poincare/src/arc_cosine.cpp | 12 +- poincare/src/arc_sine.cpp | 12 +- poincare/src/arc_tangent.cpp | 12 +- poincare/src/binary_operation.cpp | 125 +++---- poincare/src/binomial_coefficient.cpp | 16 +- poincare/src/ceiling.cpp | 9 +- poincare/src/complex.cpp | 66 ++-- poincare/src/complex_argument.cpp | 14 +- poincare/src/complex_matrix.cpp | 78 +++++ poincare/src/confidence_interval.cpp | 28 +- poincare/src/conjugate.cpp | 18 +- poincare/src/cosine.cpp | 18 +- poincare/src/derivative.cpp | 39 ++- poincare/src/determinant.cpp | 17 +- poincare/src/division_quotient.cpp | 15 +- poincare/src/division_remainder.cpp | 15 +- poincare/src/evaluation.cpp | 194 +++++++++++ poincare/src/expression.cpp | 33 +- poincare/src/expression_matrix.cpp | 87 +++++ poincare/src/expression_parser.y | 2 +- poincare/src/factorial.cpp | 14 +- poincare/src/floor.cpp | 9 +- poincare/src/frac_part.cpp | 9 +- poincare/src/fraction.cpp | 41 +-- poincare/src/function.cpp | 133 ++++---- poincare/src/global_context.cpp | 20 +- poincare/src/great_common_divisor.cpp | 16 +- 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 | 49 +-- poincare/src/hyperbolic_sine.cpp | 49 +-- poincare/src/hyperbolic_tangent.cpp | 37 +- poincare/src/imaginary_part.cpp | 14 +- poincare/src/integer.cpp | 31 +- poincare/src/integral.cpp | 23 +- poincare/src/layout/grid_layout.cpp | 4 +- poincare/src/layout/horizontal_layout.cpp | 4 +- poincare/src/layout/string_layout.cpp | 4 +- poincare/src/least_common_multiple.cpp | 15 +- poincare/src/list_data.cpp | 12 +- poincare/src/logarithm.cpp | 25 +- poincare/src/matrix.cpp | 274 +-------------- poincare/src/matrix_data.cpp | 11 +- poincare/src/matrix_dimension.cpp | 23 +- poincare/src/matrix_inverse.cpp | 28 +- poincare/src/matrix_trace.cpp | 17 +- poincare/src/matrix_transpose.cpp | 20 +- poincare/src/multiplication.cpp | 44 +-- poincare/src/naperian_logarithm.cpp | 8 +- poincare/src/nth_root.cpp | 48 +-- poincare/src/opposite.cpp | 61 ++-- poincare/src/parenthesis.cpp | 8 +- poincare/src/permute_coefficient.cpp | 18 +- poincare/src/power.cpp | 71 ++-- poincare/src/prediction_interval.cpp | 27 +- poincare/src/product.cpp | 17 +- poincare/src/reel_part.cpp | 14 +- poincare/src/round.cpp | 15 +- poincare/src/sequence.cpp | 47 +-- poincare/src/sine.cpp | 25 +- poincare/src/square_root.cpp | 25 +- poincare/src/store.cpp | 11 +- poincare/src/subtraction.cpp | 18 +- poincare/src/sum.cpp | 17 +- poincare/src/symbol.cpp | 15 +- poincare/src/tangent.cpp | 32 +- poincare/src/trigonometric_function.cpp | 40 +-- poincare/src/variable_context.cpp | 10 +- poincare/test/addition.cpp | 98 +----- poincare/test/complex.cpp | 20 +- poincare/test/fraction.cpp | 67 ++-- poincare/test/function.cpp | 322 ++++++------------ poincare/test/helper.cpp | 39 +++ poincare/test/helper.h | 6 + poincare/test/integer.cpp | 37 +- poincare/test/matrix.cpp | 12 +- poincare/test/parser.cpp | 62 ++-- poincare/test/power.cpp | 43 +-- poincare/test/product.cpp | 111 +----- poincare/test/subtraction.cpp | 100 +----- poincare/test/symbol.cpp | 23 +- poincare/test/trigo.cpp | 83 ++--- 165 files changed, 1675 insertions(+), 2154 deletions(-) create mode 100644 poincare/include/poincare/complex_matrix.h create mode 100644 poincare/include/poincare/evaluation.h create mode 100644 poincare/include/poincare/expression_matrix.h create mode 100644 poincare/src/complex_matrix.cpp create mode 100644 poincare/src/evaluation.cpp create mode 100644 poincare/src/expression_matrix.cpp create mode 100644 poincare/test/helper.cpp create mode 100644 poincare/test/helper.h diff --git a/apps/calculation/calculation.cpp b/apps/calculation/calculation.cpp index 7274e349d..7cfcc32df 100644 --- a/apps/calculation/calculation.cpp +++ b/apps/calculation/calculation.cpp @@ -76,7 +76,7 @@ ExpressionLayout * Calculation::inputLayout() { return m_inputLayout; } -Expression * Calculation::output(Context * context) { +Evaluation * Calculation::output(Context * context) { if (m_output == nullptr) { /* To ensure that the expression 'm_output' is a matrix or a complex, we * call 'evaluate'. */ diff --git a/apps/calculation/calculation.h b/apps/calculation/calculation.h index e19bae6d4..987578a41 100644 --- a/apps/calculation/calculation.h +++ b/apps/calculation/calculation.h @@ -20,7 +20,7 @@ public: const char * outputText(); Poincare::Expression * input(); Poincare::ExpressionLayout * inputLayout(); - Poincare::Expression * output(Poincare::Context * context); + Poincare::Evaluation * output(Poincare::Context * context); Poincare::ExpressionLayout * outputLayout(Poincare::Context * context); void setContent(const char * c, Poincare::Context * context); bool isEmpty(); @@ -30,7 +30,7 @@ private: char m_outputText[2*::TextField::maxBufferSize()]; Poincare::Expression * m_input; Poincare::ExpressionLayout * m_inputLayout; - Poincare::Expression * m_output; + Poincare::Evaluation * m_output; Poincare::ExpressionLayout * m_outputLayout; }; diff --git a/apps/calculation/local_context.cpp b/apps/calculation/local_context.cpp index f0352b2e3..1eb6f2512 100644 --- a/apps/calculation/local_context.cpp +++ b/apps/calculation/local_context.cpp @@ -10,7 +10,7 @@ LocalContext::LocalContext(GlobalContext * parentContext, CalculationStore * cal { } -Expression * LocalContext::ansValue() { +Evaluation * LocalContext::ansValue() { if (m_calculationStore->numberOfCalculations() == 0) { return m_parentContext->defaultExpression(); } @@ -18,13 +18,13 @@ Expression * LocalContext::ansValue() { return lastCalculation->output(m_parentContext); } -void LocalContext::setExpressionForSymbolName(Expression * expression, const Symbol * symbol) { +void LocalContext::setExpressionForSymbolName(Evaluation * expression, const Symbol * symbol) { if (symbol->name() != Symbol::SpecialSymbols::Ans) { m_parentContext->setExpressionForSymbolName(expression, symbol); } } -const Expression * LocalContext::expressionForSymbol(const Symbol * symbol) { +const Evaluation * LocalContext::expressionForSymbol(const Symbol * symbol) { if (symbol->name() == Symbol::SpecialSymbols::Ans) { return ansValue(); } else { diff --git a/apps/calculation/local_context.h b/apps/calculation/local_context.h index f960c85fe..1d3de885d 100644 --- a/apps/calculation/local_context.h +++ b/apps/calculation/local_context.h @@ -9,10 +9,10 @@ namespace Calculation { class LocalContext : public Poincare::Context { public: LocalContext(Poincare::GlobalContext * parentContext, CalculationStore * calculationStore); - void setExpressionForSymbolName(Poincare::Expression * expression, const Poincare::Symbol * symbol) override; - const Poincare::Expression * expressionForSymbol(const Poincare::Symbol * symbol) override; + void setExpressionForSymbolName(Poincare::Evaluation * expression, const Poincare::Symbol * symbol) override; + const Poincare::Evaluation * expressionForSymbol(const Poincare::Symbol * symbol) override; private: - Poincare::Expression * ansValue(); + Poincare::Evaluation * ansValue(); CalculationStore * m_calculationStore; Poincare::GlobalContext * m_parentContext; }; diff --git a/apps/sequence/local_context.cpp b/apps/sequence/local_context.cpp index 96d14176c..604362555 100644 --- a/apps/sequence/local_context.cpp +++ b/apps/sequence/local_context.cpp @@ -6,13 +6,14 @@ namespace Sequence { LocalContext::LocalContext(Context * parentContext) : VariableContext('n', parentContext), - m_values{{Complex::Float(NAN), Complex::Float(NAN)}, {Complex::Float(NAN), Complex::Float(NAN)} + m_values{{Complex::Float(NAN), Complex::Float(NAN)}, + {Complex::Float(NAN), Complex::Float(NAN)} //, {Complex::Float(NAN), Complex::Float(NAN)} } { } -const Expression * LocalContext::expressionForSymbol(const Symbol * symbol) { +const Evaluation * LocalContext::expressionForSymbol(const Symbol * symbol) { if (symbol->name() == Symbol::SpecialSymbols::un || symbol->name() == Symbol::SpecialSymbols::un1 || symbol->name() == Symbol::SpecialSymbols::vn || symbol->name() == Symbol::SpecialSymbols::vn1 || symbol->name() == Symbol::SpecialSymbols::wn || symbol->name() == Symbol::SpecialSymbols::wn1) { diff --git a/apps/sequence/local_context.h b/apps/sequence/local_context.h index de01cc6cf..e05512b7f 100644 --- a/apps/sequence/local_context.h +++ b/apps/sequence/local_context.h @@ -9,7 +9,7 @@ namespace Sequence { class LocalContext : public Poincare::VariableContext { public: LocalContext(Poincare::Context * parentContext); - const Poincare::Expression * expressionForSymbol(const Poincare::Symbol * symbol) override; + const Poincare::Evaluation * expressionForSymbol(const Poincare::Symbol * symbol) override; void setValueForSequenceRank(float value, const char * sequenceName, int rank); private: constexpr static int k_depth = 2; diff --git a/apps/variable_box_controller.cpp b/apps/variable_box_controller.cpp index 54ab33af2..6f51c4cc5 100644 --- a/apps/variable_box_controller.cpp +++ b/apps/variable_box_controller.cpp @@ -137,24 +137,22 @@ void VariableBoxController::ContentViewController::willDisplayCellForIndex(Highl char label[3]; putLabelAtIndexInBuffer(index, label); myCell->setLabel(label); - const Expression * expression = expressionForIndex(index); + const Evaluation * evaluation = expressionForIndex(index); if (m_currentPage == Page::Scalar) { myCell->displayExpression(false); char buffer[Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; - ((Complex *)expression)->writeTextInBuffer(buffer, Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)); + evaluation->writeTextInBuffer(buffer, Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)); myCell->setSubtitle(buffer); return; } myCell->displayExpression(true); - if (expression) { - assert(expression->type() == Expression::Type::Matrix); - Matrix * m = (Matrix *)expression; + if (evaluation) { /* TODO: implement list contexts */ - myCell->setExpression((Expression *)expression); + myCell->setExpression(evaluation); char buffer[2*Complex::bufferSizeForFloatsWithPrecision(2)+1]; - int numberOfChars = Complex::convertFloatToText(m->numberOfRows(), buffer, Complex::bufferSizeForFloatsWithPrecision(2), 2, Expression::FloatDisplayMode::Decimal); + int numberOfChars = Complex::convertFloatToText(evaluation->numberOfRows(), buffer, Complex::bufferSizeForFloatsWithPrecision(2), 2, Expression::FloatDisplayMode::Decimal); buffer[numberOfChars++] = 'x'; - Complex::convertFloatToText(m->numberOfColumns(), buffer+numberOfChars, Complex::bufferSizeForFloatsWithPrecision(2), 2, Expression::FloatDisplayMode::Decimal); + Complex::convertFloatToText(evaluation->numberOfColumns(), buffer+numberOfChars, Complex::bufferSizeForFloatsWithPrecision(2), 2, Expression::FloatDisplayMode::Decimal); myCell->setSubtitle(buffer); } else { myCell->setExpression(nullptr); @@ -203,7 +201,7 @@ int VariableBoxController::ContentViewController::typeAtLocation(int i, int j) { return 0; } -const Expression * VariableBoxController::ContentViewController::expressionForIndex(int index) { +const Evaluation * VariableBoxController::ContentViewController::expressionForIndex(int index) { if (m_currentPage == Page::Scalar) { const Symbol symbol = Symbol('A'+index); return m_context->expressionForSymbol(&symbol); diff --git a/apps/variable_box_controller.h b/apps/variable_box_controller.h index 96583be0f..79036fa48 100644 --- a/apps/variable_box_controller.h +++ b/apps/variable_box_controller.h @@ -56,7 +56,7 @@ private: Page pageAtIndex(int index); void putLabelAtIndexInBuffer(int index, char * buffer); I18n::Message nodeLabelAtIndex(int index); - const Poincare::Expression * expressionForIndex(int index); + const Poincare::Evaluation * expressionForIndex(int index); Poincare::Context * m_context; TextField * m_textFieldCaller; diff --git a/apps/variable_box_leaf_cell.cpp b/apps/variable_box_leaf_cell.cpp index aec45eeb8..6806d64fc 100644 --- a/apps/variable_box_leaf_cell.cpp +++ b/apps/variable_box_leaf_cell.cpp @@ -83,7 +83,7 @@ void VariableBoxLeafCell::setSubtitle(const char * text) { layoutSubviews(); } -void VariableBoxLeafCell::setExpression(Expression * expression) { +void VariableBoxLeafCell::setExpression(const Expression * expression) { if(m_expressionLayout != nullptr) { delete m_expressionLayout; m_expressionLayout = nullptr; diff --git a/apps/variable_box_leaf_cell.h b/apps/variable_box_leaf_cell.h index 83b7e0147..5de1e6a13 100644 --- a/apps/variable_box_leaf_cell.h +++ b/apps/variable_box_leaf_cell.h @@ -12,7 +12,7 @@ public: void reloadCell() override; void setLabel(const char * text); void setSubtitle(const char * text); - void setExpression(Poincare::Expression * expression); + void setExpression(const Poincare::Expression * expression); void drawRect(KDContext * ctx, KDRect rect) const override; private: constexpr static KDCoordinate k_separatorThickness = 1; diff --git a/poincare/Makefile b/poincare/Makefile index 1f4ba8d46..dabfef752 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -13,6 +13,7 @@ objs += $(addprefix poincare/src/,\ ceiling.o\ complex.o\ complex_argument.o\ + complex_matrix.o\ confidence_interval.o\ conjugate.o\ cosine.o\ @@ -20,6 +21,7 @@ objs += $(addprefix poincare/src/,\ determinant.o\ division_quotient.o\ division_remainder.o\ + evaluation.o\ expression.o\ expression_lexer.o\ expression_parser.o\ @@ -28,6 +30,7 @@ objs += $(addprefix poincare/src/,\ frac_part.o\ fraction.o\ function.o\ + expression_matrix.o\ global_context.o\ great_common_divisor.o\ hyperbolic_arc_cosine.o\ @@ -96,6 +99,7 @@ tests += $(addprefix poincare/test/,\ complex.cpp\ fraction.cpp\ function.cpp\ + helper.cpp\ identity.cpp\ integer.cpp\ matrix.cpp\ diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index 6b6564474..032a4ed77 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -20,12 +21,15 @@ #include #include #include +#include #include +#include #include #include #include #include #include +#include #include #include #include diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index d531ba8f0..2902e8043 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -12,7 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; }; diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 5e187f795..485850805 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -12,9 +12,13 @@ public: Expression * cloneWithDifferentOperands(Expression** newOperands, int numnerOfOperands, bool cloneOperands = true) const override; bool isCommutative() const override; + static Complex compute(const Complex c, const Complex d); + static Evaluation * computeOnMatrices(Evaluation * m, Evaluation * n); + static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * m); private: - Expression * evaluateOnComplex(Complex * c, Complex * d, Context& context, AngleUnit angleUnit) const override; - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Complex privateCompute(const Complex c, const Complex d) const override { + return compute(c, d); + } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; }; diff --git a/poincare/include/poincare/arc_cosine.h b/poincare/include/poincare/arc_cosine.h index 52516ad9d..202e8da4b 100644 --- a/poincare/include/poincare/arc_cosine.h +++ b/poincare/include/poincare/arc_cosine.h @@ -12,7 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/arc_sine.h b/poincare/include/poincare/arc_sine.h index ad77b737e..afaccc878 100644 --- a/poincare/include/poincare/arc_sine.h +++ b/poincare/include/poincare/arc_sine.h @@ -12,7 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/arc_tangent.h b/poincare/include/poincare/arc_tangent.h index cf158f7df..b90afe480 100644 --- a/poincare/include/poincare/arc_tangent.h +++ b/poincare/include/poincare/arc_tangent.h @@ -12,7 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/binary_operation.h b/poincare/include/poincare/binary_operation.h index 8d9664fed..54d6e36a6 100644 --- a/poincare/include/poincare/binary_operation.h +++ b/poincare/include/poincare/binary_operation.h @@ -4,11 +4,13 @@ #include #include #include +#include namespace Poincare { class BinaryOperation : public Expression { public: + BinaryOperation(); BinaryOperation(Expression ** operands, bool cloneOperands = true); ~BinaryOperation(); BinaryOperation(const BinaryOperation& other) = delete; @@ -21,11 +23,14 @@ public: Expression * clone() const override; protected: Expression * m_operands[2]; - Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const override; - virtual Expression * evaluateOnComplex(Complex * c, Complex * d, Context& context, AngleUnit angleUnit) const = 0; - virtual Expression * evaluateOnMatrixAndComplex(Matrix * m, Complex * c, Context& context, AngleUnit angleUnit) const; - virtual Expression * evaluateOnComplexAndMatrix(Complex * c, Matrix * m, Context& context, AngleUnit angleUnit) const; - virtual Expression * evaluateOnMatrices(Matrix * m, Matrix * n, Context& context, AngleUnit angleUnit) const; + Evaluation * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + virtual Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const; + virtual Evaluation * computeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const; + virtual Evaluation * computeOnNumericalMatrices(Evaluation * m, Evaluation * n) const; + Evaluation * computeOnComplexes(const Complex * c, const Complex * d) const { + return new Complex(privateCompute(*c, *d)); + } + virtual Complex privateCompute(const Complex c, const Complex d) const = 0; }; } diff --git a/poincare/include/poincare/binomial_coefficient.h b/poincare/include/poincare/binomial_coefficient.h index 06a25ea8b..61cdb4618 100644 --- a/poincare/include/poincare/binomial_coefficient.h +++ b/poincare/include/poincare/binomial_coefficient.h @@ -12,7 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; }; diff --git a/poincare/include/poincare/ceiling.h b/poincare/include/poincare/ceiling.h index e09f04eec..19078612b 100644 --- a/poincare/include/poincare/ceiling.h +++ b/poincare/include/poincare/ceiling.h @@ -12,7 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/complex.h b/poincare/include/poincare/complex.h index 93d2630c9..31a5d3c24 100644 --- a/poincare/include/poincare/complex.h +++ b/poincare/include/poincare/complex.h @@ -1,28 +1,44 @@ #ifndef POINCARE_COMPLEX_H #define POINCARE_COMPLEX_H -#include +#include #include #include namespace Poincare { -class Complex : public LeafExpression { +class Complex : public Evaluation { public: + Complex() : m_a(0.0f), m_b(0.0f) {} static Complex Float(float x); static Complex Cartesian(float a, float b); static Complex Polar(float r, float theta); Complex(const char * integralPart, int integralPartLength, bool integralNegative, const char * fractionalPart, int fractionalPartLength, const char * exponent, int exponentLength, bool exponentNegative); + float toFloat() const override; + const Complex * operand(int i) const override { + return complexOperand(i); + } + int numberOfRows() const override; + int numberOfColumns() const override; Type type() const override; - Expression * clone() const override; - int writeTextInBuffer(char * buffer, int bufferSize) override; - float a(); - float b(); + Complex * clone() const override; + Evaluation * cloneWithDifferentOperands(Expression** newOperands, + int numberOfOperands, bool cloneOperands = true) const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override; + Evaluation * createDeterminant() const override { + return clone(); + } + Evaluation * createInverse() const override; + Evaluation * createTrace() const override { + return clone(); + } + float a() const; + float b() const; float r() const; float th() const; - Complex * createConjugate(); + Complex conjugate() const; /* The parameter 'DisplayMode' refers to the way to display float 'scientific' * or 'auto'. The scientific mode returns float with style -1.2E2 whereas * the auto mode tries to return 'natural' float like (0.021) and switches @@ -41,10 +57,10 @@ public: } private: Complex(float a, float b); + const Complex * complexOperand(int i) const override; constexpr static int k_numberOfSignificantDigits = 7; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const override; - float privateApproximate(Context& context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(Context& context, AngleUnit angleUnit) const override; /* We here define the buffer size to write the lengthest float possible. * At maximum, the number has 7 significant digits so, in the worst case it * has the form -1.999999e-38 (7+6+1 char) (the auto mode is always diff --git a/poincare/include/poincare/complex_argument.h b/poincare/include/poincare/complex_argument.h index ad0651f67..e45664b44 100644 --- a/poincare/include/poincare/complex_argument.h +++ b/poincare/include/poincare/complex_argument.h @@ -12,7 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/complex_matrix.h b/poincare/include/poincare/complex_matrix.h new file mode 100644 index 000000000..66cc268ce --- /dev/null +++ b/poincare/include/poincare/complex_matrix.h @@ -0,0 +1,33 @@ +#ifndef POINCARE_COMPLEX_MATRIX_H +#define POINCARE_COMPLEX_MATRIX_H + +#include + +namespace Poincare { + +class ComplexMatrix : public Evaluation { +public: + ComplexMatrix(const Complex * complexes, int numberOfRows, int numberOfColumns); + ~ComplexMatrix(); + ComplexMatrix(const ComplexMatrix& other) = delete; + ComplexMatrix(ComplexMatrix&& other) = delete; + ComplexMatrix& operator=(const ComplexMatrix& other) = delete; + ComplexMatrix& operator=(ComplexMatrix&& other) = delete; + float toFloat() const override; + const Complex * complexOperand(int i) const override; + int numberOfRows() const override; + int numberOfColumns() const override; + ComplexMatrix * clone() const override; + ComplexMatrix * cloneWithDifferentOperands(Expression** newOperands, + int numberOfOperands, bool cloneOperands = true) const override; + static Evaluation * createIdentity(int dim); +private: + Complex * m_values; + int m_numberOfRows; + int m_numberOfColumns; +}; + +} + +#endif + diff --git a/poincare/include/poincare/confidence_interval.h b/poincare/include/poincare/confidence_interval.h index 7ef0214c9..704f3817b 100644 --- a/poincare/include/poincare/confidence_interval.h +++ b/poincare/include/poincare/confidence_interval.h @@ -12,8 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; - Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(Context& context, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/conjugate.h b/poincare/include/poincare/conjugate.h index 9de194f45..ed3980f7d 100644 --- a/poincare/include/poincare/conjugate.h +++ b/poincare/include/poincare/conjugate.h @@ -12,8 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; - Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; }; diff --git a/poincare/include/poincare/context.h b/poincare/include/poincare/context.h index c098d64a6..8aa100043 100644 --- a/poincare/include/poincare/context.h +++ b/poincare/include/poincare/context.h @@ -1,15 +1,15 @@ #ifndef POINCARE_CONTEXT_H #define POINCARE_CONTEXT_H -#include +#include #include namespace Poincare { class Context { public: - virtual const Expression * expressionForSymbol(const Symbol * symbol) = 0; - virtual void setExpressionForSymbolName(Expression * expression, const Symbol * symbol) = 0; + virtual const Evaluation * expressionForSymbol(const Symbol * symbol) = 0; + virtual void setExpressionForSymbolName(Evaluation * expression, const Symbol * symbol) = 0; }; } diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index aa9a03a4f..0a1c9b45c 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -11,9 +11,12 @@ public: Type type() const override; Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; + static Complex compute(const Complex c); private: - float trigonometricApproximation(float x) const override; - Expression * createComplexEvaluation(Expression * arg, Context & context, AngleUnit angleUnit) const override; + Complex privateCompute(const Complex c, AngleUnit angleUnit) const override { + return compute(c); + } + float computeForRadianReal(float x) const override; }; } diff --git a/poincare/include/poincare/derivative.h b/poincare/include/poincare/derivative.h index 0fc6e37d5..62f03f060 100644 --- a/poincare/include/poincare/derivative.h +++ b/poincare/include/poincare/derivative.h @@ -13,7 +13,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; float growthRateAroundAbscissa(float x, float h, VariableContext variableContext, AngleUnit angleUnit) const; float approximateDerivate2(float x, float h, VariableContext xContext, AngleUnit angleUnit) const; constexpr static float k_maxErrorRateOnApproximation = 0.001f; diff --git a/poincare/include/poincare/determinant.h b/poincare/include/poincare/determinant.h index dcc0bbea9..87f35ea74 100644 --- a/poincare/include/poincare/determinant.h +++ b/poincare/include/poincare/determinant.h @@ -12,7 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/division_quotient.h b/poincare/include/poincare/division_quotient.h index 7892ae39b..d089fa2b3 100644 --- a/poincare/include/poincare/division_quotient.h +++ b/poincare/include/poincare/division_quotient.h @@ -12,7 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/division_remainder.h b/poincare/include/poincare/division_remainder.h index 651f75cdd..dde2f675f 100644 --- a/poincare/include/poincare/division_remainder.h +++ b/poincare/include/poincare/division_remainder.h @@ -12,7 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/evaluation.h b/poincare/include/poincare/evaluation.h new file mode 100644 index 000000000..9096fc8e8 --- /dev/null +++ b/poincare/include/poincare/evaluation.h @@ -0,0 +1,28 @@ +#ifndef POINCARE_EVALUATION_H +#define POINCARE_EVALUATION_H + +#include + +namespace Poincare { + +class Complex; + +class Evaluation : public Matrix { +public: + virtual float toFloat() const = 0; + Type type() const override; + bool hasValidNumberOfArguments() const override; + virtual const Expression * operand(int i) const override; + virtual const Complex * complexOperand(int i) const = 0; + virtual Evaluation * clone() const override = 0; + virtual Evaluation * createTrace() const; + virtual Evaluation * createDeterminant() const; + virtual Evaluation * createInverse() const; + Evaluation * createTranspose() const; +private: + Evaluation * privateEvaluate(Context& context, AngleUnit angleUnit) const override; +}; + +} + +#endif diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 40c932f27..5bf6c9a59 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -7,6 +7,7 @@ namespace Poincare { class Context; +class Evaluation; class Expression { public: @@ -31,6 +32,7 @@ public: Float, Floor, FracPart, + ExpressionMatrix, GreatCommonDivisor, HyperbolicArcCosine, HyperbolicArcSine, @@ -43,7 +45,6 @@ public: Integral, Logarithm, LeastCommonMultiple, - Matrix, MatrixDimension, MatrixInverse, MatrixTrace, @@ -51,6 +52,7 @@ public: Multiplication, NaperianLogarithm, NthRoot, + Evaluation, Opposite, PredictionInterval, Fraction, @@ -131,14 +133,13 @@ public: /* The function evaluate creates a new expression and thus mallocs memory. * Do not forget to delete the new expression to avoid leaking. */ - Expression * evaluate(Context& context, AngleUnit angleUnit = AngleUnit::Default) const; + Evaluation * evaluate(Context& context, AngleUnit angleUnit = AngleUnit::Default) const; float approximate(Context& context, AngleUnit angleUnit = AngleUnit::Default) const; static float approximate(const char * text, Context& context, AngleUnit angleUnit = AngleUnit::Default); - virtual int writeTextInBuffer(char * buffer, int bufferSize); + virtual int writeTextInBuffer(char * buffer, int bufferSize) const; private: virtual ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const = 0; - virtual Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const = 0; - virtual float privateApproximate(Context& context, AngleUnit angleUnit) const = 0; + virtual Evaluation * privateEvaluate(Context& context, AngleUnit angleUnit) const = 0; bool sequentialOperandsIdentity(const Expression * e) const; bool commutativeOperandsIdentity(const Expression * e) const; bool combinatoryCommutativeOperandsIdentity(const Expression * e, diff --git a/poincare/include/poincare/expression_matrix.h b/poincare/include/poincare/expression_matrix.h new file mode 100644 index 000000000..9fded1261 --- /dev/null +++ b/poincare/include/poincare/expression_matrix.h @@ -0,0 +1,33 @@ +#ifndef POINCARE_EXPRESSION_MATRIX_H +#define POINCARE_EXPRESSION_MATRIX_H + +#include + +namespace Poincare { + +class ExpressionMatrix : public Matrix { +public: + ExpressionMatrix(MatrixData * matrixData); + ExpressionMatrix(Expression ** newOperands, int numberOfOperands, int m_numberOfColumns, int m_numberOfRows, bool cloneOperands); + ~ExpressionMatrix(); + ExpressionMatrix(const Matrix& other) = delete; + ExpressionMatrix(Matrix&& other) = delete; + ExpressionMatrix& operator=(const ExpressionMatrix& other) = delete; + ExpressionMatrix& operator=(ExpressionMatrix&& other) = delete; + bool hasValidNumberOfArguments() const override; + int numberOfRows() const override; + int numberOfColumns() const override; + const Expression * operand(int i) const override; + Expression * clone() const override; + Type type() const override; + Expression * cloneWithDifferentOperands(Expression** newOperands, + int numberOfOperands, bool cloneOperands = true) const override; +private: + Evaluation * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + static Complex * defaultExpression(); + MatrixData * m_matrixData; +}; + +} + +#endif diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index fa1e0bff3..e5c1874ea 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -12,7 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; }; diff --git a/poincare/include/poincare/floor.h b/poincare/include/poincare/floor.h index da82e8a42..01c215ae7 100644 --- a/poincare/include/poincare/floor.h +++ b/poincare/include/poincare/floor.h @@ -12,7 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/frac_part.h b/poincare/include/poincare/frac_part.h index d83a51336..88728da9e 100644 --- a/poincare/include/poincare/frac_part.h +++ b/poincare/include/poincare/frac_part.h @@ -12,7 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/fraction.h b/poincare/include/poincare/fraction.h index 0f8fdbbfa..749b53fd6 100644 --- a/poincare/include/poincare/fraction.h +++ b/poincare/include/poincare/fraction.h @@ -11,12 +11,14 @@ public: Type type() const override; Expression * cloneWithDifferentOperands(Expression** newOperands, int numnerOfOperands, bool cloneOperands = true) const override; + static Complex compute(const Complex c, const Complex d); private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - float privateApproximate(Context& context, AngleUnit angleUnit) const override; - Expression * evaluateOnComplex(Complex * c, Complex * d, Context& context, AngleUnit angleUnit) const override; - Expression * evaluateOnComplexAndMatrix(Complex * c, Matrix * m, Context& context, AngleUnit angleUnit) const override; - Expression * evaluateOnMatrices(Matrix * m, Matrix * n, Context& context, AngleUnit angleUnit) const override; + Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const override; + Evaluation * computeOnNumericalMatrices(Evaluation * m, Evaluation * n) const override; + Complex privateCompute(const Complex c, const Complex d) const override { + return compute(c, d); + } }; } diff --git a/poincare/include/poincare/function.h b/poincare/include/poincare/function.h index c71baebbd..215927853 100644 --- a/poincare/include/poincare/function.h +++ b/poincare/include/poincare/function.h @@ -3,6 +3,8 @@ #include #include +#include +#include namespace Poincare { @@ -24,8 +26,11 @@ public: int numberOfOperands() const override; Expression * clone() const override; protected: + virtual Complex computeComplex(const Complex c, AngleUnit angleUnit) const; + virtual Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + void build(Expression ** args, int numberOfArguments, bool clone); + void clean(); Expression ** m_args; int m_numberOfArguments; int m_requiredNumberOfArguments; diff --git a/poincare/include/poincare/global_context.h b/poincare/include/poincare/global_context.h index d443ed371..b318976a1 100644 --- a/poincare/include/poincare/global_context.h +++ b/poincare/include/poincare/global_context.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -20,16 +21,16 @@ public: GlobalContext& operator=(GlobalContext&& other) = delete; /* The expression recorded in global context is already a final expression. * Otherwise, we would need the context and the angle unit to evaluate it */ - const Expression * expressionForSymbol(const Symbol * symbol) override; - void setExpressionForSymbolName(Expression * expression, const Symbol * symbol) override; + const Evaluation * expressionForSymbol(const Symbol * symbol) override; + void setExpressionForSymbolName(Evaluation * expression, const Symbol * symbol) override; static constexpr uint16_t k_maxNumberOfScalarExpressions = 26; static constexpr uint16_t k_maxNumberOfListExpressions = 10; static constexpr uint16_t k_maxNumberOfMatrixExpressions = 10; - static Complex * defaultExpression(); + static Evaluation * defaultExpression(); private: int symbolIndex(const Symbol * symbol) const; - Expression * m_expressions[k_maxNumberOfScalarExpressions]; - Expression * m_matrixExpressions[k_maxNumberOfMatrixExpressions]; + Evaluation * m_expressions[k_maxNumberOfScalarExpressions]; + Evaluation * m_matrixExpressions[k_maxNumberOfMatrixExpressions]; Complex m_pi; Complex m_e; }; diff --git a/poincare/include/poincare/great_common_divisor.h b/poincare/include/poincare/great_common_divisor.h index 99ff761d0..282295c7d 100644 --- a/poincare/include/poincare/great_common_divisor.h +++ b/poincare/include/poincare/great_common_divisor.h @@ -12,7 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/hyperbolic_arc_cosine.h b/poincare/include/poincare/hyperbolic_arc_cosine.h index 1209410b5..dbbad5524 100644 --- a/poincare/include/poincare/hyperbolic_arc_cosine.h +++ b/poincare/include/poincare/hyperbolic_arc_cosine.h @@ -12,7 +12,8 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; + }; } diff --git a/poincare/include/poincare/hyperbolic_arc_sine.h b/poincare/include/poincare/hyperbolic_arc_sine.h index 007d892af..8dff58ee8 100644 --- a/poincare/include/poincare/hyperbolic_arc_sine.h +++ b/poincare/include/poincare/hyperbolic_arc_sine.h @@ -12,7 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/hyperbolic_arc_tangent.h b/poincare/include/poincare/hyperbolic_arc_tangent.h index 293440ad5..5358edc69 100644 --- a/poincare/include/poincare/hyperbolic_arc_tangent.h +++ b/poincare/include/poincare/hyperbolic_arc_tangent.h @@ -12,7 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/hyperbolic_cosine.h b/poincare/include/poincare/hyperbolic_cosine.h index 97749b36a..c78d97647 100644 --- a/poincare/include/poincare/hyperbolic_cosine.h +++ b/poincare/include/poincare/hyperbolic_cosine.h @@ -11,9 +11,11 @@ public: Type type() const override; Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; + static Complex compute(const Complex c); private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; - Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return compute(c); + } }; } diff --git a/poincare/include/poincare/hyperbolic_sine.h b/poincare/include/poincare/hyperbolic_sine.h index bda5476ed..e43e3ac02 100644 --- a/poincare/include/poincare/hyperbolic_sine.h +++ b/poincare/include/poincare/hyperbolic_sine.h @@ -11,9 +11,11 @@ public: Type type() const override; Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; + static Complex compute(const Complex c); private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; - Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return compute(c); + } }; } diff --git a/poincare/include/poincare/hyperbolic_tangent.h b/poincare/include/poincare/hyperbolic_tangent.h index 63c63b992..c82c460be 100644 --- a/poincare/include/poincare/hyperbolic_tangent.h +++ b/poincare/include/poincare/hyperbolic_tangent.h @@ -11,9 +11,11 @@ public: Type type() const override; Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; + static Complex compute(const Complex c); private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; - Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return compute(c); + } }; } diff --git a/poincare/include/poincare/imaginary_part.h b/poincare/include/poincare/imaginary_part.h index 49f72c6c7..8e8996e22 100644 --- a/poincare/include/poincare/imaginary_part.h +++ b/poincare/include/poincare/imaginary_part.h @@ -12,7 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index a381e77b0..882836550 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -36,8 +36,7 @@ public: Expression * clone() const override; private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - float privateApproximate(Context& context, AngleUnit angleUnit) const override; - Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(Context& context, AngleUnit angleUnit) const override; Integer add(const Integer &other, bool inverse_other_negative) const; int8_t ucmp(const Integer &other) const; // -1, 0, or 1 Integer usum(const Integer &other, bool subtract, bool output_negative) const; diff --git a/poincare/include/poincare/integral.h b/poincare/include/poincare/integral.h index 909544287..80c369705 100644 --- a/poincare/include/poincare/integral.h +++ b/poincare/include/poincare/integral.h @@ -13,7 +13,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; struct DetailedResult { diff --git a/poincare/include/poincare/least_common_multiple.h b/poincare/include/poincare/least_common_multiple.h index 8ee3bfdf8..6c30a4131 100644 --- a/poincare/include/poincare/least_common_multiple.h +++ b/poincare/include/poincare/least_common_multiple.h @@ -12,7 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/list_data.h b/poincare/include/poincare/list_data.h index 52bdfa44d..4ca4a05f8 100644 --- a/poincare/include/poincare/list_data.h +++ b/poincare/include/poincare/list_data.h @@ -14,6 +14,7 @@ public: ListData& operator=(const ListData& other) = delete; ListData& operator=(ListData&& other) = delete; int numberOfOperands() const; + Expression ** operands() const; const Expression * operand(int i) const; void pushExpression(Expression * operand); private: diff --git a/poincare/include/poincare/logarithm.h b/poincare/include/poincare/logarithm.h index 3c597f1aa..d776980c3 100644 --- a/poincare/include/poincare/logarithm.h +++ b/poincare/include/poincare/logarithm.h @@ -13,8 +13,9 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/matrix.h b/poincare/include/poincare/matrix.h index 1b736aab4..425a14139 100644 --- a/poincare/include/poincare/matrix.h +++ b/poincare/include/poincare/matrix.h @@ -2,44 +2,21 @@ #define POINCARE_MATRIX_H #include -#include #include namespace Poincare { class Matrix : public Expression { public: - Matrix(MatrixData * matrixData); - Matrix(Expression ** newOperands, int numberOfOperands, int m_numberOfColumns, int m_numberOfRows, bool cloneOperands); - ~Matrix(); - Matrix(const Matrix& other) = delete; - Matrix(Matrix&& other) = delete; - Matrix& operator=(const Matrix& other) = delete; - Matrix& operator=(Matrix&& other) = delete; - bool hasValidNumberOfArguments() const override; - const Expression * operand(int i) const override; + virtual const Expression * operand(int i) const override = 0; int numberOfOperands() const override; - Expression * clone() const override; - Type type() const override; - Expression * cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; - int numberOfRows() const; - int numberOfColumns() const; + virtual int numberOfRows() const = 0; + virtual int numberOfColumns() const = 0; /* If the buffer is too small, the function fills the buffer until reaching * buffer size */ - int writeTextInBuffer(char * buffer, int bufferSize) override; - Expression * createDimensionMatrix(Context& context, AngleUnit angleUnit) const; - float trace(Context& context, AngleUnit angleUnit) const; - float determinant(Context& context, AngleUnit angleUnit) const; - Expression * createInverse(Context& context, AngleUnit angleUnit) const; - Expression * createTranspose(Context& context, AngleUnit angleUnit) const; - static Expression * createIdentity(int dim); + int writeTextInBuffer(char * buffer, int bufferSize) const override; private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - float privateApproximate(Context& context, AngleUnit angleUnit) const override; - Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const override; - MatrixData * m_matrixData; - static Complex * defaultExpression(); }; } diff --git a/poincare/include/poincare/matrix_data.h b/poincare/include/poincare/matrix_data.h index 066501d1f..527295762 100644 --- a/poincare/include/poincare/matrix_data.h +++ b/poincare/include/poincare/matrix_data.h @@ -2,11 +2,12 @@ #define POINCARE_MATRIX_DATA_H #include -#include #include namespace Poincare { +class Complex; + class MatrixData { public: MatrixData(ListData * listData, bool clone); diff --git a/poincare/include/poincare/matrix_dimension.h b/poincare/include/poincare/matrix_dimension.h index f90a1f630..e399aece6 100644 --- a/poincare/include/poincare/matrix_dimension.h +++ b/poincare/include/poincare/matrix_dimension.h @@ -12,8 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; - Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(Context& context, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/matrix_inverse.h b/poincare/include/poincare/matrix_inverse.h index ba96f89b8..28b2ff0db 100644 --- a/poincare/include/poincare/matrix_inverse.h +++ b/poincare/include/poincare/matrix_inverse.h @@ -12,8 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; - Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(Context& context, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/matrix_trace.h b/poincare/include/poincare/matrix_trace.h index fc3fd1b3d..799e45ec0 100644 --- a/poincare/include/poincare/matrix_trace.h +++ b/poincare/include/poincare/matrix_trace.h @@ -12,7 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(Context& context, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/matrix_transpose.h b/poincare/include/poincare/matrix_transpose.h index 8755e3be3..53bdec606 100644 --- a/poincare/include/poincare/matrix_transpose.h +++ b/poincare/include/poincare/matrix_transpose.h @@ -12,8 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; - Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(Context& context, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 97f1f6f89..fbbce4fe3 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -11,11 +11,17 @@ public: Type type() const override; Expression * cloneWithDifferentOperands(Expression** newOperands, int numnerOfOperands, bool cloneOperands = true) const override; + static Evaluation * computeOnMatrices(Evaluation * m, Evaluation * n); + static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * m); + static Complex compute(const Complex c, const Complex d); private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - float privateApproximate(Context& context, AngleUnit angleUnit) const override; - Expression * evaluateOnComplex(Complex * c, Complex * d, Context& context, AngleUnit angleUnit) const override; - Expression * evaluateOnMatrices(Matrix * m, Matrix * n, Context& context, AngleUnit angleUnit) const override; + Evaluation * computeOnNumericalMatrices(Evaluation * m, Evaluation * n) const override { + return computeOnMatrices(m, n); + } + Complex privateCompute(const Complex c, const Complex d) const override { + return compute(c, d); + } }; } diff --git a/poincare/include/poincare/naperian_logarithm.h b/poincare/include/poincare/naperian_logarithm.h index bc80fffe3..c2459e5ae 100644 --- a/poincare/include/poincare/naperian_logarithm.h +++ b/poincare/include/poincare/naperian_logarithm.h @@ -12,7 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/nth_root.h b/poincare/include/poincare/nth_root.h index cc3e60da1..dc14ddb88 100644 --- a/poincare/include/poincare/nth_root.h +++ b/poincare/include/poincare/nth_root.h @@ -12,9 +12,9 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + Complex compute(const Complex c, const Complex d) const; }; } diff --git a/poincare/include/poincare/opposite.h b/poincare/include/poincare/opposite.h index da28feb2f..747f89b02 100644 --- a/poincare/include/poincare/opposite.h +++ b/poincare/include/poincare/opposite.h @@ -21,12 +21,12 @@ public: Type type() const override; Expression * cloneWithDifferentOperands(Expression** newOperands, int numnerOfOperands, bool cloneOperands = true) const override; + static Complex compute(const Complex c); + static Evaluation * computeOnMatrix(Evaluation * m); private: - float privateApproximate(Context& context, AngleUnit angleUnit) const override; - Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; Expression * m_operand; - Expression * evaluateOnMatrix(Matrix * m, Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index 036f65e70..c317181c9 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -22,8 +22,7 @@ public: int numnerOfOperands, bool cloneOperands = true) const override; private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - float privateApproximate(Context& context, AngleUnit angleUnit) const override; - Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; Expression * m_operand; }; diff --git a/poincare/include/poincare/permute_coefficient.h b/poincare/include/poincare/permute_coefficient.h index 24664e935..578ca4203 100644 --- a/poincare/include/poincare/permute_coefficient.h +++ b/poincare/include/poincare/permute_coefficient.h @@ -12,7 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 47da53c8b..d709c5e60 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -11,14 +11,16 @@ public: Type type() const override; Expression * cloneWithDifferentOperands(Expression** newOperands, int numnerOfOperands, bool cloneOperands = true) const override; + static Complex compute(const Complex c, const Complex d); private: constexpr static float k_maxNumberOfSteps = 10000.0f; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - float privateApproximate(Context& context, AngleUnit angleUnit) const override; - Expression * evaluateOnComplex(Complex * c, Complex * d, Context& context, AngleUnit angleUnit) const override; - Expression * evaluateOnMatrixAndComplex(Matrix * m, Complex * c, Context& context, AngleUnit angleUnit) const override; - Expression * evaluateOnComplexAndMatrix(Complex * c, Matrix * m, Context& context, AngleUnit angleUnit) const override; - Expression * evaluateOnMatrices(Matrix * m, Matrix * n, Context& context, AngleUnit angleUnit) const override; + Complex privateCompute(const Complex c, const Complex d) const override { + return compute(c, d); + } + Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const override; + Evaluation * computeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const override; + Evaluation * computeOnNumericalMatrices(Evaluation * m, Evaluation * n) const override; }; } diff --git a/poincare/include/poincare/prediction_interval.h b/poincare/include/poincare/prediction_interval.h index 5044945a6..476269891 100644 --- a/poincare/include/poincare/prediction_interval.h +++ b/poincare/include/poincare/prediction_interval.h @@ -12,8 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; - Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/product.h b/poincare/include/poincare/product.h index 49618d621..596c44a18 100644 --- a/poincare/include/poincare/product.h +++ b/poincare/include/poincare/product.h @@ -13,9 +13,8 @@ public: int numberOfOperands, bool cloneOperands = true) const override; private: float emptySequenceValue() const override; - float approximateWithNextTerm(float sequence, float newTerm) const override; ExpressionLayout * createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const override; - Expression * evaluateWithNextTerm(Expression ** args, Context& context, AngleUnit angleUnit) const override; + Evaluation * evaluateWithNextTerm(Evaluation * a, Evaluation * b) const override; }; } diff --git a/poincare/include/poincare/reel_part.h b/poincare/include/poincare/reel_part.h index 64ebea971..88164c8b4 100644 --- a/poincare/include/poincare/reel_part.h +++ b/poincare/include/poincare/reel_part.h @@ -12,7 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/round.h b/poincare/include/poincare/round.h index 85e1bd0e1..6cfb83229 100644 --- a/poincare/include/poincare/round.h +++ b/poincare/include/poincare/round.h @@ -12,7 +12,7 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/sequence.h b/poincare/include/poincare/sequence.h index 18f3e0b29..f0cbc01b8 100644 --- a/poincare/include/poincare/sequence.h +++ b/poincare/include/poincare/sequence.h @@ -10,13 +10,11 @@ public: Sequence(const char * name); private: constexpr static float k_maxNumberOfSteps = 10000.0f; - float privateApproximate(Context & context, AngleUnit angleUnit) const override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(Context& context, AngleUnit angleUnit) const override; virtual float emptySequenceValue() const = 0; - virtual float approximateWithNextTerm(float sequence, float newTerm) const = 0; virtual ExpressionLayout * createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const = 0; - virtual Expression * evaluateWithNextTerm(Expression ** args, Context& context, AngleUnit angleUnit) const = 0; + virtual Evaluation * evaluateWithNextTerm(Evaluation * a, Evaluation * b) const = 0; }; } diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index 0d6eba683..6e81ed30e 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -11,9 +11,12 @@ public: Type type() const override; Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; + static Complex compute(const Complex c); private: - float trigonometricApproximation(float x) const override; - Expression * createComplexEvaluation(Expression * arg, Context & context, AngleUnit angleUnit) const override; + Complex privateCompute(const Complex c, AngleUnit angleUnit) const override { + return compute(c); + } + float computeForRadianReal(float x) const override; }; } diff --git a/poincare/include/poincare/square_root.h b/poincare/include/poincare/square_root.h index e2198de9e..b33f796b9 100644 --- a/poincare/include/poincare/square_root.h +++ b/poincare/include/poincare/square_root.h @@ -12,9 +12,8 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; }; } diff --git a/poincare/include/poincare/store.h b/poincare/include/poincare/store.h index 084b30761..957daa044 100644 --- a/poincare/include/poincare/store.h +++ b/poincare/include/poincare/store.h @@ -23,8 +23,7 @@ public: int numberOfOperands, bool cloneOperands = true) const override; private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const override; - float privateApproximate(Context& context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; Symbol * m_symbol; Expression * m_value; }; diff --git a/poincare/include/poincare/subtraction.h b/poincare/include/poincare/subtraction.h index 181795ad9..e63c6166a 100644 --- a/poincare/include/poincare/subtraction.h +++ b/poincare/include/poincare/subtraction.h @@ -11,11 +11,13 @@ public: Type type() const override; Expression * cloneWithDifferentOperands(Expression** newOperands, int numnerOfOperands, bool cloneOperands = true) const override; + static Complex compute(const Complex c, const Complex d); private: - float privateApproximate(Context& context, AngleUnit angleUnit) const override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - Expression * evaluateOnComplex(Complex * c, Complex * d, Context& context, AngleUnit angleUnit) const override; - Expression * evaluateOnComplexAndMatrix(Complex * c, Matrix * m, Context& context, AngleUnit angleUnit) const override; + Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * m) const override; + Complex privateCompute(const Complex c, const Complex d) const override { + return compute(c, d); + } }; } diff --git a/poincare/include/poincare/sum.h b/poincare/include/poincare/sum.h index 1b6a68769..9723dd7c9 100644 --- a/poincare/include/poincare/sum.h +++ b/poincare/include/poincare/sum.h @@ -13,9 +13,8 @@ public: int numberOfOperands, bool cloneOperands = true) const override; private: float emptySequenceValue() const override; - float approximateWithNextTerm(float sequence, float newTerm) const override; ExpressionLayout * createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const override; - Expression * evaluateWithNextTerm(Expression ** args, Context& context, AngleUnit angleUnit) const override; + Evaluation * evaluateWithNextTerm(Evaluation * a, Evaluation * b) const override; }; } diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index 06cde83a2..66ea3f55b 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -36,8 +36,7 @@ public: bool valueEquals(const Expression * e) const override; bool isMatrixSymbol() const; private: - float privateApproximate(Context& context, AngleUnit angleUnit) const override; - Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(Context& context, AngleUnit angleUnit) const override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; const char m_name; }; diff --git a/poincare/include/poincare/tangent.h b/poincare/include/poincare/tangent.h index 9da1383bf..d4ae7ace0 100644 --- a/poincare/include/poincare/tangent.h +++ b/poincare/include/poincare/tangent.h @@ -12,8 +12,8 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numnerOfOperands, bool cloneOperands = true) const override; private: - float trigonometricApproximation(float x) const override; - Expression * createComplexEvaluation(Expression * arg, Context & context, AngleUnit angleUnit) const override; + Complex privateCompute(const Complex c, AngleUnit angleUnit) const override; + float computeForRadianReal(float x) const override; }; } diff --git a/poincare/include/poincare/trigonometric_function.h b/poincare/include/poincare/trigonometric_function.h index d20bcc877..9a454c887 100644 --- a/poincare/include/poincare/trigonometric_function.h +++ b/poincare/include/poincare/trigonometric_function.h @@ -9,10 +9,9 @@ class TrigonometricFunction : public Function { public: TrigonometricFunction(const char * name); private: - float privateApproximate(Context & context, AngleUnit angleUnit) const override; - Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const override; - virtual float trigonometricApproximation(float x) const = 0; - virtual Expression * createComplexEvaluation(Expression * arg, Context & context, AngleUnit angleUnit) const = 0; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; + virtual float computeForRadianReal(float x) const = 0; + virtual Complex privateCompute(const Complex c, AngleUnit angleUnit) const = 0; }; } diff --git a/poincare/include/poincare/variable_context.h b/poincare/include/poincare/variable_context.h index 90a08db9f..7dd0d9eea 100644 --- a/poincare/include/poincare/variable_context.h +++ b/poincare/include/poincare/variable_context.h @@ -9,8 +9,8 @@ namespace Poincare { class VariableContext : public Context { public: VariableContext(char name, Context * parentContext = nullptr); - void setExpressionForSymbolName(Expression * expression, const Symbol * symbol) override; - const Expression * expressionForSymbol(const Symbol * symbol) override; + void setExpressionForSymbolName(Evaluation * expression, const Symbol * symbol) override; + const Evaluation * expressionForSymbol(const Symbol * symbol) override; private: char m_name; Complex m_value; diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index ae77810a0..9827cbe98 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -26,18 +26,8 @@ Expression * AbsoluteValue::cloneWithDifferentOperands(Expression** newOperands, return a; } -float AbsoluteValue::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - Expression * evaluation = m_args[0]->evaluate(context, angleUnit); - assert(evaluation->type() == Type::Matrix || evaluation->type() == Type::Complex); - float result = 0.0f; - if (evaluation->type() == Type::Matrix) { - result = NAN; - } else { - result = ((Complex *)evaluation)->r(); - } - delete evaluation; - return result; +Complex AbsoluteValue::computeComplex(const Complex c, AngleUnit angleUnit) const { + return Complex::Float(c.r()); } ExpressionLayout * AbsoluteValue::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index ceaad643b..a561ad3f0 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -1,4 +1,5 @@ #include +#include extern "C" { #include #include @@ -16,22 +17,31 @@ Expression::Type Addition::type() const { ExpressionLayout * Addition::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - ExpressionLayout** children_layouts = (ExpressionLayout **)malloc(3*sizeof(ExpressionLayout *)); + ExpressionLayout** children_layouts = new ExpressionLayout * [3]; children_layouts[0] = m_operands[0]->createLayout(floatDisplayMode, complexFormat); children_layouts[1] = new StringLayout("+", 1); children_layouts[2] = m_operands[1]->type() == Type::Opposite ? new ParenthesisLayout(m_operands[1]->createLayout(floatDisplayMode, complexFormat)) : m_operands[1]->createLayout(floatDisplayMode, complexFormat); ExpressionLayout * layout = new HorizontalLayout(children_layouts, 3); - free(children_layouts); + delete[] children_layouts; return layout; } -float Addition::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - return m_operands[0]->approximate(context, angleUnit)+m_operands[1]->approximate(context, angleUnit);; +Complex Addition::compute(const Complex c, const Complex d) { + return Complex::Cartesian(c.a()+d.a(), c.b()+d.b()); +} + +Evaluation * Addition::computeOnMatrices(Evaluation * m, Evaluation * n) { + Addition a; + return a.computeOnNumericalMatrices(m,n); +} + +Evaluation * Addition::computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { + Addition a; + return a.computeOnComplexAndComplexMatrix(c,m); } Expression * Addition::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { + int numberOfOperands, bool cloneOperands) const { return new Addition(newOperands, cloneOperands); } @@ -39,8 +49,4 @@ bool Addition::isCommutative() const { return true; } -Expression * Addition::evaluateOnComplex(Complex * c, Complex * d, Context& context, AngleUnit angleUnit) const { - return new Complex(Complex::Cartesian(c->a()+ d->a(), c->b() + d->b())); -} - } diff --git a/poincare/src/arc_cosine.cpp b/poincare/src/arc_cosine.cpp index b1b08eed1..33062c46d 100644 --- a/poincare/src/arc_cosine.cpp +++ b/poincare/src/arc_cosine.cpp @@ -23,12 +23,16 @@ Expression * ArcCosine::cloneWithDifferentOperands(Expression** newOperands, return c; } -float ArcCosine::privateApproximate(Context& context, AngleUnit angleUnit) const { +Complex ArcCosine::computeComplex(const Complex c, AngleUnit angleUnit) const { assert(angleUnit != AngleUnit::Default); - if (angleUnit == AngleUnit::Degree) { - return acosf(m_args[0]->approximate(context, angleUnit))*180.0f/M_PI; + if (c.b() != 0.0f) { + return Complex::Float(NAN); } - return acosf(m_args[0]->approximate(context, angleUnit)); + float result = acosf(c.a()); + if (angleUnit == AngleUnit::Degree) { + return Complex::Float(result*180.0f/M_PI); + } + return Complex::Float(result); } } diff --git a/poincare/src/arc_sine.cpp b/poincare/src/arc_sine.cpp index dc3de37f2..86a637b95 100644 --- a/poincare/src/arc_sine.cpp +++ b/poincare/src/arc_sine.cpp @@ -23,12 +23,16 @@ Expression * ArcSine::cloneWithDifferentOperands(Expression** newOperands, return s; } -float ArcSine::privateApproximate(Context& context, AngleUnit angleUnit) const { +Complex ArcSine::computeComplex(const Complex c, AngleUnit angleUnit) const { assert(angleUnit != AngleUnit::Default); - if (angleUnit == AngleUnit::Degree) { - return asinf(m_args[0]->approximate(context, angleUnit))*180.0f/M_PI; + if (c.b() != 0.0f) { + return Complex::Float(NAN); } - return asinf(m_args[0]->approximate(context, angleUnit)); + float result = asinf(c.a()); + if (angleUnit == AngleUnit::Degree) { + return Complex::Float(result*180.0f/M_PI); + } + return Complex::Float(result); } } diff --git a/poincare/src/arc_tangent.cpp b/poincare/src/arc_tangent.cpp index 6a9e5c4a2..2334e7295 100644 --- a/poincare/src/arc_tangent.cpp +++ b/poincare/src/arc_tangent.cpp @@ -23,12 +23,16 @@ Expression * ArcTangent::cloneWithDifferentOperands(Expression** newOperands, return t; } -float ArcTangent::privateApproximate(Context& context, AngleUnit angleUnit) const { +Complex ArcTangent::computeComplex(const Complex c, AngleUnit angleUnit) const { assert(angleUnit != AngleUnit::Default); - if (angleUnit == AngleUnit::Degree) { - return atanf(m_args[0]->approximate(context, angleUnit))*180.0f/M_PI; + if (c.b() != 0.0f) { + return Complex::Float(NAN); } - return atanf(m_args[0]->approximate(context, angleUnit)); + float result = atanf(c.a()); + if (angleUnit == AngleUnit::Degree) { + return Complex::Float(result*180.0f/M_PI); + } + return Complex::Float(result); } } diff --git a/poincare/src/binary_operation.cpp b/poincare/src/binary_operation.cpp index be8c965d9..fc243a327 100644 --- a/poincare/src/binary_operation.cpp +++ b/poincare/src/binary_operation.cpp @@ -1,4 +1,5 @@ #include +#include extern "C" { #include #include @@ -7,6 +8,12 @@ extern "C" { namespace Poincare { +BinaryOperation::BinaryOperation() +{ + m_operands[0] = nullptr; + m_operands[1] = nullptr; +} + BinaryOperation::BinaryOperation(Expression ** operands, bool cloneOperands) { assert(operands != nullptr); assert(operands[0] != nullptr); @@ -21,8 +28,12 @@ BinaryOperation::BinaryOperation(Expression ** operands, bool cloneOperands) { } BinaryOperation::~BinaryOperation() { - delete m_operands[1]; - delete m_operands[0]; + if (m_operands[1] != nullptr) { + delete m_operands[1]; + } + if (m_operands[0] != nullptr) { + delete m_operands[0]; + } } bool BinaryOperation::hasValidNumberOfArguments() const { @@ -43,95 +54,51 @@ Expression * BinaryOperation::clone() const { return this->cloneWithDifferentOperands((Expression**) m_operands, 2, true); } -Expression * BinaryOperation::privateEvaluate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - Expression * leftOperandEvalutation = m_operands[0]->evaluate(context, angleUnit); - Expression * rightOperandEvalutation = m_operands[1]->evaluate(context, angleUnit); - Expression * result = nullptr; - switch (leftOperandEvalutation->type()) { - case Type::Complex: - { - switch (rightOperandEvalutation->type()) { - case Type::Complex: - result = evaluateOnComplex((Complex *)leftOperandEvalutation, (Complex *)rightOperandEvalutation, context, angleUnit); - break; - case Type::Matrix: - result = evaluateOnComplexAndMatrix((Complex *)leftOperandEvalutation, (Matrix *)rightOperandEvalutation, context, angleUnit); - break; - default: - result = new Complex(Complex::Float(NAN)); - break; - } - } - break; - case Type::Matrix: - { - switch (rightOperandEvalutation->type()) { - case Type::Complex: - result = evaluateOnMatrixAndComplex((Matrix *)leftOperandEvalutation, (Complex *)rightOperandEvalutation, context, angleUnit); - break; - case Type::Matrix: - result = evaluateOnMatrices((Matrix *)leftOperandEvalutation, (Matrix *)rightOperandEvalutation, context, angleUnit); - break; - default: - result = new Complex(Complex::Float(NAN)); - break; - } - } - break; - default: - result = new Complex(Complex::Float(NAN)); - break; +Evaluation * BinaryOperation::privateEvaluate(Context& context, AngleUnit angleUnit) const { + Evaluation * leftOperandEvalutation = m_operands[0]->evaluate(context, angleUnit); + Evaluation * rightOperandEvalutation = m_operands[1]->evaluate(context, angleUnit); + Evaluation * result = nullptr; + if (leftOperandEvalutation->numberOfRows() == 1 && leftOperandEvalutation->numberOfColumns() == 1 && rightOperandEvalutation->numberOfRows() == 1 && rightOperandEvalutation->numberOfColumns() == 1) { + result = computeOnComplexes(leftOperandEvalutation->complexOperand(0), rightOperandEvalutation->complexOperand(0)); + } else if (leftOperandEvalutation->numberOfRows() == 1 && leftOperandEvalutation->numberOfColumns() == 1) { + result = computeOnComplexAndComplexMatrix(leftOperandEvalutation->complexOperand(0), rightOperandEvalutation); + } else if (rightOperandEvalutation->numberOfRows() == 1 && rightOperandEvalutation->numberOfColumns() == 1) { + result = computeOnComplexMatrixAndComplex(leftOperandEvalutation, rightOperandEvalutation->complexOperand(0)); + } else { + result = computeOnNumericalMatrices(leftOperandEvalutation, rightOperandEvalutation); } delete leftOperandEvalutation; delete rightOperandEvalutation; + if (result == nullptr) { + result = new Complex(Complex::Float(NAN)); + } return result; } -Expression * BinaryOperation::evaluateOnMatrixAndComplex(Matrix * m, Complex * c, Context& context, AngleUnit angleUnit) const { - Expression ** operands = (Expression **)malloc(m->numberOfRows() * m->numberOfColumns()*sizeof(Expression *)); - for (int i = 0; i < m->numberOfRows() * m->numberOfColumns(); i++) { - Expression * evaluation = m->operand(i)->evaluate(context, angleUnit); - assert(evaluation->type() == Type::Matrix || evaluation->type() == Type::Complex); - if (evaluation->type() == Type::Matrix) { - operands[i] = new Complex(Complex::Float(NAN)); - delete evaluation; - continue; - } - operands[i] = evaluateOnComplex((Complex *)evaluation, c, context, angleUnit); - delete evaluation; +Evaluation * BinaryOperation::computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const { + return computeOnComplexMatrixAndComplex(n, c); +} + +Evaluation * BinaryOperation::computeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const { + Complex * operands = new Complex[m->numberOfRows()*m->numberOfColumns()]; + for (int i = 0; i < m->numberOfOperands(); i++) { + operands[i] = privateCompute(*(m->complexOperand(i)), *d); } - Expression * result = new Matrix(operands, m->numberOfRows() * m->numberOfColumns(), m->numberOfColumns(), m->numberOfRows(), false); - free(operands); + Evaluation * result = new ComplexMatrix(operands, m->numberOfRows(), m->numberOfColumns()); + delete[] operands; return result; } -Expression * BinaryOperation::evaluateOnComplexAndMatrix(Complex * c, Matrix * m, Context& context, AngleUnit angleUnit) const { - return evaluateOnMatrixAndComplex(m, c, context, angleUnit); -} - -Expression * BinaryOperation::evaluateOnMatrices(Matrix * m, Matrix * n, Context& context, AngleUnit angleUnit) const { - if (m->numberOfColumns() != n->numberOfColumns() || m->numberOfRows() != n->numberOfRows()) { - return new Complex(Complex::Float(NAN)); +Evaluation * BinaryOperation::computeOnNumericalMatrices(Evaluation * m, Evaluation * n) const { + if (m->numberOfRows() != n->numberOfRows() && m->numberOfColumns() != n->numberOfColumns()) { + return nullptr; } - Expression ** operands = (Expression **)malloc(m->numberOfRows() * m->numberOfColumns()*sizeof(Expression *)); - for (int i = 0; i < m->numberOfRows() * m->numberOfColumns(); i++) { - Expression * mEvaluation = m->operand(i)->evaluate(context, angleUnit); - Expression * nEvaluation = n->operand(i)->evaluate(context, angleUnit); - assert(mEvaluation->type() == Type::Matrix || mEvaluation->type() == Type::Complex); - assert(nEvaluation->type() == Type::Matrix || nEvaluation->type() == Type::Complex); - if (mEvaluation->type() == Type::Matrix ||nEvaluation->type() == Type::Matrix) { - operands[i] = new Complex(Complex::Float(NAN)); - delete mEvaluation; - delete nEvaluation; - continue; - } - operands[i] = evaluateOnComplex((Complex *)mEvaluation, (Complex *)nEvaluation, context, angleUnit); - delete mEvaluation; - delete nEvaluation; + Complex * operands = new Complex[m->numberOfRows()*m->numberOfColumns()]; + for (int i = 0; i < m->numberOfOperands(); i++) { + operands[i] = privateCompute(*(m->complexOperand(i)), *(n->complexOperand(i))); } - Expression * result = new Matrix(operands, m->numberOfRows() * m->numberOfColumns(), m->numberOfColumns(), m->numberOfRows(), false); - free(operands); + Evaluation * result = new ComplexMatrix(operands, m->numberOfRows(), m->numberOfColumns()); + delete[] operands; return result; } diff --git a/poincare/src/binomial_coefficient.cpp b/poincare/src/binomial_coefficient.cpp index 8b3380f34..ca63c81e0 100644 --- a/poincare/src/binomial_coefficient.cpp +++ b/poincare/src/binomial_coefficient.cpp @@ -1,4 +1,5 @@ #include +#include #include #include "layout/parenthesis_layout.h" #include "layout/grid_layout.h" @@ -28,18 +29,21 @@ Expression * BinomialCoefficient::cloneWithDifferentOperands(Expression** newOpe return bc; } -float BinomialCoefficient::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - float n = m_args[0]->approximate(context, angleUnit); - float k = m_args[1]->approximate(context, angleUnit); +Evaluation * BinomialCoefficient::privateEvaluate(Context& context, AngleUnit angleUnit) const { + Evaluation * nInput = m_args[0]->evaluate(context, angleUnit); + Evaluation * kInput = m_args[1]->evaluate(context, angleUnit); + float n = nInput->toFloat(); + float k = kInput->toFloat(); + delete nInput; + delete kInput; if (isnan(n) || isnan(k) || n != (int)n || k != (int)k || k > n || k < 0.0f || n < 0.0f) { - return NAN; + return new Complex(Complex::Float(NAN)); } float result = 1.0f; for (int i = 0; i < (int)k; i++) { result *= (n-(float)i)/(k-(float)i); } - return roundf(result); + return new Complex(Complex::Float(roundf(result))); } ExpressionLayout * BinomialCoefficient::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { diff --git a/poincare/src/ceiling.cpp b/poincare/src/ceiling.cpp index b40a36ba8..75e74e274 100644 --- a/poincare/src/ceiling.cpp +++ b/poincare/src/ceiling.cpp @@ -24,10 +24,11 @@ Expression * Ceiling::cloneWithDifferentOperands(Expression** newOperands, return c; } -float Ceiling::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - float f = m_args[0]->approximate(context, angleUnit); - return ceilf(f); +Complex Ceiling::computeComplex(const Complex c, AngleUnit angleUnit) const { + if (c.b() != 0.0f) { + return Complex::Float(NAN); + } + return Complex::Float(ceilf(c.a())); } } diff --git a/poincare/src/complex.cpp b/poincare/src/complex.cpp index 6679c83c3..96ed47a7e 100644 --- a/poincare/src/complex.cpp +++ b/poincare/src/complex.cpp @@ -6,6 +6,7 @@ extern "C" { #include #include } +#include #include "layout/string_layout.h" #include "layout/baseline_relative_layout.h" #include @@ -56,44 +57,47 @@ Complex::Complex(const char * integralPart, int integralPartLength, bool integra m_b = 0.0f; } -Expression * Complex::clone() const { - return new Complex(Cartesian(m_a, m_b)); -} - -float Complex::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - if (m_b == 0.0f) { - return m_a; +float Complex::toFloat() const { + if (m_b != 0.0f) { + return NAN; } - return NAN; + return m_a; } -Expression * Complex::privateEvaluate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - return clone(); +int Complex::numberOfRows() const { + return 1; +} + +int Complex::numberOfColumns() const { + return 1; } Expression::Type Complex::type() const { return Type::Complex; } -ExpressionLayout * Complex::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != FloatDisplayMode::Default); - if (complexFormat == ComplexFormat::Polar) { - return createPolarLayout(floatDisplayMode); - } - return createCartesianLayout(floatDisplayMode); +Complex * Complex::clone() const { + return new Complex(Cartesian(m_a, m_b)); } -int Complex::writeTextInBuffer(char * buffer, int bufferSize) { +Evaluation * Complex::cloneWithDifferentOperands(Expression** newOperands, + int numberOfOperands, bool cloneOperands) const { + return this->clone(); +} + +int Complex::writeTextInBuffer(char * buffer, int bufferSize) const { return convertComplexToText(buffer, bufferSize, Preferences::sharedPreferences()->displayMode(), Preferences::sharedPreferences()->complexFormat()); } -float Complex::a() { +Evaluation * Complex::createInverse() const { + return new Complex(Cartesian(1.0f/m_a, -1.0f/m_b)); +} + +float Complex::a() const { return m_a; } -float Complex::b() { +float Complex::b() const { return m_b; } @@ -116,8 +120,8 @@ float Complex::th() const { return result; } -Complex * Complex::createConjugate() { - return new Complex(Complex::Cartesian(m_a, -m_b)); +Complex Complex::conjugate() const { + return Complex::Cartesian(m_a, -m_b); } int Complex::convertFloatToText(float f, char * buffer, int bufferSize, @@ -152,6 +156,22 @@ Complex::Complex(float a, float b) : { } +const Complex * Complex::complexOperand(int i) const { + return this; +} + +Evaluation * Complex::privateEvaluate(Context& context, AngleUnit angleUnit) const { + return this->clone(); +} + +ExpressionLayout * Complex::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { + assert(floatDisplayMode != FloatDisplayMode::Default); + if (complexFormat == ComplexFormat::Polar) { + return createPolarLayout(floatDisplayMode); + } + return createCartesianLayout(floatDisplayMode); +} + int Complex::convertComplexToText(char * buffer, int bufferSize, FloatDisplayMode displayMode, ComplexFormat complexFormat) const { assert(displayMode != FloatDisplayMode::Default); int numberOfChars = 0; diff --git a/poincare/src/complex_argument.cpp b/poincare/src/complex_argument.cpp index 3010ea71c..ba3f24eaf 100644 --- a/poincare/src/complex_argument.cpp +++ b/poincare/src/complex_argument.cpp @@ -25,18 +25,8 @@ Expression * ComplexArgument::cloneWithDifferentOperands(Expression** newOperand return ca; } -float ComplexArgument::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - Expression * evaluation = m_args[0]->evaluate(context, angleUnit); - assert(evaluation->type() == Type::Matrix || evaluation->type() == Type::Complex); - float result = 0.0f; - if (evaluation->type() == Type::Matrix) { - result = NAN; - } else { - result = ((Complex *)evaluation)->th(); - } - delete evaluation; - return result; +Complex ComplexArgument::computeComplex(const Complex c, AngleUnit angleUnit) const { + return Complex::Float(c.th()); } } diff --git a/poincare/src/complex_matrix.cpp b/poincare/src/complex_matrix.cpp new file mode 100644 index 000000000..23912627f --- /dev/null +++ b/poincare/src/complex_matrix.cpp @@ -0,0 +1,78 @@ +extern "C" { +#include +#include +} +#include +#include +#include "layout/grid_layout.h" +#include "layout/bracket_layout.h" +#include +#include +#include + +namespace Poincare { + +ComplexMatrix::ComplexMatrix(const Complex * complexes, int numberOfRows, int numberOfColumns) : + m_numberOfRows(numberOfRows), + m_numberOfColumns(numberOfColumns) +{ + assert(complexes != nullptr); + m_values = new Complex[numberOfColumns*numberOfRows]; + for (int i = 0; i < numberOfColumns*numberOfRows; i++) { + m_values[i] = complexes[i]; + } +} + +ComplexMatrix::~ComplexMatrix() { + delete[] m_values; +} + +float ComplexMatrix::toFloat() const { + if (m_numberOfColumns != 1 || m_numberOfRows != 1) { + return NAN; + } + if (m_values[0].b() != 0.0f) { + return NAN; + } + return m_values[0].a(); +} + +int ComplexMatrix::numberOfRows() const { + return m_numberOfRows; +} + +int ComplexMatrix::numberOfColumns() const { + return m_numberOfColumns; +} + +const Complex * ComplexMatrix::complexOperand(int i) const { + return &m_values[i]; +} + +ComplexMatrix * ComplexMatrix::clone() const { + return this->cloneWithDifferentOperands((Expression **)&m_values, m_numberOfRows*m_numberOfColumns); +} + +ComplexMatrix * ComplexMatrix::cloneWithDifferentOperands(Expression** newOperands, + int numberOfOperands, bool cloneOperands) const { + assert(newOperands != nullptr); + return new ComplexMatrix((Complex *)newOperands[0], m_numberOfColumns, m_numberOfRows); +} + +Evaluation * ComplexMatrix::createIdentity(int dim) { + Complex * operands = new Complex [dim*dim]; + for (int i = 0; i < dim; i++) { + for (int j = 0; j < dim; j++) { + if (i == j) { + operands[i*dim+j] = Complex(Complex::Float(1.0)); + } else { + operands[i*dim+j] = Complex(Complex::Float(0.0)); + } + } + } + Evaluation * matrix = new ComplexMatrix(operands, dim, dim); + delete [] operands; + return matrix; +} + +} diff --git a/poincare/src/confidence_interval.cpp b/poincare/src/confidence_interval.cpp index 7158b28d3..f17ef57a9 100644 --- a/poincare/src/confidence_interval.cpp +++ b/poincare/src/confidence_interval.cpp @@ -1,5 +1,6 @@ #include #include +#include extern "C" { #include #include @@ -24,19 +25,20 @@ Expression * ConfidenceInterval::cloneWithDifferentOperands(Expression** newOper return ci; } -float ConfidenceInterval::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - return NAN; -} - -Expression * ConfidenceInterval::privateEvaluate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - float f = m_args[0]->approximate(context, angleUnit); - float n = m_args[1]->approximate(context, angleUnit); - Expression * operands[2]; - operands[0] = new Complex(Complex::Float(f - 1.0f/sqrtf(n))); - operands[1] = new Complex(Complex::Float(f + 1.0f/sqrtf(n))); - return new Matrix(new MatrixData(operands, 2, 2, 1, false)); +Evaluation * ConfidenceInterval::privateEvaluate(Context& context, AngleUnit angleUnit) const { + Evaluation * fInput = m_args[0]->evaluate(context, angleUnit); + Evaluation * nInput = m_args[1]->evaluate(context, angleUnit); + float f = fInput->toFloat(); + float n = nInput->toFloat(); + delete fInput; + delete nInput; + if (isnan(f) || isnan(n) || n != (int)n || n < 0.0f || f < 0.0f || f > 1.0f) { + return new Complex(Complex::Float(NAN)); + } + Complex operands[2]; + operands[0] = Complex::Float(f - 1.0f/sqrtf(n)); + operands[1] = Complex::Float(f + 1.0f/sqrtf(n)); + return new ComplexMatrix(operands, 2, 1); } } diff --git a/poincare/src/conjugate.cpp b/poincare/src/conjugate.cpp index 40c387ef3..aab872d61 100644 --- a/poincare/src/conjugate.cpp +++ b/poincare/src/conjugate.cpp @@ -26,22 +26,8 @@ Expression * Conjugate::cloneWithDifferentOperands(Expression** newOperands, return c; } -float Conjugate::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - return m_args[0]->approximate(context, angleUnit); -} - -Expression * Conjugate::privateEvaluate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - Expression * evaluation = m_args[0]->evaluate(context, angleUnit); - assert(evaluation->type() == Type::Matrix || evaluation->type() == Type::Complex); - if (evaluation->type() == Type::Matrix) { - delete evaluation; - return new Complex(Complex::Float(NAN)); - } - Expression * result = ((Complex *)evaluation)->createConjugate(); - delete evaluation; - return result; +Complex Conjugate::computeComplex(const Complex c, AngleUnit angleUnit) const { + return c.conjugate(); } ExpressionLayout * Conjugate::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { diff --git a/poincare/src/cosine.cpp b/poincare/src/cosine.cpp index 84eef7922..f7baa3f30 100644 --- a/poincare/src/cosine.cpp +++ b/poincare/src/cosine.cpp @@ -25,19 +25,13 @@ Expression * Cosine::cloneWithDifferentOperands(Expression** newOperands, return c; } -float Cosine::trigonometricApproximation(float x) const { +Complex Cosine::compute(const Complex c) { + Complex arg = Complex::Cartesian(-c.b(), c.a()); + return HyperbolicCosine::compute(arg); +} + +float Cosine::computeForRadianReal(float x) const { return cosf(x); } -Expression * Cosine::createComplexEvaluation(Expression * exp, Context & context, AngleUnit angleUnit) const { - assert(exp->type() == Type::Complex); - Expression * arg = new Complex(Complex::Cartesian(-((Complex *)exp)->b(), ((Complex *)exp)->a())); - Function * cosh = new HyperbolicCosine(); - cosh->setArgument(&arg, 1, true); - delete arg; - Expression * resultEvaluation = cosh->evaluate(context, angleUnit); - delete cosh; - return resultEvaluation; -} - } diff --git a/poincare/src/derivative.cpp b/poincare/src/derivative.cpp index cf5a4503a..c2856771d 100644 --- a/poincare/src/derivative.cpp +++ b/poincare/src/derivative.cpp @@ -27,18 +27,21 @@ Expression * Derivative::cloneWithDifferentOperands(Expression** newOperands, return d; } -float Derivative::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); +Evaluation * Derivative::privateEvaluate(Context& context, AngleUnit angleUnit) const { VariableContext xContext = VariableContext('x', &context); Symbol xSymbol = Symbol('x'); - float x = m_args[1]->approximate(context, angleUnit); + Evaluation * xInput = m_args[1]->evaluate(context, angleUnit); + float x = xInput->toFloat(); + delete xInput; Complex e = Complex::Float(x); xContext.setExpressionForSymbolName(&e, &xSymbol); - float functionValue = m_args[0]->approximate(xContext, angleUnit); + Evaluation * fInput = m_args[1]->evaluate(xContext, angleUnit); + float functionValue = fInput->toFloat(); + delete fInput; // No complex/matrix version of Derivative if (isnan(x) || isnan(functionValue)) { - return NAN; + return new Complex(Complex::Float(NAN)); } /* Ridders' Algorithm @@ -96,23 +99,27 @@ float Derivative::privateApproximate(Context& context, AngleUnit angleUnit) cons } /* if the error is too big regarding the value, do not return the answer */ if (err/ans > k_maxErrorRateOnApproximation || isnan(err)) { - return NAN; + return new Complex(Complex::Float(NAN)); } if (err < FLT_MIN) { - return ans; + return new Complex(Complex::Float(ans)); } err = powf(10.0f, (int)log10f(fabsf(err))+2.0f); - return roundf(ans/err)*err; + return new Complex(Complex::Float(roundf(ans/err)*err)); } float Derivative::growthRateAroundAbscissa(float x, float h, VariableContext xContext, AngleUnit angleUnit) const { Symbol xSymbol = Symbol('x'); Complex e = Complex::Float(x + h); xContext.setExpressionForSymbolName(&e, &xSymbol); - float expressionPlus = m_args[0]->approximate(xContext, angleUnit); + Evaluation * fInput = m_args[0]->evaluate(xContext, angleUnit); + float expressionPlus = fInput->toFloat(); + delete fInput; e = Complex::Float(x-h); xContext.setExpressionForSymbolName(&e, &xSymbol); - float expressionMinus = m_args[0]->approximate(xContext, angleUnit); + fInput = m_args[0]->evaluate(xContext, angleUnit); + float expressionMinus = fInput->toFloat(); + delete fInput; return (expressionPlus - expressionMinus)/(2*h); } @@ -120,13 +127,19 @@ float Derivative::approximateDerivate2(float x, float h, VariableContext xContex Symbol xSymbol = Symbol('x'); Complex e = Complex::Float(x + h); xContext.setExpressionForSymbolName(&e, &xSymbol); - float expressionPlus = m_args[0]->approximate(xContext, angleUnit); + Evaluation * fInput = m_args[0]->evaluate(xContext, angleUnit); + float expressionPlus = fInput->toFloat(); + delete fInput; e = Complex::Float(x); xContext.setExpressionForSymbolName(&e, &xSymbol); - float expression = m_args[0]->approximate(xContext, angleUnit); + fInput = m_args[0]->evaluate(xContext, angleUnit); + float expression = fInput->toFloat(); + delete fInput; e = Complex::Float(x-h); xContext.setExpressionForSymbolName(&e, &xSymbol); - float expressionMinus = m_args[0]->approximate(xContext, angleUnit); + fInput = m_args[0]->evaluate(xContext, angleUnit); + float expressionMinus = fInput->toFloat(); + delete fInput; return expressionPlus - 2.0f*expression + expressionMinus; } diff --git a/poincare/src/determinant.cpp b/poincare/src/determinant.cpp index 1456f5cda..0a46eb5e9 100644 --- a/poincare/src/determinant.cpp +++ b/poincare/src/determinant.cpp @@ -24,18 +24,11 @@ Expression * Determinant::cloneWithDifferentOperands(Expression** newOperands, return d; } -float Determinant::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - Expression * evaluation = m_args[0]->evaluate(context, angleUnit); - assert(evaluation->type() == Type::Matrix || evaluation->type() == Type::Complex); - if (evaluation->type() == Type::Complex) { - float result = evaluation->approximate(context, angleUnit); - delete evaluation; - return result; - } - float det = ((Matrix *)evaluation)->determinant(context, angleUnit); - delete evaluation; - return det; +Evaluation * Determinant::privateEvaluate(Context& context, AngleUnit angleUnit) const { + Evaluation * input = m_args[0]->evaluate(context, angleUnit); + Evaluation * result = input->createDeterminant(); + delete input; + return result; } } diff --git a/poincare/src/division_quotient.cpp b/poincare/src/division_quotient.cpp index 4ac7cf42a..c54328266 100644 --- a/poincare/src/division_quotient.cpp +++ b/poincare/src/division_quotient.cpp @@ -24,14 +24,17 @@ Expression * DivisionQuotient::cloneWithDifferentOperands(Expression** newOperan return dq; } -float DivisionQuotient::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - float f1 = m_args[0]->approximate(context, angleUnit); - float f2 = m_args[1]->approximate(context, angleUnit); +Evaluation * DivisionQuotient::privateEvaluate(Context & context, AngleUnit angleUnit) const { + Evaluation * f1Input = m_args[0]->evaluate(context, angleUnit); + Evaluation * f2Input = m_args[1]->evaluate(context, angleUnit); + float f1 = f1Input->toFloat(); + float f2 = f2Input->toFloat(); + delete f1Input; + delete f2Input; if (isnan(f1) || isnan(f2) || f1 != (int)f1 || f2 != (int)f2) { - return NAN; + return new Complex(Complex::Float(NAN)); } - return floorf(f1/f2); + return new Complex(Complex::Float(floorf(f1/f2))); } } diff --git a/poincare/src/division_remainder.cpp b/poincare/src/division_remainder.cpp index 79f3ea788..ed57de154 100644 --- a/poincare/src/division_remainder.cpp +++ b/poincare/src/division_remainder.cpp @@ -24,14 +24,17 @@ Expression * DivisionRemainder::cloneWithDifferentOperands(Expression** newOpera return dr; } -float DivisionRemainder::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - float f1 = m_args[0]->approximate(context, angleUnit); - float f2 = m_args[1]->approximate(context, angleUnit); +Evaluation * DivisionRemainder::privateEvaluate(Context & context, AngleUnit angleUnit) const { + Evaluation * f1Input = m_args[0]->evaluate(context, angleUnit); + Evaluation * f2Input = m_args[1]->evaluate(context, angleUnit); + float f1 = f1Input->toFloat(); + float f2 = f2Input->toFloat(); + delete f1Input; + delete f2Input; if (isnan(f1) || isnan(f2) || f1 != (int)f1 || f2 != (int)f2) { - return NAN; + return new Complex(Complex::Float(NAN)); } - return roundf(f1-f2*floorf(f1/f2)); + return new Complex(Complex::Float(roundf(f1-f2*floorf(f1/f2)))); } } diff --git a/poincare/src/evaluation.cpp b/poincare/src/evaluation.cpp new file mode 100644 index 000000000..c40148d86 --- /dev/null +++ b/poincare/src/evaluation.cpp @@ -0,0 +1,194 @@ +#include +extern "C" { +#include +#include +} +#include +#include +#include +#include "layout/grid_layout.h" +#include "layout/bracket_layout.h" +#include +#include +#include + +namespace Poincare { + +Expression::Type Evaluation::type() const { + return Type::Evaluation; +} + +bool Evaluation::hasValidNumberOfArguments() const { + return true; +} + +const Expression * Evaluation::operand(int i) const { + return complexOperand(i); +} + +Evaluation * Evaluation::privateEvaluate(Context& context, AngleUnit angleUnit) const { + assert(false); + return this->clone(); +} + +Evaluation * Evaluation::createTrace() const { + if (numberOfColumns() != numberOfRows()) { + return new Complex(Complex::Float(NAN)); + } + int dim = numberOfRows(); + Complex c = Complex::Float(0.0f); + for (int i = 0; i < dim; i++) { + c = Addition::compute(c, *complexOperand(i*dim+i)); + } + return new Complex(c); +} + +// TODO: implement determinant for complex matrix? +Evaluation * Evaluation::createDeterminant() const { + if (numberOfColumns() != numberOfRows()) { + return new Complex(Complex::Float(NAN)); + } + int dim = numberOfRows(); + float ** tempMat = new float*[dim]; + for (int i = 0; i < dim; i++) { + tempMat[i] = new float[dim]; + } + float det = 1.0f; + /* Copy the matrix */ + for (int i = 0; i < dim; i++) { + for (int j = 0; j < dim; j++) { + tempMat[i][j] = complexOperand(i*dim+ j)->toFloat(); + } + } + + /* Main Loop: Gauss pivot */ + for (int i = 0; i < dim-1; i++) { + /* Search for pivot */ + int rowWithPivot = i; + for (int row = i+1; row < dim; row++) { + if (fabsf(tempMat[rowWithPivot][i]) < fabsf(tempMat[row][i])) { + rowWithPivot = row; + } + } + float valuePivot = tempMat[rowWithPivot][i]; + /* if the pivot is null, det = 0. */ + if (fabsf(valuePivot) <= FLT_EPSILON) { + for (int i = 0; i < dim; i++) { + free(tempMat[i]); + } + free(tempMat); + return new Complex(Complex::Float(0.0f)); + } + /* Switch rows to have the pivot row as first row */ + if (rowWithPivot != i) { + for (int col = i; col < dim; col++) { + float temp = tempMat[i][col]; + tempMat[i][col] = tempMat[rowWithPivot][col]; + tempMat[rowWithPivot][col] = temp; + } + det *= -1; + } + det *= valuePivot; + /* Set to 0 all A[][i] by linear combination */ + for (int row = i+1; row < dim; row++) { + float factor = tempMat[row][i]/valuePivot; + for (int col = i; col < dim; col++) { + tempMat[row][col] -= factor*tempMat[i][col]; + } + } + } + det *= tempMat[dim-1][dim-1]; + for (int i = 0; i < dim; i++) { + delete[] tempMat[i]; + } + delete[] tempMat; + return new Complex(Complex::Float(det)); +} + +Evaluation * Evaluation::createInverse() const { + if (numberOfColumns() != numberOfRows()) { + return new Complex(Complex::Float(NAN)); + } + int dim = numberOfRows(); + /* Create the matrix inv = (A|I) with A the input matrix and I the dim identity matrix */ + float ** inv = new float*[dim]; + for (int i = 0; i < dim; i++) { + inv[i] = new float [2*dim]; + } + for (int i = 0; i < dim; i++) { + for (int j = 0; j < dim; j++) { + inv[i][j] = complexOperand(i*dim+j)->toFloat(); + } + for (int j = dim; j < 2*dim; j++) { + inv[i][j] = (i+dim == j); + } + } + /* Main Loop: Gauss pivot */ + for (int i = 0; i < dim; i++) { + /* Search for pivot */ + int rowWithPivot = i; + for (int row = i+1; row < dim; row++) { + if (fabsf(inv[rowWithPivot][i]) < fabsf(inv[row][i])) { + rowWithPivot = row; + } + } + float valuePivot = inv[rowWithPivot][i]; + /* if the pivot is null, the matrix in not invertible. */ + if (fabsf(valuePivot) <= FLT_EPSILON) { + for (int i = 0; i < dim; i++) { + free(inv[i]); + } + free(inv); + return new Complex(Complex::Float(NAN)); + } + /* Switch rows to have the pivot row as first row */ + if (rowWithPivot != i) { + for (int col = i; col < 2*dim; col++) { + float temp = inv[i][col]; + inv[i][col] = inv[rowWithPivot][col]; + inv[rowWithPivot][col] = temp; + } + } + /* A[pivot][] = A[pivot][]/valuePivot */ + for (int col = 0; col < 2*dim; col++) { + inv[i][col] /= valuePivot; + } + /* Set to 0 all A[][row] by linear combination */ + for (int row = 0; row < dim; row++) { + if (row == i) { + continue; + } + float factor = inv[row][i]; + for (int col = 0; col < 2*dim; col++) { + inv[row][col] -= factor*inv[i][col]; + } + } + } + Complex * operands = new Complex[numberOfOperands()]; + for (int i = 0; i < dim; i++) { + for (int j = 0; j < dim; j++) { + operands[i*dim+j] = Complex(Complex::Float(inv[i][j+dim])); + } + } + for (int i = 0; i < dim; i++) { + delete[] inv[i]; + } + delete[] inv; + Evaluation * matrix = new ComplexMatrix(operands, numberOfColumns(), numberOfRows()); + delete[] operands; + return matrix; +} + +Evaluation * Evaluation::createTranspose() const { + Complex * operands = new Complex[numberOfOperands()]; + for (int i = 0; i < numberOfRows(); i++) { + for (int j = 0; j < numberOfColumns(); j++) { + operands[j*numberOfRows()+i] = *(complexOperand(i*numberOfColumns()+j)); + } + } + Evaluation * matrix = new ComplexMatrix(operands, numberOfRows(), numberOfColumns()); + delete[] operands; + return matrix; +} + +} diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 4564f1bc2..55a157ccb 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "expression_parser.hpp" #include "expression_lexer.hpp" extern "C" { @@ -57,7 +58,7 @@ ExpressionLayout * Expression::createLayout(FloatDisplayMode floatDisplayMode, C } } -Expression * Expression::evaluate(Context& context, AngleUnit angleUnit) const { +Evaluation * Expression::evaluate(Context& context, AngleUnit angleUnit) const { switch (angleUnit) { case AngleUnit::Default: return privateEvaluate(context, Preferences::sharedPreferences()->angleUnit()); @@ -67,21 +68,21 @@ Expression * Expression::evaluate(Context& context, AngleUnit angleUnit) const { } float Expression::approximate(Context& context, AngleUnit angleUnit) const { - switch (angleUnit) { - case AngleUnit::Default: - return privateApproximate(context, Preferences::sharedPreferences()->angleUnit()); - default: - return privateApproximate(context, angleUnit); - } + Evaluation * evaluation = evaluate(context, angleUnit); + float result = evaluation->toFloat(); + delete evaluation; + return result; } float Expression::approximate(const char * text, Context& context, AngleUnit angleUnit) { Expression * exp = parse(text); - float result = NAN; - if (exp != nullptr) { - result = exp->approximate(context, angleUnit); - delete exp; + if (exp == nullptr) { + return NAN; } + Evaluation * evaluation = exp->evaluate(context, angleUnit); + delete exp; + float result = evaluation->toFloat(); + delete evaluation; return result; } @@ -103,7 +104,7 @@ Expression * Expression::simplify() const { /* We recursively simplify the children expressions. * Note that we are sure to get the samne number of children as we had before */ - Expression ** simplifiedOperands = (Expression**) malloc(result->numberOfOperands() * sizeof(Expression*)); + Expression ** simplifiedOperands = new Expression * [result->numberOfOperands()]; for (int i = 0; i < result->numberOfOperands(); i++) { simplifiedOperands[i] = result->operand(i)->simplify(); } @@ -115,7 +116,7 @@ Expression * Expression::simplify() const { result = tmp; // The table is no longer needed. - free(simplifiedOperands); + delete [] simplifiedOperands; simplification_pass_was_useful = false; for (int i=0; inumberOfOperands() * sizeof(bool)); + bool * operandMatched = new bool [this->numberOfOperands()]; for (int i(0); inumberOfOperands(); i++) { operandMatched[i] = false; } @@ -188,7 +189,7 @@ bool Expression::commutativeOperandsIdentity(const Expression * e) const { // We call our recursive helper. bool commutativelyIdentical = this->combinatoryCommutativeOperandsIdentity(e, operandMatched, leftToMatch); - free(operandMatched); + delete [] operandMatched; return commutativelyIdentical; } @@ -229,7 +230,7 @@ bool Expression::isCommutative() const { return false; } -int Expression::writeTextInBuffer(char * buffer, int bufferSize) { +int Expression::writeTextInBuffer(char * buffer, int bufferSize) const { return 0; } diff --git a/poincare/src/expression_matrix.cpp b/poincare/src/expression_matrix.cpp new file mode 100644 index 000000000..61f9487c5 --- /dev/null +++ b/poincare/src/expression_matrix.cpp @@ -0,0 +1,87 @@ +extern "C" { +#include +#include +} +#include +#include +#include +#include +#include +#include + +namespace Poincare { + +ExpressionMatrix::ExpressionMatrix(MatrixData * matrixData) : + m_matrixData(matrixData) +{ +} + +ExpressionMatrix::ExpressionMatrix(Expression ** newOperands, int numberOfOperands, int numberOfColumns, int numberOfRows, bool cloneOperands) +{ + m_matrixData = new MatrixData(newOperands, numberOfOperands, numberOfColumns, numberOfRows, cloneOperands); +} + +ExpressionMatrix::~ExpressionMatrix() { + delete m_matrixData; +} + +bool ExpressionMatrix::hasValidNumberOfArguments() const { + for (int i = 0; i < numberOfOperands(); i++) { + if (!operand(i)->hasValidNumberOfArguments()) { + return false; + } + } + return true; +} + + +int ExpressionMatrix::numberOfRows() const { + return m_matrixData->numberOfRows(); +} + +int ExpressionMatrix::numberOfColumns() const { + return m_matrixData->numberOfColumns(); +} + +const Expression * ExpressionMatrix::operand(int i) const { + assert(i >= 0); + assert(i < numberOfOperands()); + return m_matrixData->operands()[i]; +} + +Expression * ExpressionMatrix::clone() const { + return this->cloneWithDifferentOperands(m_matrixData->operands(), numberOfOperands(), true); +} + +Expression::Type ExpressionMatrix::type() const { + return Type::ExpressionMatrix; +} + +Expression * ExpressionMatrix::cloneWithDifferentOperands(Expression** newOperands, + int numberOfOperands, bool cloneOperands) const { + assert(newOperands != nullptr); + return new ExpressionMatrix(newOperands, numberOfOperands, numberOfColumns(), numberOfRows(), cloneOperands); +} + +Evaluation * ExpressionMatrix::privateEvaluate(Context& context, AngleUnit angleUnit) const { + Complex * operands = new Complex[numberOfOperands()]; + for (int i = 0; i < numberOfOperands(); i++) { + Evaluation * operandEvaluation = operand(i)->evaluate(context, angleUnit); + if (operandEvaluation->numberOfOperands() != 1) { + operands[i] = Complex::Float(NAN); + } else { + operands[i] = *(operandEvaluation->complexOperand(0)); + } + delete operandEvaluation; + } + Evaluation * matrix = new ComplexMatrix(operands, numberOfRows(), numberOfColumns()); + delete[] operands; + return matrix; +} + +Complex * ExpressionMatrix::defaultExpression() { + static Complex * defaultExpression = new Complex(Complex::Float(0.0f)); + return defaultExpression; +} + +} diff --git a/poincare/src/expression_parser.y b/poincare/src/expression_parser.y index 56197c0ef..b8768ab46 100644 --- a/poincare/src/expression_parser.y +++ b/poincare/src/expression_parser.y @@ -180,7 +180,7 @@ exp: | MINUS exp %prec UNARY_MINUS { $$ = new Poincare::Opposite($2, false); } | LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { $$ = new Poincare::Parenthesis($2, false); } /* MATRICES_ARE_DEFINED */ - | LEFT_BRACKET mtxData RIGHT_BRACKET { $$ = new Poincare::Matrix($2); } + | LEFT_BRACKET mtxData RIGHT_BRACKET { $$ = new Poincare::ExpressionMatrix($2); } | FUNCTION LEFT_PARENTHESIS lstData RIGHT_PARENTHESIS { $$ = $1; $1->setArgument($3, true); delete $3; } final_exp: diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index 2a60f1cfc..c5b32daac 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -25,20 +25,20 @@ Expression * Factorial::cloneWithDifferentOperands(Expression** newOperands, return f; } -float Factorial::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - float n = m_args[0]->approximate(context, angleUnit); - if (isnan(n) || n != (int)n || n < 0.0f) { - return NAN; +Complex Factorial::computeComplex(const Complex c, AngleUnit angleUnit) const { + float n = c.a(); + if (c.b() != 0.0f || isnan(n) || n != (int)n || n < 0.0f) { + return Complex::Float(NAN); } + return Complex::Float(c.r()); float result = 1.0f; for (int i = 1; i <= (int)n; i++) { result *= (float)i; if (isinf(result)) { - return result; + return Complex::Float(result); } } - return roundf(result); + return Complex::Float(roundf(result)); } ExpressionLayout * Factorial::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { diff --git a/poincare/src/floor.cpp b/poincare/src/floor.cpp index 6486e5c75..788c930c2 100644 --- a/poincare/src/floor.cpp +++ b/poincare/src/floor.cpp @@ -24,10 +24,11 @@ Expression * Floor::cloneWithDifferentOperands(Expression** newOperands, return f; } -float Floor::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - float f = m_args[0]->approximate(context, angleUnit); - return floorf(f); +Complex Floor::computeComplex(const Complex c, AngleUnit angleUnit) const { + if (c.b() != 0.0f) { + return Complex::Float(NAN); + } + return Complex::Float(floorf(c.a())); } } diff --git a/poincare/src/frac_part.cpp b/poincare/src/frac_part.cpp index 28bafd79c..464a5794e 100644 --- a/poincare/src/frac_part.cpp +++ b/poincare/src/frac_part.cpp @@ -24,10 +24,11 @@ Expression * FracPart::cloneWithDifferentOperands(Expression** newOperands, return fp; } -float FracPart::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - float f = m_args[0]->approximate(context, angleUnit); - return f-floorf(f); +Complex FracPart::computeComplex(const Complex c, AngleUnit angleUnit) const { + if (c.b() != 0.0f) { + return Complex::Float(NAN); + } + return Complex::Float(c.a()-floorf(c.a())); } } diff --git a/poincare/src/fraction.cpp b/poincare/src/fraction.cpp index ed2bb0912..bd499642c 100644 --- a/poincare/src/fraction.cpp +++ b/poincare/src/fraction.cpp @@ -23,46 +23,37 @@ ExpressionLayout * Fraction::privateCreateLayout(FloatDisplayMode floatDisplayMo return new FractionLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat), m_operands[1]->createLayout(floatDisplayMode, complexFormat)); } -float Fraction::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - return m_operands[0]->approximate(context, angleUnit)/m_operands[1]->approximate(context, angleUnit); -} - Expression::Type Fraction::type() const { return Type::Fraction; } -Expression * Fraction::evaluateOnComplex(Complex * c, Complex * d, Context& context, AngleUnit angleUnit) const { - float norm = d->a()*d->a() + d->b()*d->b(); +Complex Fraction::compute(const Complex c, const Complex d) { + float norm = d.a()*d.a() + d.b()*d.b(); /* We handle the case of c and d pure real numbers apart. Even if the complex * fraction is mathematically correct on real numbers, it requires more * operations and is thus more likely to propagate errors due to float exact * representation. */ - if (d->b() == 0.0f && c->b() == 0.0f) { - return new Complex(Complex::Float(c->a()/d->a())); + if (d.b() == 0.0f && c.b() == 0.0f) { + return Complex::Float(c.a()/d.a()); } - return new Complex(Complex::Cartesian((c->a()*d->a()+c->b()*d->b())/norm, (d->a()*c->b()-c->a()*d->b())/norm)); + return Complex::Cartesian((c.a()*d.a()+c.b()*d.b())/norm, (d.a()*c.b()-c.a()*d.b())/norm); } -Expression * Fraction::evaluateOnComplexAndMatrix(Complex * c, Matrix * m, Context& context, AngleUnit angleUnit) const { - return new Complex(Complex::Float(NAN)); +Evaluation * Fraction::computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * m) const { + Evaluation * inverse = m->createInverse(); + Evaluation * result = Multiplication::computeOnComplexAndMatrix(c, inverse); + delete inverse; + return result; } -Expression * Fraction::evaluateOnMatrices(Matrix * m, Matrix * n, Context& context, AngleUnit angleUnit) const { +Evaluation * Fraction::computeOnNumericalMatrices(Evaluation * m, Evaluation * n) const { if (m->numberOfColumns() != n->numberOfColumns()) { - return new Complex(Complex::Float(NAN)); + return nullptr; } - if (fabsf(n->determinant(context, angleUnit)) <= FLT_EPSILON) { - return new Complex(Complex::Float(NAN)); - } - Expression * args[2]; - args[0] = m; - args[1] = n->createInverse(context, angleUnit); - Expression * result = new Multiplication(args, true); - delete args[1]; - Expression * resultEvaluation = result->evaluate(context, angleUnit); - delete result; - return resultEvaluation; + Evaluation * inverse = n->createInverse(); + Evaluation * result = Multiplication::computeOnMatrices(m, inverse); + delete inverse; + return result; } } diff --git a/poincare/src/function.cpp b/poincare/src/function.cpp index 4c334cfb9..970207173 100644 --- a/poincare/src/function.cpp +++ b/poincare/src/function.cpp @@ -19,49 +19,15 @@ Function::Function(const char * name, int requiredNumberOfArguments) : } void Function::setArgument(Expression ** args, int numberOfArguments, bool clone) { - if (m_args != nullptr) { - for (int i = 0; i < m_numberOfArguments; i++) { - delete m_args[i]; - } - free(m_args); - } - m_numberOfArguments = numberOfArguments; - m_args = (Expression **)malloc(numberOfArguments*sizeof(Expression *)); - for (int i = 0; i < numberOfArguments; i++) { - assert(args[i] != nullptr); - if (clone) { - m_args[i] = args[i]->clone(); - } else { - m_args[i] = args[i]; - } - } + build(args, numberOfArguments, clone); } void Function::setArgument(ListData * listData, bool clone) { - if (m_args != nullptr) { - for (int i = 0; i < m_numberOfArguments; i++) { - delete m_args[i]; - } - free(m_args); - } - m_numberOfArguments = listData->numberOfOperands(); - m_args = (Expression **)malloc(m_numberOfArguments*sizeof(Expression *)); - for (int i = 0; i < m_numberOfArguments; i++) { - if (clone) { - m_args[i] = (Expression *)listData->operand(i)->clone(); - } else { - m_args[i] = (Expression *)listData->operand(i); - } - } + build(listData->operands(), listData->numberOfOperands(), clone); } Function::~Function() { - if (m_args != nullptr) { - for (int i = 0; i < m_numberOfArguments; i++) { - delete m_args[i]; - } - free(m_args); - } + clean(); } bool Function::hasValidNumberOfArguments() const { @@ -76,28 +42,6 @@ bool Function::hasValidNumberOfArguments() const { return true; } -Expression * Function::clone() const { - return this->cloneWithDifferentOperands(m_args, m_numberOfArguments, true); -} - -ExpressionLayout * Function::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != FloatDisplayMode::Default); - assert(complexFormat != ComplexFormat::Default); - ExpressionLayout ** grandChildrenLayouts = (ExpressionLayout **)malloc((2*m_numberOfArguments-1)*sizeof(ExpressionLayout *)); - int layoutIndex = 0; - grandChildrenLayouts[layoutIndex++] = m_args[0]->createLayout(floatDisplayMode, complexFormat); - for (int i = 1; i < m_numberOfArguments; i++) { - grandChildrenLayouts[layoutIndex++] = new StringLayout(",", 1); - grandChildrenLayouts[layoutIndex++] = m_args[i]->createLayout(floatDisplayMode, complexFormat); - } - ExpressionLayout * argumentLayouts = new HorizontalLayout(grandChildrenLayouts, 2*m_numberOfArguments-1); - free(grandChildrenLayouts); - ExpressionLayout * childrenLayouts[2]; - childrenLayouts[0] = new StringLayout(m_name, strlen(m_name)); - childrenLayouts[1] = new ParenthesisLayout(argumentLayouts); - return new HorizontalLayout(childrenLayouts, 2); -} - const Expression * Function::operand(int i) const { assert(i >= 0 && i < m_numberOfArguments); return m_args[i]; @@ -107,10 +51,73 @@ int Function::numberOfOperands() const { return m_numberOfArguments; } -Expression * Function::privateEvaluate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - /* Default function evaluation works for reel function */ - return new Complex(Complex::Float(approximate(context, angleUnit))); +Expression * Function::clone() const { + return this->cloneWithDifferentOperands(m_args, m_numberOfArguments, true); +} + +Complex Function::computeComplex(const Complex c, AngleUnit angleUnit) const { + return Complex::Float(NAN); +} + +Evaluation * Function::privateEvaluate(Context& context, AngleUnit angleUnit) const { + if (m_numberOfArguments != 1) { + return new Complex(Complex::Float(NAN)); + } + Evaluation * input = m_args[0]->evaluate(context, angleUnit); + Complex * operands = new Complex[input->numberOfRows()*input->numberOfColumns()]; + for (int i = 0; i < input->numberOfOperands(); i++) { + operands[i] = computeComplex(*input->complexOperand(i), angleUnit); + } + Evaluation * result = nullptr; + if (input->numberOfOperands() == 1) { + result = new Complex(operands[0]); + } else { + result = new ComplexMatrix(operands, input->numberOfRows(), input->numberOfColumns()); + } + delete input; + delete[] operands; + return result; +} + +ExpressionLayout * Function::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { + assert(floatDisplayMode != FloatDisplayMode::Default); + assert(complexFormat != ComplexFormat::Default); + ExpressionLayout ** grandChildrenLayouts = new ExpressionLayout *[2*m_numberOfArguments-1]; + int layoutIndex = 0; + grandChildrenLayouts[layoutIndex++] = m_args[0]->createLayout(floatDisplayMode, complexFormat); + for (int i = 1; i < m_numberOfArguments; i++) { + grandChildrenLayouts[layoutIndex++] = new StringLayout(",", 1); + grandChildrenLayouts[layoutIndex++] = m_args[i]->createLayout(floatDisplayMode, complexFormat); + } + ExpressionLayout * argumentLayouts = new HorizontalLayout(grandChildrenLayouts, 2*m_numberOfArguments-1); + delete [] grandChildrenLayouts; + ExpressionLayout * childrenLayouts[2]; + childrenLayouts[0] = new StringLayout(m_name, strlen(m_name)); + childrenLayouts[1] = new ParenthesisLayout(argumentLayouts); + return new HorizontalLayout(childrenLayouts, 2); +} + +void Function::build(Expression ** args, int numberOfArguments, bool clone) { + clean(); + m_numberOfArguments = numberOfArguments; + m_args = new Expression * [numberOfArguments]; + for (int i = 0; i < numberOfArguments; i++) { + assert(args[i] != nullptr); + if (clone) { + m_args[i] = args[i]->clone(); + } else { + m_args[i] = args[i]; + } + } +} + +void Function::clean() { + if (m_args != nullptr) { + for (int i = 0; i < m_numberOfArguments; i++) { + delete m_args[i]; + } + delete[] m_args; + } } } diff --git a/poincare/src/global_context.cpp b/poincare/src/global_context.cpp index 3b65dce13..8328006ee 100644 --- a/poincare/src/global_context.cpp +++ b/poincare/src/global_context.cpp @@ -33,8 +33,8 @@ GlobalContext::~GlobalContext() { } } -Complex * GlobalContext::defaultExpression() { - static Complex * defaultExpression = new Complex(Complex::Float(0.0f)); +Evaluation * GlobalContext::defaultExpression() { + static Evaluation * defaultExpression = new Complex(Complex::Float(0.0f)); return defaultExpression; } @@ -43,7 +43,7 @@ int GlobalContext::symbolIndex(const Symbol * symbol) const { return index; } -const Expression * GlobalContext::expressionForSymbol(const Symbol * symbol) { +const Evaluation * GlobalContext::expressionForSymbol(const Symbol * symbol) { if (symbol->name() == Ion::Charset::SmallPi) { return &m_pi; } @@ -64,7 +64,7 @@ const Expression * GlobalContext::expressionForSymbol(const Symbol * symbol) { return m_expressions[index]; } -void GlobalContext::setExpressionForSymbolName(Expression * expression, const Symbol * symbol) { +void GlobalContext::setExpressionForSymbolName(Evaluation * expression, const Symbol * symbol) { if (symbol->isMatrixSymbol()) { int indexMatrix = symbol->name() - (char)Symbol::SpecialSymbols::M0; assert(indexMatrix >= 0 && indexMatrix < k_maxNumberOfMatrixExpressions); @@ -72,8 +72,12 @@ void GlobalContext::setExpressionForSymbolName(Expression * expression, const Sy delete m_matrixExpressions[indexMatrix]; m_matrixExpressions[indexMatrix] = nullptr; } - if (expression != nullptr && expression->type() == Expression::Type::Matrix) { - m_matrixExpressions[indexMatrix] = expression->clone(); + if (expression != nullptr) { + if (expression->numberOfOperands() == 1) { + m_matrixExpressions[indexMatrix] = new ComplexMatrix(expression->complexOperand(0), 1, 1); + } else { + m_matrixExpressions[indexMatrix] = expression->clone(); + } } return; } @@ -88,8 +92,8 @@ void GlobalContext::setExpressionForSymbolName(Expression * expression, const Sy if (expression == nullptr) { return; } - if (expression->type() == Expression::Type::Complex) { - m_expressions[index] = expression->clone(); + if (expression->numberOfOperands() == 1) { + m_expressions[index] = new Complex(*(expression->complexOperand(0))); } else { m_expressions[index] = new Complex(Complex::Float(NAN)); } diff --git a/poincare/src/great_common_divisor.cpp b/poincare/src/great_common_divisor.cpp index 5a3afdbd8..aca9014ba 100644 --- a/poincare/src/great_common_divisor.cpp +++ b/poincare/src/great_common_divisor.cpp @@ -25,12 +25,15 @@ Expression * GreatCommonDivisor::cloneWithDifferentOperands(Expression** newOper return gcd; } -float GreatCommonDivisor::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - float f1 = m_args[0]->approximate(context, angleUnit); - float f2 = m_args[1]->approximate(context, angleUnit); +Evaluation * GreatCommonDivisor::privateEvaluate(Context & context, AngleUnit angleUnit) const { + Evaluation * f1Input = m_args[0]->evaluate(context, angleUnit); + Evaluation * f2Input = m_args[1]->evaluate(context, angleUnit); + float f1 = f1Input->toFloat(); + float f2 = f2Input->toFloat(); + delete f1Input; + delete f2Input; if (isnan(f1) || isnan(f2) || f1 != (int)f1 || f2 != (int)f2) { - return NAN; + return new Complex(Complex::Float(NAN)); } int a = (int)f2; int b = (int)f1; @@ -44,7 +47,8 @@ float GreatCommonDivisor::privateApproximate(Context& context, AngleUnit angleUn a = b; b = r; } - return roundf((float)a); + return new Complex(Complex::Float(roundf((float)a))); + } } diff --git a/poincare/src/hyperbolic_arc_cosine.cpp b/poincare/src/hyperbolic_arc_cosine.cpp index 38a811d61..7c71094d1 100644 --- a/poincare/src/hyperbolic_arc_cosine.cpp +++ b/poincare/src/hyperbolic_arc_cosine.cpp @@ -23,10 +23,11 @@ Expression * HyperbolicArcCosine::cloneWithDifferentOperands(Expression** newOpe return c; } -float HyperbolicArcCosine::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - float x = m_args[0]->approximate(context, angleUnit); - return acoshf(x); +Complex HyperbolicArcCosine::computeComplex(const Complex c, AngleUnit angleUnit) const { + if (c.b() != 0.0f) { + return Complex::Float(NAN); + } + return Complex::Float(acoshf(c.a())); } } diff --git a/poincare/src/hyperbolic_arc_sine.cpp b/poincare/src/hyperbolic_arc_sine.cpp index 29c5ece28..8b7d932fc 100644 --- a/poincare/src/hyperbolic_arc_sine.cpp +++ b/poincare/src/hyperbolic_arc_sine.cpp @@ -23,10 +23,11 @@ Expression * HyperbolicArcSine::cloneWithDifferentOperands(Expression** newOpera return s; } -float HyperbolicArcSine::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - float x = m_args[0]->approximate(context, angleUnit); - return asinhf(x); +Complex HyperbolicArcSine::computeComplex(const Complex c, AngleUnit angleUnit) const { + if (c.b() != 0.0f) { + return Complex::Float(NAN); + } + return Complex::Float(asinhf(c.a())); } } diff --git a/poincare/src/hyperbolic_arc_tangent.cpp b/poincare/src/hyperbolic_arc_tangent.cpp index 9bf34cc68..d73c1dcfd 100644 --- a/poincare/src/hyperbolic_arc_tangent.cpp +++ b/poincare/src/hyperbolic_arc_tangent.cpp @@ -23,10 +23,11 @@ Expression * HyperbolicArcTangent::cloneWithDifferentOperands(Expression** newOp return t; } -float HyperbolicArcTangent::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - float x = m_args[0]->approximate(context, angleUnit); - return atanhf(x); +Complex HyperbolicArcTangent::computeComplex(const Complex c, AngleUnit angleUnit) const { + if (c.b() != 0.0f) { + return Complex::Float(NAN); + } + return Complex::Float(atanhf(c.a())); } } diff --git a/poincare/src/hyperbolic_cosine.cpp b/poincare/src/hyperbolic_cosine.cpp index 557f2e09c..abbb9ed4a 100644 --- a/poincare/src/hyperbolic_cosine.cpp +++ b/poincare/src/hyperbolic_cosine.cpp @@ -28,48 +28,15 @@ Expression * HyperbolicCosine::cloneWithDifferentOperands(Expression** newOperan return hc; } -float HyperbolicCosine::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - return coshf(m_args[0]->approximate(context, angleUnit)); -} - -Expression * HyperbolicCosine::privateEvaluate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - Expression * evaluation = m_args[0]->evaluate(context, angleUnit); - assert(evaluation->type() == Type::Matrix || evaluation->type() == Type::Complex); - if (evaluation->type() == Type::Matrix) { - delete evaluation; - return new Complex(Complex::Float(NAN)); +Complex HyperbolicCosine::compute(const Complex c) { + if (c.b() == 0.0f) { + return Complex::Float(coshf(c.a())); } - /* Float case */ - if (((Complex *)evaluation)->b() == 0) { - Expression * result = new Complex(Complex::Float(coshf(evaluation->approximate(context, angleUnit)))); - delete evaluation; - return result; - } - /* Complex case */ - Expression * arguments[2]; - arguments[0] = new Complex(Complex::Float(M_E)); - arguments[1] = evaluation; - Expression * exp1 = new Power(arguments, true); - arguments[1] = new Opposite(evaluation, true); - Expression * exp2 = new Power(arguments, true); - delete arguments[1]; - delete arguments[0]; - delete evaluation; - arguments[0] = exp1; - arguments[1] = exp2; - Expression * sum = new Addition(arguments, true); - delete exp1; - delete exp2; - arguments[0] = sum; - arguments[1] = new Complex(Complex::Float(2.0f)); - Expression * result = new Fraction(arguments, true); - delete arguments[1]; - delete arguments[0]; - Expression * resultEvaluation = result->evaluate(context, angleUnit); - delete result; - return resultEvaluation; + Complex e = Complex::Float(M_E); + Complex exp1 = Power::compute(e, c); + Complex exp2 = Power::compute(e, Complex::Cartesian(-c.a(), -c.b())); + Complex sum = Addition::compute(exp1, exp2); + return Fraction::compute(sum, Complex::Float(2.0f)); } } diff --git a/poincare/src/hyperbolic_sine.cpp b/poincare/src/hyperbolic_sine.cpp index e059fed1e..54f77a6aa 100644 --- a/poincare/src/hyperbolic_sine.cpp +++ b/poincare/src/hyperbolic_sine.cpp @@ -28,48 +28,15 @@ Expression * HyperbolicSine::cloneWithDifferentOperands(Expression** newOperands return hs; } -float HyperbolicSine::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - return sinhf(m_args[0]->approximate(context, angleUnit)); -} - -Expression * HyperbolicSine::privateEvaluate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - Expression * evaluation = m_args[0]->evaluate(context, angleUnit); - assert(evaluation->type() == Type::Matrix || evaluation->type() == Type::Complex); - if (evaluation->type() == Type::Matrix) { - delete evaluation; - return new Complex(Complex::Float(NAN)); +Complex HyperbolicSine::compute(const Complex c) { + if (c.b() == 0.0f) { + return Complex::Float(sinhf(c.a())); } - /* Float case */ - if (((Complex *)evaluation)->b() == 0) { - Expression * result = new Complex(Complex::Float(sinhf(evaluation->approximate(context, angleUnit)))); - delete evaluation; - return result; - } - /* Complex case */ - Expression * arguments[2]; - arguments[0] = new Complex(Complex::Float(M_E)); - arguments[1] = evaluation; - Expression * exp1 = new Power(arguments, true); - arguments[1] = new Opposite(evaluation, true); - Expression * exp2 = new Power(arguments, true); - delete arguments[1]; - delete arguments[0]; - delete evaluation; - arguments[0] = exp1; - arguments[1] = exp2; - Expression * sub = new Subtraction(arguments, true); - delete exp1; - delete exp2; - arguments[0] = sub; - arguments[1] = new Complex(Complex::Float(2.0f)); - Expression * result = new Fraction(arguments, true); - delete arguments[1]; - delete arguments[0]; - Expression * resultEvaluation = result->evaluate(context, angleUnit); - delete result; - return resultEvaluation; + Complex e = Complex::Float(M_E); + Complex exp1 = Power::compute(e, c); + Complex exp2 = Power::compute(e, Complex::Cartesian(-c.a(), -c.b())); + Complex sub = Subtraction::compute(exp1, exp2); + return Fraction::compute(sub, Complex::Float(2.0f)); } } diff --git a/poincare/src/hyperbolic_tangent.cpp b/poincare/src/hyperbolic_tangent.cpp index 38b3ed549..d171ec16c 100644 --- a/poincare/src/hyperbolic_tangent.cpp +++ b/poincare/src/hyperbolic_tangent.cpp @@ -26,38 +26,13 @@ Expression * HyperbolicTangent::cloneWithDifferentOperands(Expression** newOpera return ht; } -float HyperbolicTangent::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - return tanhf(m_args[0]->approximate(context, angleUnit)); -} - -Expression * HyperbolicTangent::privateEvaluate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - Expression * evaluation = m_args[0]->evaluate(context, angleUnit); - assert(evaluation->type() == Type::Matrix || evaluation->type() == Type::Complex); - if (evaluation->type() == Type::Matrix) { - delete evaluation; - return new Complex(Complex::Float(NAN)); +Complex HyperbolicTangent::compute(const Complex c) { + if (c.b() == 0.0f) { + return Complex::Float(tanhf(c.a())); } - /* Float case */ - if (((Complex *)evaluation)->b() == 0) { - Expression * result = new Complex(Complex::Float(tanhf(evaluation->approximate(context, angleUnit)))); - delete evaluation; - return result; - } - /* Complex case */ - Expression * arguments[2]; - arguments[0] = new HyperbolicSine(); - ((Function *)arguments[0])->setArgument(&evaluation, 1, true); - arguments[1] = new HyperbolicCosine(); - ((Function *)arguments[1])->setArgument(&evaluation, 1, true); - delete evaluation; - Expression * result = new Fraction(arguments, true); - delete arguments[1]; - delete arguments[0]; - Expression * resultEvaluation = result->evaluate(context, angleUnit); - delete result; - return resultEvaluation; + Complex arg1 = HyperbolicSine::compute(c); + Complex arg2 = HyperbolicCosine::compute(c); + return Fraction::compute(arg1, arg2); } } diff --git a/poincare/src/imaginary_part.cpp b/poincare/src/imaginary_part.cpp index bd6c72d35..a9b3e532b 100644 --- a/poincare/src/imaginary_part.cpp +++ b/poincare/src/imaginary_part.cpp @@ -25,18 +25,8 @@ Expression * ImaginaryPart::cloneWithDifferentOperands(Expression** newOperands, return ip; } -float ImaginaryPart::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - Expression * evaluation = m_args[0]->evaluate(context, angleUnit); - assert(evaluation->type() == Type::Matrix || evaluation->type() == Type::Complex); - float result = 0.0f; - if (evaluation->type() == Type::Matrix) { - result = NAN; - } else { - result = ((Complex *)evaluation)->b(); - } - delete evaluation; - return result; +Complex ImaginaryPart::computeComplex(const Complex c, AngleUnit angleUnit) const { + return Complex::Float(c.b()); } } diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 3ab775621..9a15a21be 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -40,7 +40,7 @@ Integer::Integer(native_int_t i) { assert(sizeof(native_int_t) <= sizeof(native_uint_t)); m_negative = (i<0); m_numberOfDigits = 1; - m_digits = (native_uint_t *)malloc(sizeof(native_uint_t)); + m_digits = new native_uint_t[1]; *m_digits = (native_uint_t)(i>0 ? i : -i); } @@ -75,7 +75,7 @@ Integer::Integer(const char * digits, bool negative) { Integer::~Integer() { if (m_digits) { - free(m_digits); + delete[] m_digits; } } @@ -129,7 +129,7 @@ Integer& Integer::operator=(Integer&& other) { // Release our ivars m_negative = 0; m_numberOfDigits = 0; - free(m_digits); + delete[] m_digits; // Pilfer other's ivars m_numberOfDigits = other.m_numberOfDigits; @@ -175,7 +175,7 @@ Integer Integer::usum(const Integer &other, bool subtract, bool output_negative) // Addition can overflow size += 1; } - native_uint_t * digits = (native_uint_t *)malloc(size*sizeof(native_uint_t)); + native_uint_t * digits = new native_uint_t [size]; bool carry = false; for (uint16_t i = 0; i= m_numberOfDigits ? 0 : m_digits[i]); @@ -194,7 +194,7 @@ Integer Integer::usum(const Integer &other, bool subtract, bool output_negative) Integer Integer::multiply_by(const Integer &other) const { assert(sizeof(double_native_uint_t) == 2*sizeof(native_uint_t)); uint16_t productSize = other.m_numberOfDigits + m_numberOfDigits; - native_uint_t * digits = (native_uint_t *)malloc(productSize*sizeof(native_uint_t)); + native_uint_t * digits = new native_uint_t [productSize]; memset(digits, 0, productSize*sizeof(native_uint_t)); double_native_uint_t carry = 0; @@ -251,16 +251,15 @@ Expression * Integer::clone() const { Integer * clone = new Integer((native_int_t)0); clone->m_numberOfDigits = m_numberOfDigits; clone->m_negative = m_negative; - free(clone->m_digits); - clone->m_digits = (native_uint_t *)malloc(m_numberOfDigits*sizeof(native_uint_t)); + delete[] clone->m_digits; + clone->m_digits = new native_uint_t [m_numberOfDigits]; for (unsigned int i=0;im_digits[i] = m_digits[i]; } return clone; } -float Integer::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); +Evaluation * Integer::privateEvaluate(Context& context, AngleUnit angleUnit) const { union { uint32_t uint_result; float float_result; @@ -288,7 +287,7 @@ float Integer::privateApproximate(Context& context, AngleUnit angleUnit) const { * the integer whose 2-exponent is bigger than 255 cannot be stored as a * float (IEEE 754 floating point). The approximation is thus INFINITY. */ if ((int)exponent + (m_numberOfDigits-1)*32 +numberOfBitsInLastDigit> 255) { - return INFINITY; + return new Complex(Complex::Float(INFINITY)); } exponent += (m_numberOfDigits-1)*32; exponent += numberOfBitsInLastDigit; @@ -306,7 +305,8 @@ float Integer::privateApproximate(Context& context, AngleUnit angleUnit) const { * area), the issue is that when the mantissa is 0, a "shadow bit" is * assumed to be there, thus 126 0x000000 is equal to 0.5 and not zero. */ - return m_negative ? -0.0f : 0.0f; + float result = m_negative ? -0.0f : 0.0f; + return new Complex(Complex::Float(result)); } uint_result = 0; @@ -317,15 +317,10 @@ float Integer::privateApproximate(Context& context, AngleUnit angleUnit) const { /* If exponent is 255 and the float is undefined, we have exceed IEEE 754 * representable float. */ if (exponent == 255 && isnan(float_result)) { - return INFINITY; + return new Complex(Complex::Float(INFINITY)); } - return float_result; -} - -Expression * Integer::privateEvaluate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - return new Complex(Complex::Float(approximate(context, angleUnit))); + return new Complex(Complex::Float(float_result)); } Expression::Type Integer::type() const { diff --git a/poincare/src/integral.cpp b/poincare/src/integral.cpp index f8ebb0064..32475a607 100644 --- a/poincare/src/integral.cpp +++ b/poincare/src/integral.cpp @@ -31,19 +31,23 @@ Expression * Integral::cloneWithDifferentOperands(Expression** newOperands, return i; } -float Integral::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); +Evaluation * Integral::privateEvaluate(Context & context, AngleUnit angleUnit) const { VariableContext xContext = VariableContext('x', &context); - float a = m_args[1]->approximate(context, angleUnit); - float b = m_args[2]->approximate(context, angleUnit); + Evaluation * aInput = m_args[1]->evaluate(context, angleUnit); + float a = aInput->toFloat(); + delete aInput; + Evaluation * bInput = m_args[2]->evaluate(context, angleUnit); + float b = bInput->toFloat(); + delete bInput; if (isnan(a) || isnan(b)) { - return NAN; + return new Complex(Complex::Float(NAN)); } #ifdef LAGRANGE_METHOD - return lagrangeGaussQuadrature(a, b, xContext, angleUnit); + float result = lagrangeGaussQuadrature(a, b, xContext, angleUnit); #else - return adaptiveQuadrature(a, b, 0.1, k_maxNumberOfIterations, xContext, angleUnit); + float result = adaptiveQuadrature(a, b, 0.1, k_maxNumberOfIterations, xContext, angleUnit); #endif + return new Complex(Complex::Float(result)); } ExpressionLayout * Integral::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { @@ -59,7 +63,10 @@ float Integral::functionValueAtAbscissa(float x, VariableContext xContext, Angle Complex e = Complex::Float(x); Symbol xSymbol = Symbol('x'); xContext.setExpressionForSymbolName(&e, &xSymbol); - return m_args[0]->approximate(xContext, angleUnit); + Evaluation * f = m_args[0]->evaluate(xContext, angleUnit); + float result = f->toFloat(); + delete f; + return result; } #ifdef LAGRANGE_METHOD diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index 4564f613d..91bc2f6f3 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -11,7 +11,7 @@ GridLayout::GridLayout(ExpressionLayout ** entryLayouts, int numberOfRows, int n m_numberOfRows(numberOfRows), m_numberOfColumns(numberOfColumns) { - m_entryLayouts = (ExpressionLayout **)malloc(numberOfColumns*numberOfRows*sizeof(ExpressionLayout *)); + m_entryLayouts = new ExpressionLayout *[numberOfColumns*numberOfRows]; for (int i = 0; i < m_numberOfRows*m_numberOfColumns; i++) { m_entryLayouts[i] = entryLayouts[i]; m_entryLayouts[i]->setParent(this); @@ -23,7 +23,7 @@ GridLayout::~GridLayout() { for (int i=0; i 0); - m_children_layouts = (ExpressionLayout **)malloc(number_of_children*sizeof(ExpressionLayout *)); + m_children_layouts = new ExpressionLayout *[number_of_children]; for (int i=0; isetParent(this); @@ -25,7 +25,7 @@ HorizontalLayout::~HorizontalLayout() { for (int i=0; iapproximate(context, angleUnit); - float f2 = m_args[1]->approximate(context, angleUnit); +Evaluation * LeastCommonMultiple::privateEvaluate(Context & context, AngleUnit angleUnit) const { + Evaluation * f1Input = m_args[0]->evaluate(context, angleUnit); + Evaluation * f2Input = m_args[1]->evaluate(context, angleUnit); + float f1 = f1Input->toFloat(); + float f2 = f2Input->toFloat(); + delete f1Input; + delete f2Input; if (isnan(f1) || isnan(f2) || f1 != (int)f1 || f2 != (int)f2 || f1 == 0.0f || f2 == 0.0f) { - return NAN; + return new Complex(Complex::Float(NAN)); } int a = (int)f2; int b = (int)f1; @@ -45,7 +48,7 @@ float LeastCommonMultiple::privateApproximate(Context& context, AngleUnit angleU a = b; b = r; } - return roundf((float)(product/a)); + return new Complex(Complex::Float(roundf((float)(product/a)))); } } diff --git a/poincare/src/list_data.cpp b/poincare/src/list_data.cpp index 4e6e11194..82e29b43c 100644 --- a/poincare/src/list_data.cpp +++ b/poincare/src/list_data.cpp @@ -8,7 +8,7 @@ namespace Poincare { ListData::ListData(Expression * operand) : m_numberOfOperands(1), - m_operands((Expression **)malloc(sizeof(Expression *))) + m_operands(new Expression*[1]) { assert(operand != nullptr); m_operands[0] = operand; @@ -18,15 +18,15 @@ ListData::~ListData() { for (int i=0; i= 0); assert(i < m_numberOfOperands); diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 69ad546f9..0c9f662c7 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -1,4 +1,5 @@ #include +#include extern "C" { #include #include @@ -40,12 +41,26 @@ Expression * Logarithm::cloneWithDifferentOperands(Expression** newOperands, return l; } -float Logarithm::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - if (m_numberOfArguments == 1) { - return log10f(m_args[0]->approximate(context, angleUnit)); +Complex Logarithm::computeComplex(const Complex c, AngleUnit angleUnit) const { + if (c.b() != 0.0f) { + return Complex::Float(NAN); } - return log10f(m_args[1]->approximate(context, angleUnit))/log10f(m_args[0]->approximate(context, angleUnit)); + return Complex::Float(log10f(c.a())); +} + +Evaluation * Logarithm::privateEvaluate(Context & context, AngleUnit angleUnit) const { + if (m_numberOfArguments == 1) { + return Function::privateEvaluate(context, angleUnit); + } + Evaluation * x = m_args[0]->evaluate(context, angleUnit); + Evaluation * n = m_args[1]->evaluate(context, angleUnit); + if (x->numberOfRows() != 1 || x->numberOfColumns() != 1 || n->numberOfRows() != 1 || n->numberOfColumns() != 1) { + return new Complex(Complex::Float(NAN)); + } + Complex result = Fraction::compute(computeComplex(*(n->complexOperand(0)), angleUnit), computeComplex(*(x->complexOperand(0)), angleUnit)); + delete x; + delete n; + return new Complex(result); } ExpressionLayout * Logarithm::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { diff --git a/poincare/src/matrix.cpp b/poincare/src/matrix.cpp index 1fee60037..7c6b88ab1 100644 --- a/poincare/src/matrix.cpp +++ b/poincare/src/matrix.cpp @@ -12,101 +12,23 @@ extern "C" { namespace Poincare { -Matrix::Matrix(MatrixData * matrixData) : - m_matrixData(matrixData) -{ -} - -Matrix::~Matrix() { - delete m_matrixData; -} - -bool Matrix::hasValidNumberOfArguments() const { - for (int i = 0; i < numberOfOperands(); i++) { - if (!operand(i)->hasValidNumberOfArguments()) { - return false; - } - } - return true; -} - -Matrix::Matrix(Expression ** newOperands, int numberOfOperands, int numberOfColumns, int numberOfRows, bool cloneOperands) -{ - m_matrixData = new MatrixData(newOperands, numberOfOperands, numberOfColumns, numberOfRows, cloneOperands); -} - -Complex * Matrix::defaultExpression() { - static Complex * defaultExpression = new Complex(Complex::Float(0.0f)); - return defaultExpression; -} - int Matrix::numberOfOperands() const { - return m_matrixData->numberOfRows() * m_matrixData->numberOfColumns(); -} - -const Expression * Matrix::operand(int i) const { - assert(i >= 0); - assert(i < numberOfOperands()); - return m_matrixData->operands()[i]; -} - -Expression * Matrix::clone() const { - return this->cloneWithDifferentOperands(m_matrixData->operands(), numberOfOperands(), true); + return numberOfRows() * numberOfColumns(); } ExpressionLayout * Matrix::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - ExpressionLayout ** childrenLayouts = (ExpressionLayout **)malloc(numberOfOperands()*sizeof(ExpressionLayout *)); + ExpressionLayout ** childrenLayouts = new ExpressionLayout * [numberOfOperands()]; for (int i = 0; i < numberOfOperands(); i++) { childrenLayouts[i] = operand(i)->createLayout(floatDisplayMode, complexFormat); } ExpressionLayout * layout = new BracketLayout(new GridLayout(childrenLayouts, numberOfRows(), numberOfColumns())); - free(childrenLayouts); + delete [] childrenLayouts; return layout; } -float Matrix::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - return NAN; -} - -Expression * Matrix::privateEvaluate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - Expression ** operands = (Expression **)malloc(numberOfOperands()*sizeof(Expression *)); - for (int i = 0; i < numberOfOperands(); i++) { - operands[i] = operand(i)->evaluate(context, angleUnit); - assert(operands[i]->type() == Type::Matrix || operands[i]->type() == Type::Complex); - if (operands[i]->type() == Type::Matrix) { - delete operands[i]; - operands[i] = new Complex(Complex::Float(NAN)); - continue; - } - } - Expression * matrix = new Matrix(new MatrixData(operands, numberOfOperands(), numberOfColumns(), numberOfRows(), false)); - free(operands); - return matrix; -} - -Expression::Type Matrix::type() const { - return Type::Matrix; -} - -Expression * Matrix::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - return new Matrix(newOperands, numberOfOperands, numberOfColumns(), numberOfRows(), cloneOperands); -} - -int Matrix::numberOfRows() const { - return m_matrixData->numberOfRows(); -} - -int Matrix::numberOfColumns() const { - return m_matrixData->numberOfColumns(); -} - -int Matrix::writeTextInBuffer(char * buffer, int bufferSize) { +int Matrix::writeTextInBuffer(char * buffer, int bufferSize) const { buffer[bufferSize-1] = 0; int currentChar = 0; if (currentChar >= bufferSize) { @@ -116,12 +38,12 @@ int Matrix::writeTextInBuffer(char * buffer, int bufferSize) { if (currentChar >= bufferSize) { return currentChar; } - for (int i = 0; i < m_matrixData->numberOfRows(); i++) { + for (int i = 0; i < numberOfRows(); i++) { buffer[currentChar++] = '['; if (currentChar >= bufferSize) { return currentChar; } - currentChar += m_matrixData->operands()[i*m_matrixData->numberOfColumns()]->writeTextInBuffer(buffer+currentChar, bufferSize-currentChar); + currentChar += operand(i*numberOfColumns())->writeTextInBuffer(buffer+currentChar, bufferSize-currentChar); if (currentChar >= bufferSize) { return currentChar; } @@ -130,7 +52,7 @@ int Matrix::writeTextInBuffer(char * buffer, int bufferSize) { if (currentChar >= bufferSize) { return currentChar; } - currentChar += m_matrixData->operands()[i*m_matrixData->numberOfColumns()+j]->writeTextInBuffer(buffer+currentChar, bufferSize-currentChar); + currentChar += operand(i*numberOfColumns()+j)->writeTextInBuffer(buffer+currentChar, bufferSize-currentChar); if (currentChar >= bufferSize) { return currentChar; } @@ -152,186 +74,4 @@ int Matrix::writeTextInBuffer(char * buffer, int bufferSize) { return currentChar; } -Expression * Matrix::createDimensionMatrix(Context& context, AngleUnit angleUnit) const { - Expression * operands[2]; - operands[0] = new Complex(Complex::Float(numberOfRows())); - operands[1] = new Complex(Complex::Float(numberOfColumns())); - return new Matrix(new MatrixData(operands, 2, 2, 1, false)); -} - -float Matrix::trace(Context& context, AngleUnit angleUnit) const { - if (numberOfColumns() != numberOfRows()) { - return NAN; - } - int dim = numberOfRows(); - float trace = 0.0f; - for (int i = 0; i < dim; i++) { - trace += m_matrixData->operands()[i*dim+i]->approximate(context, angleUnit); - } - return trace; -} - -float Matrix::determinant(Context& context, AngleUnit angleUnit) const { - if (numberOfColumns() != numberOfRows()) { - return NAN; - } - int dim = numberOfRows(); - float ** tempMat = (float **)malloc(dim*sizeof(float*)); - for (int i = 0; i < dim; i++) { - tempMat[i] = (float *)malloc(dim*sizeof(float)); - } - float det = 1.0f; - /* Copy the matrix */ - for (int i = 0; i < dim; i++) { - for (int j = 0; j < dim; j++) { - tempMat[i][j] = m_matrixData->operands()[i*dim+j]->approximate(context, angleUnit); - } - } - -/* Main Loop: Gauss pivot */ - for (int i = 0; i < dim-1; i++) { - /* Search for pivot */ - int rowWithPivot = i; - for (int row = i+1; row < dim; row++) { - if (fabsf(tempMat[rowWithPivot][i]) < fabsf(tempMat[row][i])) { - rowWithPivot = row; - } - } - float valuePivot = tempMat[rowWithPivot][i]; - /* if the pivot is null, det = 0. */ - if (fabsf(valuePivot) <= FLT_EPSILON) { - for (int i = 0; i < dim; i++) { - free(tempMat[i]); - } - free(tempMat); - return 0.0f; - } -/* Switch rows to have the pivot row as first row */ - if (rowWithPivot != i) { - for (int col = i; col < dim; col++) { - float temp = tempMat[i][col]; - tempMat[i][col] = tempMat[rowWithPivot][col]; - tempMat[rowWithPivot][col] = temp; - } - det *= -1; - } - det *= valuePivot; -/* Set to 0 all A[][i] by linear combination */ - for (int row = i+1; row < dim; row++) { - float factor = tempMat[row][i]/valuePivot; - for (int col = i; col < dim; col++) { - tempMat[row][col] -= factor*tempMat[i][col]; - } - } - } - det *= tempMat[dim-1][dim-1]; - for (int i = 0; i < dim; i++) { - free(tempMat[i]); - } - free(tempMat); - return det; -} - -Expression * Matrix::createInverse(Context& context, AngleUnit angleUnit) const { - if (numberOfColumns() != numberOfRows()) { - return new Complex(Complex::Float(NAN)); - } - int dim = numberOfRows(); - /* Create the matrix inv = (A|I) with A the input matrix and I the dim identity matrix */ - float ** inv = (float **)malloc(dim*sizeof(float*)); - for (int i = 0; i < dim; i++) { - inv[i] = (float *)malloc(2*dim*sizeof(float)); - } - for (int i = 0; i < dim; i++) { - for (int j = 0; j < dim; j++) { - inv[i][j] = m_matrixData->operands()[i*dim+j]->approximate(context, angleUnit); - } - for (int j = dim; j < 2*dim; j++) { - inv[i][j] = (i+dim == j); - } - } -/* Main Loop: Gauss pivot */ - for (int i = 0; i < dim; i++) { - /* Search for pivot */ - int rowWithPivot = i; - for (int row = i+1; row < dim; row++) { - if (fabsf(inv[rowWithPivot][i]) < fabsf(inv[row][i])) { - rowWithPivot = row; - } - } - float valuePivot = inv[rowWithPivot][i]; - /* if the pivot is null, the matrix in not invertible. */ - if (fabsf(valuePivot) <= FLT_EPSILON) { - for (int i = 0; i < dim; i++) { - free(inv[i]); - } - free(inv); - return new Complex(Complex::Float(NAN)); - } - /* Switch rows to have the pivot row as first row */ - if (rowWithPivot != i) { - for (int col = i; col < 2*dim; col++) { - float temp = inv[i][col]; - inv[i][col] = inv[rowWithPivot][col]; - inv[rowWithPivot][col] = temp; - } - } - /* A[pivot][] = A[pivot][]/valuePivot */ - for (int col = 0; col < 2*dim; col++) { - inv[i][col] /= valuePivot; - } - /* Set to 0 all A[][row] by linear combination */ - for (int row = 0; row < dim; row++) { - if (row == i) { - continue; - } - float factor = inv[row][i]; - for (int col = 0; col < 2*dim; col++) { - inv[row][col] -= factor*inv[i][col]; - } - } - } - Expression ** operands = (Expression **)malloc(numberOfOperands()*sizeof(Expression *)); - for (int i = 0; i < dim; i++) { - for (int j = 0; j < dim; j++) { - operands[i*dim+j] = new Complex(Complex::Float(inv[i][j+dim])); - } - } - for (int i = 0; i < dim; i++) { - free(inv[i]); - } - free(inv); - Expression * matrix = new Matrix(new MatrixData(operands, numberOfOperands(), numberOfColumns(), numberOfRows(), false)); - free(operands); - return matrix; -} - -Expression * Matrix::createTranspose(Context& context, AngleUnit angleUnit) const { - Expression ** operands = (Expression **)malloc(numberOfOperands()*sizeof(Expression *)); - for (int i = 0; i < numberOfRows(); i++) { - for (int j = 0; j < numberOfColumns(); j++) { - operands[j*numberOfRows()+i] = m_matrixData->operands()[i*numberOfColumns()+j]->clone(); - } - } - Expression * matrix = new Matrix(new MatrixData(operands, numberOfOperands(), numberOfRows(), numberOfColumns(), false)); - free(operands); - return matrix; -} - -Expression * Matrix::createIdentity(int dim) { - Expression ** operands = (Expression **)malloc(dim*dim*sizeof(Expression *)); - for (int i = 0; i < dim; i++) { - for (int j = 0; j < dim; j++) { - if (i == j) { - operands[i*dim+j] = new Complex(Complex::Float(1.0f)); - } else { - operands[i*dim+j] = new Complex(Complex::Float(0.0f)); - } - } - } - Expression * matrix = new Matrix(new MatrixData(operands, dim*dim, dim, dim, false)); - free(operands); - return matrix; -} - } diff --git a/poincare/src/matrix_data.cpp b/poincare/src/matrix_data.cpp index e5506a431..a0de65b8c 100644 --- a/poincare/src/matrix_data.cpp +++ b/poincare/src/matrix_data.cpp @@ -3,6 +3,7 @@ extern "C" { #include } #include +#include namespace Poincare { @@ -12,7 +13,7 @@ MatrixData::MatrixData(ListData * listData, bool clone) : { assert(listData != nullptr); m_numberOfColumns = listData->numberOfOperands(); - m_operands = (Expression **)malloc(m_numberOfColumns*sizeof(Expression *)); + m_operands = new Expression *[m_numberOfColumns]; for (int i = 0; i < m_numberOfColumns; i++) { if (clone) { m_operands[i] = (Expression *)listData->operand(i)->clone(); @@ -27,7 +28,7 @@ MatrixData::MatrixData(Expression ** newOperands, int numberOfOperands, int numb m_numberOfColumns(numberOfColumns) { assert(newOperands != nullptr); - m_operands = (Expression **)malloc(m_numberOfRows*m_numberOfColumns*sizeof(Expression *)); + m_operands = new Expression *[m_numberOfRows*m_numberOfColumns]; for (int i = 0; i < m_numberOfColumns*m_numberOfRows; i++) { if (cloneOperands) { m_operands[i] = i < numberOfOperands ? newOperands[i]->clone() : defaultExpression(); @@ -49,11 +50,11 @@ MatrixData::~MatrixData() { delete m_operands[i]; } } - free(m_operands); + delete[] m_operands; } void MatrixData::pushListData(ListData * listData, bool clone) { - Expression ** newOperands = (Expression **)malloc(((m_numberOfRows+1)*m_numberOfColumns)*sizeof(Expression *)); + Expression ** newOperands = new Expression * [(m_numberOfRows+1)*m_numberOfColumns]; for (int i = 0; i < m_numberOfRows*m_numberOfColumns; i++) { newOperands[i] = m_operands[i]; } @@ -65,7 +66,7 @@ void MatrixData::pushListData(ListData * listData, bool clone) { newOperands[m_numberOfRows*m_numberOfColumns+i] = i < max ? (Expression *)listData->operand(i) : defaultExpression(); } } - free(m_operands); + delete[] m_operands; m_operands = newOperands; m_numberOfRows++; } diff --git a/poincare/src/matrix_dimension.cpp b/poincare/src/matrix_dimension.cpp index 2e464737a..873415513 100644 --- a/poincare/src/matrix_dimension.cpp +++ b/poincare/src/matrix_dimension.cpp @@ -24,22 +24,13 @@ Expression * MatrixDimension::cloneWithDifferentOperands(Expression** newOperand return md; } -float MatrixDimension::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - return NAN; -} - -Expression * MatrixDimension::privateEvaluate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - Expression * evaluation = m_args[0]->evaluate(context, angleUnit); - assert(evaluation->type() == Type::Matrix || evaluation->type() == Type::Complex); - if (evaluation->type() == Type::Complex) { - delete evaluation; - return new Complex(Complex::Float(NAN)); - } - Expression * dimension = ((Matrix *)evaluation)->createDimensionMatrix(context, angleUnit); - delete evaluation; - return dimension; +Evaluation * MatrixDimension::privateEvaluate(Context& context, AngleUnit angleUnit) const { + Evaluation * input = m_args[0]->evaluate(context, angleUnit); + Complex operands[2]; + operands[0] = Complex::Float((float)input->numberOfRows()); + operands[1] = Complex::Float((float)input->numberOfColumns()); + delete input; + return new ComplexMatrix(operands, 2, 1); } } diff --git a/poincare/src/matrix_inverse.cpp b/poincare/src/matrix_inverse.cpp index 58c34427a..91ec3d04e 100644 --- a/poincare/src/matrix_inverse.cpp +++ b/poincare/src/matrix_inverse.cpp @@ -26,29 +26,11 @@ Expression * MatrixInverse::cloneWithDifferentOperands(Expression** newOperands, return i; } -float MatrixInverse::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - return NAN; -} - -Expression * MatrixInverse::privateEvaluate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - Expression * evaluation = m_args[0]->evaluate(context, angleUnit); - assert(evaluation->type() == Type::Matrix || evaluation->type() == Type::Complex); - if (evaluation->type() == Type::Complex) { - Expression * arguments[2]; - arguments[0] = new Complex(Complex::Float(1.0f)); - arguments[1] = evaluation; - Expression * result = new Fraction(arguments, true); - delete arguments[0]; - delete arguments[1]; - Expression * resultEvaluation = result->evaluate(context, angleUnit); - delete result; - return resultEvaluation; - } - Expression * inverse = ((Matrix *)evaluation)->createInverse(context, angleUnit); - delete evaluation; - return inverse; +Evaluation * MatrixInverse::privateEvaluate(Context& context, AngleUnit angleUnit) const { + Evaluation * input = m_args[0]->evaluate(context, angleUnit); + Evaluation * result = input->createInverse(); + delete input; + return result; } } diff --git a/poincare/src/matrix_trace.cpp b/poincare/src/matrix_trace.cpp index e34519f93..1f565f26a 100644 --- a/poincare/src/matrix_trace.cpp +++ b/poincare/src/matrix_trace.cpp @@ -24,18 +24,11 @@ Expression * MatrixTrace::cloneWithDifferentOperands(Expression** newOperands, return t; } -float MatrixTrace::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - Expression * evaluation = m_args[0]->evaluate(context, angleUnit); - assert(evaluation->type() == Type::Matrix || evaluation->type() == Type::Complex); - if (evaluation->type() == Type::Complex) { - float result = evaluation->approximate(context, angleUnit); - delete evaluation; - return result; - } - float trace = ((Matrix *)evaluation)->trace(context, angleUnit); - delete evaluation; - return trace; +Evaluation * MatrixTrace::privateEvaluate(Context& context, AngleUnit angleUnit) const { + Evaluation * input = m_args[0]->evaluate(context, angleUnit); + Evaluation * result = input->createTrace(); + delete input; + return result; } } diff --git a/poincare/src/matrix_transpose.cpp b/poincare/src/matrix_transpose.cpp index 3a1c7a86a..1657157a1 100644 --- a/poincare/src/matrix_transpose.cpp +++ b/poincare/src/matrix_transpose.cpp @@ -26,21 +26,11 @@ Expression * MatrixTranspose::cloneWithDifferentOperands(Expression** newOperand return t; } -float MatrixTranspose::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - return NAN; -} - -Expression * MatrixTranspose::privateEvaluate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - Expression * evaluation = m_args[0]->evaluate(context, angleUnit); - assert(evaluation->type() == Type::Matrix || evaluation->type() == Type::Complex); - if (evaluation->type() == Type::Complex) { - return evaluation; - } - Expression * transpose = ((Matrix *)evaluation)->createTranspose(context, angleUnit); - delete evaluation; - return transpose; +Evaluation * MatrixTranspose::privateEvaluate(Context& context, AngleUnit angleUnit) const { + Evaluation * input = m_args[0]->evaluate(context, angleUnit); + Evaluation * result = input->createTranspose(); + delete input; + return result; } } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index cbce738cd..a9bda3fe7 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -25,11 +25,6 @@ ExpressionLayout * Multiplication::privateCreateLayout(FloatDisplayMode floatDis return new HorizontalLayout(children_layouts, 3); } -float Multiplication::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - return m_operands[0]->approximate(context, angleUnit)*m_operands[1]->approximate(context, angleUnit);; -} - Expression * Multiplication::cloneWithDifferentOperands(Expression** newOperands, int numberOfOperands, bool cloneOperands) const { assert(numberOfOperands == 2); @@ -37,41 +32,36 @@ Expression * Multiplication::cloneWithDifferentOperands(Expression** newOperands return new Multiplication(newOperands, cloneOperands); } -Expression * Multiplication::evaluateOnComplex(Complex * c, Complex * d, Context& context, AngleUnit angleUnit) const { - return new Complex(Complex::Cartesian(c->a()*d->a()-c->b()*d->b(), c->b()*d->a() + c->a()*d->b())); +Complex Multiplication::compute(const Complex c, const Complex d) { + return Complex::Cartesian(c.a()*d.a()-c.b()*d.b(), c.b()*d.a() + c.a()*d.b()); } -Expression * Multiplication::evaluateOnMatrices(Matrix * m, Matrix * n, Context& context, AngleUnit angleUnit) const { +Evaluation * Multiplication::computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { + Multiplication mul; + return mul.computeOnComplexAndComplexMatrix(c, m); +} + +Evaluation * Multiplication::computeOnMatrices(Evaluation * m, Evaluation * n) { if (m->numberOfColumns() != n->numberOfRows()) { return new Complex(Complex::Float(NAN)); } - Expression ** operands = (Expression **)malloc(m->numberOfRows() * n->numberOfColumns()*sizeof(Expression *)); + Complex * operands = new Complex[m->numberOfRows()*n->numberOfColumns()]; for (int i = 0; i < m->numberOfRows(); i++) { for (int j = 0; j < n->numberOfColumns(); j++) { float a = 0.0f; float b = 0.0f; for (int k = 0; k < m->numberOfColumns(); k++) { - Expression * mEvaluation = m->operand(i*m->numberOfColumns()+k)->evaluate(context, angleUnit); - Expression * nEvaluation = n->operand(k*n->numberOfColumns()+j)->evaluate(context, angleUnit); - assert(mEvaluation->type() == Type::Matrix || mEvaluation->type() == Type::Complex); - assert(nEvaluation->type() == Type::Matrix || nEvaluation->type() == Type::Complex); - if (mEvaluation->type() == Type::Matrix ||nEvaluation->type() == Type::Matrix) { - operands[i] = new Complex(Complex::Float(NAN)); - delete mEvaluation; - delete nEvaluation; - continue; - } - a += ((Complex *)mEvaluation)->a()*((Complex *)nEvaluation)->a() - ((Complex *)mEvaluation)->b()*((Complex *)nEvaluation)->b(); - b += ((Complex *)mEvaluation)->b()*((Complex *)nEvaluation)->a() + ((Complex *)mEvaluation)->a()*((Complex *)nEvaluation)->b(); - delete mEvaluation; - delete nEvaluation; + Complex mEntry = *(m->complexOperand(i*m->numberOfColumns()+k)); + Complex nEntry = *(n->complexOperand(k*n->numberOfColumns()+j)); + a += mEntry.a()*nEntry.a() - mEntry.b()*nEntry.b(); + b += mEntry.b()*nEntry.a() + mEntry.a()*nEntry.b(); } - operands[i*n->numberOfColumns()+j] = new Complex(Complex::Cartesian(a, b)); + operands[i*n->numberOfColumns()+j] = Complex::Cartesian(a, b); } } - Expression * matrix = new Matrix(operands, m->numberOfRows() * n->numberOfColumns(), n->numberOfColumns(), m->numberOfRows(), false); - free(operands); - return matrix; + Evaluation * result = new ComplexMatrix(operands, n->numberOfColumns(), m->numberOfRows()); + delete[] operands; + return result; } } diff --git a/poincare/src/naperian_logarithm.cpp b/poincare/src/naperian_logarithm.cpp index dc9e11a87..bbdd87069 100644 --- a/poincare/src/naperian_logarithm.cpp +++ b/poincare/src/naperian_logarithm.cpp @@ -27,9 +27,11 @@ Expression * NaperianLogarithm::cloneWithDifferentOperands(Expression** newOpera return l; } -float NaperianLogarithm::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - return logf(m_args[0]->approximate(context, angleUnit)); +Complex NaperianLogarithm::computeComplex(const Complex c, AngleUnit angleUnit) const { + if (c.b() != 0.0f) { + return Complex::Float(NAN); + } + return Complex::Float(logf(c.a())); } } diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index 8a3e96373..23ee6ac2b 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -28,44 +28,30 @@ Expression * NthRoot::cloneWithDifferentOperands(Expression** newOperands, return r; } -float NthRoot::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - return powf(m_args[0]->approximate(context, angleUnit), 1.0f/m_args[1]->approximate(context, angleUnit)); -} - ExpressionLayout * NthRoot::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); return new NthRootLayout(m_args[0]->createLayout(floatDisplayMode, complexFormat), m_args[1]->createLayout(floatDisplayMode, complexFormat)); } -Expression * NthRoot::privateEvaluate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - Expression * baseEvaluation = m_args[0]->evaluate(context, angleUnit); - Expression * indexEvaluation = m_args[1]->evaluate(context, angleUnit); - assert(baseEvaluation->type() == Type::Matrix || baseEvaluation->type() == Type::Complex); - assert(indexEvaluation->type() == Type::Matrix || indexEvaluation->type() == Type::Complex); - if (baseEvaluation->type() == Type::Matrix || indexEvaluation->type() == Type::Matrix) { - delete baseEvaluation; - delete indexEvaluation; - return new Complex(Complex::Float(NAN)); +Evaluation * NthRoot::privateEvaluate(Context& context, AngleUnit angleUnit) const { + Evaluation * base = m_args[0]->evaluate(context, angleUnit); + Evaluation * index = m_args[1]->evaluate(context, angleUnit); + Complex result = Complex::Float(NAN); + if (base->numberOfOperands() == 1 || index->numberOfOperands() == 1) { + result = compute(*(base->complexOperand(0)), *(index->complexOperand(0))); } - Expression * operands[2]; - operands[0] = baseEvaluation; - Expression * operandChildren[2]; - operandChildren[0] = new Complex(Complex::Float(1.0f)); - operandChildren[1] = indexEvaluation; - Expression * fraction = new Fraction(operandChildren, true); - operands[1] = fraction->evaluate(context, angleUnit); - Expression * power = new Power(operands, true); - Expression * newResult = power->evaluate(context, angleUnit); - delete baseEvaluation; - delete operandChildren[0]; - delete indexEvaluation; - delete fraction; - delete operands[1]; - delete power; - return newResult; + delete base; + delete index; + return new Complex(result); +} + +Complex NthRoot::compute(const Complex c, const Complex d) const { + if (c.b() == 0.0f && d.b() == 0.0f) { + return Complex::Float(powf(c.a(), 1.0f/d.a())); + } + Complex invIndex = Fraction::compute(Complex::Float(1.0f), d); + return Power::compute(c, invIndex); } } diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index 5be43f9d3..7f5ad4471 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -1,4 +1,6 @@ #include +#include +#include extern "C" { #include #include @@ -40,23 +42,27 @@ Expression * Opposite::clone() const { return this->cloneWithDifferentOperands((Expression**)&m_operand, 1, true); } -Expression * Opposite::privateEvaluate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - Expression * operandEvalutation = m_operand->evaluate(context, angleUnit); - Expression * result = nullptr; - switch (operandEvalutation->type()) { - case Type::Complex: - result = new Complex(Complex::Cartesian(-((Complex *)operandEvalutation)->a(), -((Complex *)operandEvalutation)->b())); - break; - case Type::Matrix: - result = evaluateOnMatrix((Matrix *)operandEvalutation, context, angleUnit); - break; - default: - result = new Complex(Complex::Float(NAN)); - break; +Complex Opposite::compute(const Complex c) { + return Complex::Cartesian(-c.a(), -c.b()); +} + +Evaluation * Opposite::computeOnMatrix(Evaluation * m) { + Complex * operands = new Complex[m->numberOfRows() * m->numberOfColumns()]; + for (int i = 0; i < m->numberOfRows() * m->numberOfColumns(); i++) { + Complex entry = *(m->complexOperand(i)); + operands[i] = Complex::Cartesian(-entry.a(), -entry.b()); } - delete operandEvalutation; - return result; + Evaluation * matrix = new ComplexMatrix(operands, m->numberOfColumns(), m->numberOfRows()); + delete[] operands; + return matrix; +} + +Evaluation * Opposite::privateEvaluate(Context& context, AngleUnit angleUnit) const { + Evaluation * operandEvalutation = m_operand->evaluate(context, angleUnit); + if (operandEvalutation->numberOfRows() == 1 && operandEvalutation->numberOfColumns() == 1) { + return new Complex(compute(*(operandEvalutation->complexOperand(0)))); + } + return computeOnMatrix(operandEvalutation); } ExpressionLayout * Opposite::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { @@ -69,11 +75,6 @@ ExpressionLayout * Opposite::privateCreateLayout(FloatDisplayMode floatDisplayMo return new HorizontalLayout(children_layouts, 2); } -float Opposite::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - return -m_operand->approximate(context, angleUnit); -} - Expression::Type Opposite::type() const { return Expression::Type::Opposite; } @@ -85,22 +86,4 @@ Expression * Opposite::cloneWithDifferentOperands(Expression** newOperands, return new Opposite(newOperands[0], cloneOperands); } -Expression * Opposite::evaluateOnMatrix(Matrix * m, Context& context, AngleUnit angleUnit) const { - Expression ** operands = (Expression **)malloc(m->numberOfRows() * m->numberOfColumns()*sizeof(Expression *)); - for (int i = 0; i < m->numberOfRows() * m->numberOfColumns(); i++) { - Expression * evaluation = m->operand(i)->evaluate(context, angleUnit); - assert(evaluation->type() == Type::Matrix || evaluation->type() == Type::Complex); - if (evaluation->type() == Type::Matrix) { - operands[i] = new Complex(Complex::Float(NAN)); - delete evaluation; - continue; - } - operands[i] = new Complex(Complex::Cartesian(-((Complex *)evaluation)->a(), -((Complex *)evaluation)->b())); - delete evaluation; - } - Expression * matrix = new Matrix(operands, m->numberOfRows() * m->numberOfColumns(), m->numberOfColumns(), m->numberOfRows(), false); - free(operands); - return matrix; -} - } diff --git a/poincare/src/parenthesis.cpp b/poincare/src/parenthesis.cpp index b12aefe24..57bf157e2 100644 --- a/poincare/src/parenthesis.cpp +++ b/poincare/src/parenthesis.cpp @@ -43,13 +43,7 @@ ExpressionLayout * Parenthesis::privateCreateLayout(FloatDisplayMode floatDispla return new ParenthesisLayout(m_operand->createLayout(floatDisplayMode, complexFormat)); } -float Parenthesis::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - return m_operand->approximate(context, angleUnit); -} - -Expression * Parenthesis::privateEvaluate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); +Evaluation * Parenthesis::privateEvaluate(Context& context, AngleUnit angleUnit) const { return m_operand->evaluate(context, angleUnit); } diff --git a/poincare/src/permute_coefficient.cpp b/poincare/src/permute_coefficient.cpp index cbbf20372..6c57ae133 100644 --- a/poincare/src/permute_coefficient.cpp +++ b/poincare/src/permute_coefficient.cpp @@ -25,21 +25,25 @@ Expression * PermuteCoefficient::cloneWithDifferentOperands(Expression** newOper return pc; } -float PermuteCoefficient::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - float n = m_args[0]->approximate(context, angleUnit); - float k = m_args[1]->approximate(context, angleUnit); +Evaluation * PermuteCoefficient::privateEvaluate(Context& context, AngleUnit angleUnit) const { + Evaluation * nInput = m_args[0]->evaluate(context, angleUnit); + Evaluation * kInput = m_args[1]->evaluate(context, angleUnit); + float n = nInput->toFloat(); + float k = kInput->toFloat(); + delete nInput; + delete kInput; if (isnan(n) || isnan(k) || n != (int)n || k != (int)k || n < 0.0f || k < 0.0f) { - return NAN; + + return new Complex(Complex::Float(NAN)); } if (k > n) { - return 0.0f; + return new Complex(Complex::Float(0.0f)); } float result = 1.0f; for (int i = (int)n-(int)k+1; i <= (int)n; i++) { result *= i; } - return roundf(result); + return new Complex(Complex::Float(roundf(result))); } } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 8c8c5d678..26239f5de 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -5,15 +5,11 @@ extern "C" { } #include #include +#include #include "layout/baseline_relative_layout.h" namespace Poincare { -float Power::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - return powf(m_operands[0]->approximate(context, angleUnit), m_operands[1]->approximate(context, angleUnit)); -} - Expression::Type Power::type() const { return Type::Power; } @@ -35,85 +31,68 @@ ExpressionLayout * Power::privateCreateLayout(FloatDisplayMode floatDisplayMode, return new BaselineRelativeLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat),indiceOperand->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Superscript); } -Expression * Power::evaluateOnComplex(Complex * c, Complex * d, Context& context, AngleUnit angleUnit) const { - if (d->b() != 0.0f) { +Complex Power::compute(const Complex c, const Complex d) { + if (d.b() != 0.0f) { /* First case c and d is complex */ - if (c->b() != 0.0f || c->a() <= 0) { - return new Complex(Complex::Float(NAN)); + if (c.b() != 0.0f || c.a() <= 0) { + return Complex::Float(NAN); } /* Second case only d is complex */ - float radius = powf(c->a(), d->a()); - float theta = d->b()*logf(c->a()); - return new Complex(Complex::Polar(radius, theta)); + float radius = powf(c.a(), d.a()); + float theta = d.b()*logf(c.a()); + return Complex::Polar(radius, theta); } /* Third case only c is complex */ - float radius = powf(c->r(), d->a()); - if (c->b() == 0 && d->a() == roundf(d->a())) { + float radius = powf(c.r(), d.a()); + if (c.b() == 0 && d.a() == roundf(d.a())) { /* We handle the case "c float and d integer" separatly to avoid getting * complex result due to float representation: a float power an integer is * always real. */ - return new Complex(Complex::Cartesian(radius, 0.0f)); + return Complex::Cartesian(radius, 0.0f); } - if (c->a() < 0 && c->b() == 0 && d->a() == 0.5f) { + if (c.a() < 0 && c.b() == 0 && d.a() == 0.5f) { /* We handle the case "c negative float and d = 1/2" separatly to avoid * getting wrong result due to float representation: the squared root of * a negative float is always a pure imaginative. */ - return new Complex(Complex::Cartesian(0.0f, radius)); + return Complex::Cartesian(0.0f, radius); } /* Third case only c is complex */ - float theta = d->a()*c->th(); - return new Complex(Complex::Polar(radius, theta)); + float theta = d.a()*c.th(); + return Complex::Polar(radius, theta); } -Expression * Power::evaluateOnMatrixAndComplex(Matrix * m, Complex * c, Context& context, AngleUnit angleUnit) const { - if (isnan(m_operands[1]->approximate(context, angleUnit)) || m_operands[1]->approximate(context, angleUnit) != (int)m_operands[1]->approximate(context, angleUnit)) { - return new Complex(Complex::Float(NAN)); - } +Evaluation * Power::computeOnComplexMatrixAndComplex(Evaluation * m, const Complex * c) const { if (m->numberOfColumns() != m->numberOfRows()) { return new Complex(Complex::Float(NAN)); } - float power = c->approximate(context, angleUnit); + float power = c->toFloat(); if (isnan(power) || isinf(power) || power != (int)power || fabsf(power) > k_maxNumberOfSteps) { return new Complex(Complex::Float(NAN)); } - if (power == 0.0f) { - /* Build the identity matrix with the same dimensions as m */ - return Matrix::createIdentity(m->numberOfRows()); - } if (power < 0.0f) { - Expression * inverse = m->createInverse(context, angleUnit); - Expression * operands[2]; - operands[0] = inverse; - operands[1] = new Complex(Complex::Float(-power));; - Expression * power = new Power(operands, false); - Expression * result = power->evaluate(context, angleUnit); - delete power; + Evaluation * inverse = m->createInverse(); + Complex minusC = Opposite::compute(*c); + Evaluation * result = Power::computeOnComplexMatrixAndComplex(inverse, &minusC); + delete inverse; return result; } - Expression * result = new Complex(Complex::Float(1.0f)); + Evaluation * result = ComplexMatrix::createIdentity(m->numberOfRows()); // TODO: implement a quick exponentiation for (int k = 0; k < (int)power; k++) { if (shouldStopProcessing()) { delete result; return new Complex(Complex::Float(NAN)); } - Expression * operands[2]; - operands[0] = result; - operands[1] = m; - Expression * multiplication = new Multiplication(operands, true); - Expression * newResult = multiplication->evaluate(context, angleUnit); - delete result; - result = newResult; - delete multiplication; + result = Multiplication::computeOnMatrices(result, m); } return result; } -Expression * Power::evaluateOnComplexAndMatrix(Complex * c, Matrix * m, Context& context, AngleUnit angleUnit) const { +Evaluation * Power::computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * m) const { return new Complex(Complex::Float(NAN)); } -Expression * Power::evaluateOnMatrices(Matrix * m, Matrix * n, Context& context, AngleUnit angleUnit) const { +Evaluation * Power::computeOnNumericalMatrices(Evaluation * m, Evaluation * n) const { return new Complex(Complex::Float(NAN)); } diff --git a/poincare/src/prediction_interval.cpp b/poincare/src/prediction_interval.cpp index 802a921c0..f9d4deb20 100644 --- a/poincare/src/prediction_interval.cpp +++ b/poincare/src/prediction_interval.cpp @@ -24,19 +24,20 @@ Expression * PredictionInterval::cloneWithDifferentOperands(Expression** newOper return pi; } -float PredictionInterval::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - return NAN; -} - -Expression * PredictionInterval::privateEvaluate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - float p = m_args[0]->approximate(context, angleUnit); - float n = m_args[1]->approximate(context, angleUnit); - Expression * operands[2]; - operands[0] = new Complex(Complex::Float(p - 1.96f*sqrtf(p*(1.0f-p))/sqrtf(n))); - operands[1] = new Complex(Complex::Float(p + 1.96f*sqrtf(p*(1.0f-p))/sqrtf(n))); - return new Matrix(new MatrixData(operands, 2, 2, 1, false)); +Evaluation * PredictionInterval::privateEvaluate(Context& context, AngleUnit angleUnit) const { + Evaluation * pInput = m_args[0]->evaluate(context, angleUnit); + Evaluation * nInput = m_args[1]->evaluate(context, angleUnit); + float p = pInput->toFloat(); + float n = nInput->toFloat(); + delete pInput; + delete nInput; + if (isnan(p) || isnan(n) || n != (int)n || n < 0.0f || p < 0.0f || p > 1.0f) { + return new Complex(Complex::Float(NAN)); + } + Complex operands[2]; + operands[0] = Complex::Float(p - 1.96f*sqrtf(p*(1.0f-p))/sqrtf(n)); + operands[1] = Complex::Float(p + 1.96f*sqrtf(p*(1.0f-p))/sqrtf(n)); + return new ComplexMatrix(operands, 2, 1); } } diff --git a/poincare/src/product.cpp b/poincare/src/product.cpp index d65c67314..0b0b03a2f 100644 --- a/poincare/src/product.cpp +++ b/poincare/src/product.cpp @@ -30,19 +30,18 @@ float Product::emptySequenceValue() const { return 1.0f; } -float Product::approximateWithNextTerm(float sequence, float nextTerm) const { - return sequence * nextTerm; -} - ExpressionLayout * Product::createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const { return new ProductLayout(subscriptLayout, superscriptLayout, argumentLayout); } -Expression * Product::evaluateWithNextTerm(Expression ** args, Context& context, AngleUnit angleUnit) const { - Expression * multiplication = new Multiplication(args, true); - Expression * result = multiplication->evaluate(context, angleUnit); - delete multiplication; - return result; +Evaluation * Product::evaluateWithNextTerm(Evaluation * a, Evaluation * b) const { + if (a->numberOfOperands() == 1 && b->numberOfOperands() == 1) { + return new Complex(Multiplication::compute(*(a->complexOperand(0)), *(b->complexOperand(0)))); + } + if (a->numberOfOperands() == 1) { + return Multiplication::computeOnComplexAndMatrix(a->complexOperand(0), b); + } + return Multiplication::computeOnMatrices(a, b); } } diff --git a/poincare/src/reel_part.cpp b/poincare/src/reel_part.cpp index 49a718476..9bbe25a61 100644 --- a/poincare/src/reel_part.cpp +++ b/poincare/src/reel_part.cpp @@ -25,18 +25,8 @@ Expression * ReelPart::cloneWithDifferentOperands(Expression** newOperands, return rp; } -float ReelPart::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - Expression * evaluation = m_args[0]->evaluate(context, angleUnit); - assert(evaluation->type() == Type::Matrix || evaluation->type() == Type::Complex); - float result = 0.0f; - if (evaluation->type() == Type::Matrix) { - result = NAN; - } else { - result = ((Complex *)evaluation)->a(); - } - delete evaluation; - return result; +Complex ReelPart::computeComplex(const Complex c, AngleUnit angleUnit) const { + return Complex::Float(c.a()); } } diff --git a/poincare/src/round.cpp b/poincare/src/round.cpp index dd40bdc49..999988ca8 100644 --- a/poincare/src/round.cpp +++ b/poincare/src/round.cpp @@ -24,15 +24,18 @@ Expression * Round::cloneWithDifferentOperands(Expression** newOperands, return r; } -float Round::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - float f1 = m_args[0]->approximate(context, angleUnit); - float f2 = m_args[1]->approximate(context, angleUnit); +Evaluation * Round::privateEvaluate(Context & context, AngleUnit angleUnit) const { + Evaluation * f1Entry = m_args[0]->evaluate(context, angleUnit); + Evaluation * f2Entry = m_args[1]->evaluate(context, angleUnit); + float f1 = f1Entry->toFloat(); + float f2 = f2Entry->toFloat(); + delete f1Entry; + delete f2Entry; if (isnan(f2) || f2 != (int)f2) { - return NAN; + return new Complex(Complex::Float(NAN)); } float err = powf(10.0f, (int)f2); - return roundf(f1*err)/err; + return new Complex(Complex::Float(roundf(f1*err)/err)); } } diff --git a/poincare/src/sequence.cpp b/poincare/src/sequence.cpp index 401168a12..758b5ea3d 100644 --- a/poincare/src/sequence.cpp +++ b/poincare/src/sequence.cpp @@ -17,27 +17,6 @@ Sequence::Sequence(const char * name) : { } -float Sequence::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - VariableContext nContext = VariableContext('n', &context); - Symbol nSymbol = Symbol('n'); - float start = m_args[1]->approximate(context, angleUnit); - float end = m_args[2]->approximate(context, angleUnit); - if (isnan(start) || isnan(end) || start != (int)start || end != (int)end || end - start > k_maxNumberOfSteps) { - return NAN; - } - float result = emptySequenceValue(); - for (int i = start; i <= end; i++) { - if (shouldStopProcessing()) { - return NAN; - } - Complex iExpression = Complex::Float(i); - nContext.setExpressionForSymbolName(&iExpression, &nSymbol); - result = approximateWithNextTerm(result, m_args[0]->approximate(nContext, angleUnit)); - } - return result; -} - ExpressionLayout * Sequence::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); @@ -47,30 +26,30 @@ ExpressionLayout * Sequence::privateCreateLayout(FloatDisplayMode floatDisplayMo return createSequenceLayoutWithArgumentLayouts(new HorizontalLayout(childrenLayouts, 2), m_args[2]->createLayout(floatDisplayMode, complexFormat), m_args[0]->createLayout(floatDisplayMode, complexFormat)); } -Expression * Sequence::privateEvaluate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - float start = m_args[1]->approximate(context, angleUnit); - float end = m_args[2]->approximate(context, angleUnit); +Evaluation * Sequence::privateEvaluate(Context& context, AngleUnit angleUnit) const { + Evaluation * aInput = m_args[1]->evaluate(context, angleUnit); + Evaluation * bInput = m_args[2]->evaluate(context, angleUnit); + float start = aInput->toFloat(); + float end = bInput->toFloat(); + delete aInput; + delete bInput; if (isnan(start) || isnan(end) || start != (int)start || end != (int)end || end - start > k_maxNumberOfSteps) { return new Complex(Complex::Float(NAN)); } VariableContext nContext = VariableContext('n', &context); Symbol nSymbol = Symbol('n'); - Expression * result = new Complex(Complex::Float(emptySequenceValue())); + Evaluation * result = new Complex(Complex::Float(emptySequenceValue())); for (int i = (int)start; i <= (int)end; i++) { if (shouldStopProcessing()) { delete result; return new Complex(Complex::Float(NAN)); } - Complex * iExpression = new Complex(Complex::Float(i)); - nContext.setExpressionForSymbolName(iExpression, &nSymbol); - delete iExpression; - Expression * operands[2]; - operands[0] = result; - operands[1] = m_args[0]->evaluate(nContext, angleUnit); - Expression * newResult = evaluateWithNextTerm(operands, context, angleUnit); + Complex iExpression = Complex::Float(i); + nContext.setExpressionForSymbolName(&iExpression, &nSymbol); + Evaluation * expression = m_args[0]->evaluate(nContext, angleUnit); + Evaluation * newResult = evaluateWithNextTerm(result, expression); delete result; - delete operands[1]; + delete expression; result = newResult; } return result; diff --git a/poincare/src/sine.cpp b/poincare/src/sine.cpp index ab72a6e7c..1aaad5d5c 100644 --- a/poincare/src/sine.cpp +++ b/poincare/src/sine.cpp @@ -26,25 +26,14 @@ Expression * Sine::cloneWithDifferentOperands(Expression** newOperands, return s; } -float Sine::trigonometricApproximation(float x) const { +Complex Sine::compute(const Complex c) { + Complex arg = Complex::Cartesian(-c.b(), c.a()); + Complex sinh = HyperbolicSine::compute(arg); + return Multiplication::compute(Complex::Cartesian(0.0f, -1.0f), sinh); +} + +float Sine::computeForRadianReal(float x) const { return sinf(x); } -Expression * Sine::createComplexEvaluation(Expression * exp, Context & context, AngleUnit angleUnit) const { - assert(exp->type() == Type::Complex); - Expression * arg = new Complex(Complex::Cartesian(-((Complex *)exp)->b(), ((Complex *)exp)->a())); - Function * sinh = new HyperbolicSine(); - sinh->setArgument(&arg, 1, true); - delete arg; - Expression * args[2]; - args[0] = new Complex(Complex::Cartesian(0.0f, -1.0f)); - args[1] = sinh; - Multiplication * result = new Multiplication(args, true); - delete args[0]; - delete args[1]; - Expression * resultEvaluation = result->evaluate(context, angleUnit); - delete result; - return resultEvaluation; -} - } diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index 37cdb6135..ba15c9ac6 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -26,34 +26,17 @@ Expression * SquareRoot::cloneWithDifferentOperands(Expression** newOperands, return sr; } -float SquareRoot::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - return powf(m_args[0]->approximate(context, angleUnit), 1.0f/2.0f); -} - ExpressionLayout * SquareRoot::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); return new NthRootLayout(m_args[0]->createLayout(floatDisplayMode, complexFormat),nullptr); } -Expression * SquareRoot::privateEvaluate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - Expression * evaluation = m_args[0]->evaluate(context, angleUnit); - assert(evaluation->type() == Type::Matrix || evaluation->type() == Type::Complex); - if (evaluation->type() == Type::Matrix) { - delete evaluation; - return new Complex(Complex::Float(NAN)); +Complex SquareRoot::computeComplex(const Complex c, AngleUnit angleUnit) const { + if (c.b() == 0.0f) { + return Complex::Float(sqrtf(c.a())); } - Expression * operands[2]; - operands[0] = evaluation; - operands[1] = new Complex(Complex::Float(0.5f)); - Expression * power = new Power(operands, true); - Expression * newResult = power->evaluate(context, angleUnit); - delete evaluation; - delete operands[1]; - delete power; - return newResult; + return Power::compute(c, Complex::Float(0.5f)); } } diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index 2f0a8dae0..920053aa0 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -4,6 +4,7 @@ extern "C" { } #include #include +#include #include #include #include "layout/horizontal_layout.h" @@ -71,9 +72,8 @@ ExpressionLayout * Store::privateCreateLayout(FloatDisplayMode floatDisplayMode, } -Expression * Store::privateEvaluate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - Expression * valueEvaluation = m_value->evaluate(context, angleUnit); +Evaluation * Store::privateEvaluate(Context& context, AngleUnit angleUnit) const { + Evaluation * valueEvaluation = m_value->evaluate(context, angleUnit); context.setExpressionForSymbolName(valueEvaluation, m_symbol); delete valueEvaluation; if (context.expressionForSymbol(m_symbol) != nullptr) { @@ -82,9 +82,4 @@ Expression * Store::privateEvaluate(Context& context, AngleUnit angleUnit) const return new Complex(Complex::Float(NAN)); } -float Store::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - return NAN; -} - } diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index 09d4308c2..c54a196b1 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -18,11 +18,6 @@ Expression * Subtraction::cloneWithDifferentOperands(Expression** newOperands, return new Subtraction(newOperands, cloneOperands); } -float Subtraction::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - return m_operands[0]->approximate(context, angleUnit) - m_operands[1]->approximate(context, angleUnit); -} - Expression::Type Subtraction::type() const { return Expression::Type::Subtraction; } @@ -38,15 +33,14 @@ ExpressionLayout * Subtraction::privateCreateLayout(FloatDisplayMode floatDispla return new HorizontalLayout(children_layouts, 3); } -Expression * Subtraction::evaluateOnComplex(Complex * c, Complex * d, Context& context, AngleUnit angleUnit) const { - return new Complex(Complex::Cartesian(c->a() - d->a(), c->b() - d->b())); +Complex Subtraction::compute(const Complex c, const Complex d) { + return Complex::Cartesian(c.a()-d.a(), c.b() - d.b()); } -Expression * Subtraction::evaluateOnComplexAndMatrix(Complex * c, Matrix * m, Context& context, AngleUnit angleUnit) const { - Expression * operand = evaluateOnMatrixAndComplex(m, c, context, angleUnit); - Opposite * opposite = new Opposite(operand, false); - Expression * result = opposite->evaluate(context, angleUnit); - delete opposite; +Evaluation * Subtraction::computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * m) const { + Evaluation * operand = computeOnComplexMatrixAndComplex(m, c); + Evaluation * result = Opposite::computeOnMatrix(operand); + delete operand; return result; } diff --git a/poincare/src/sum.cpp b/poincare/src/sum.cpp index 9af320eff..45a0dbeb8 100644 --- a/poincare/src/sum.cpp +++ b/poincare/src/sum.cpp @@ -30,19 +30,18 @@ float Sum::emptySequenceValue() const { return 0.0f; } -float Sum::approximateWithNextTerm(float sequence, float nextTerm) const { - return sequence + nextTerm; -} - ExpressionLayout * Sum::createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const { return new SumLayout(subscriptLayout, superscriptLayout, argumentLayout); } -Expression * Sum::evaluateWithNextTerm(Expression ** args, Context& context, AngleUnit angleUnit) const { - Expression * addition = new Addition(args, true); - Expression * result = addition->evaluate(context, angleUnit); - delete addition; - return result; +Evaluation * Sum::evaluateWithNextTerm(Evaluation * a, Evaluation * b) const { + if (a->numberOfOperands() == 1 && b->numberOfOperands() == 1) { + return new Complex(Addition::compute(*(a->complexOperand(0)), *(b->complexOperand(0)))); + } + if (a->numberOfOperands() == 1) { + return Addition::computeOnComplexAndMatrix(a->complexOperand(0), b); + } + return Addition::computeOnMatrices(a, b); } } diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 52867567c..2c4d00624 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -3,6 +3,7 @@ #include #include "layout/baseline_relative_layout.h" #include "layout/string_layout.h" +#include extern "C" { #include #include @@ -43,19 +44,9 @@ Symbol::Symbol(char name) : { } -float Symbol::privateApproximate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - if (context.expressionForSymbol(this)) { - return context.expressionForSymbol(this)->approximate(context, angleUnit); - } - // TODO: decide with Leo what we should return - return NAN; -} - -Expression * Symbol::privateEvaluate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); +Evaluation * Symbol::privateEvaluate(Context& context, AngleUnit angleUnit) const { if (context.expressionForSymbol(this) != nullptr) { - return context.expressionForSymbol(this)->evaluate(context, angleUnit); + return context.expressionForSymbol(this)->clone(); } return new Complex(Complex::Float(NAN)); } diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp index bb1cbf71c..4a5206ba7 100644 --- a/poincare/src/tangent.cpp +++ b/poincare/src/tangent.cpp @@ -29,35 +29,17 @@ Expression::Type Tangent::type() const { return Expression::Type::Tangent; } -float Tangent::trigonometricApproximation(float x) const { +float Tangent::computeForRadianReal(float x) const { return tanf(x); } -Expression * Tangent::createComplexEvaluation(Expression * exp, Context & context, AngleUnit angleUnit) const { - assert(exp->type() == Type::Complex); - Expression * arguments[2]; - arguments[0] = new Sine(); - ((Function *)arguments[0])->setArgument(&exp, 1, true); - arguments[1] = new Cosine(); - ((Function *)arguments[1])->setArgument(&exp, 1, true); - Expression * result = new Fraction(arguments, false); - Expression * resultEvaluation = result->evaluate(context, angleUnit); - delete result; - if (!isnan(((Complex *)resultEvaluation)->a()) && !isnan(((Complex *)resultEvaluation)->b())) { - return resultEvaluation; +Complex Tangent::privateCompute(const Complex c, AngleUnit angleUnit) const { + Complex result = Fraction::compute(Sine::compute(c), Cosine::compute(c)); + if (!isnan(result.a()) && !isnan(result.b())) { + return result; } - delete resultEvaluation; - arguments[0] = new Complex(Complex::Cartesian(0.0f, -1.0f)); - arguments[1] = exp; - Expression * arg = new Multiplication(arguments, true); - delete arguments[0]; - arguments[0] = new Complex(Complex::Cartesian(0.0f, 1.0f)); - arguments[1] = new HyperbolicTangent(); - ((Function *)arguments[1])->setArgument(&arg, 1, false); - result = new Multiplication(arguments, false); - resultEvaluation = result->evaluate(context, angleUnit); - delete result; - return resultEvaluation; + Complex tanh = HyperbolicTangent::compute(Multiplication::compute(Complex::Cartesian(0.0f, -1.0f), c)); + return Multiplication::compute(Complex::Cartesian(0.0f, 1.0f), tanh); } } diff --git a/poincare/src/trigonometric_function.cpp b/poincare/src/trigonometric_function.cpp index 797a6825f..d5c1ffefd 100644 --- a/poincare/src/trigonometric_function.cpp +++ b/poincare/src/trigonometric_function.cpp @@ -12,36 +12,20 @@ TrigonometricFunction::TrigonometricFunction(const char * name) : { } -float TrigonometricFunction::privateApproximate(Context& context, AngleUnit angleUnit) const { +Complex TrigonometricFunction::computeComplex(const Complex c, AngleUnit angleUnit) const { assert(angleUnit != AngleUnit::Default); - float input = m_args[0]->approximate(context, angleUnit); - if (angleUnit == AngleUnit::Degree) { - input *= M_PI/180.0f; + if (c.b() == 0.0f) { + float input = c.a(); + if (angleUnit == AngleUnit::Degree) { + input *= M_PI/180.0f; + } + float result = computeForRadianReal(input); + if (input != 0.0f && fabsf(result/input) <= 1E-7f) { + return Complex::Float(0.0f); + } + return Complex::Float(result); } - float result = trigonometricApproximation(input); - if (input != 0.0f && fabsf(result/input) <= 1E-7f) { - return 0.0f; - } - return result; -} - -Expression * TrigonometricFunction::privateEvaluate(Context& context, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - Expression * evaluation = m_args[0]->evaluate(context, angleUnit); - assert(evaluation->type() == Type::Matrix || evaluation->type() == Type::Complex); - if (evaluation->type() == Type::Matrix) { - delete evaluation; - return new Complex(Complex::Float(NAN)); - } - /* Float case */ - if (((Complex *)evaluation)->b() == 0) { - delete evaluation; - return Function::privateEvaluate(context, angleUnit); - } - /* Complex case */ - Expression * resultEvaluation = createComplexEvaluation(evaluation, context, angleUnit); - delete evaluation; - return resultEvaluation; + return privateCompute(c, angleUnit); } } diff --git a/poincare/src/variable_context.cpp b/poincare/src/variable_context.cpp index d8a0bc9ed..e2ef5e24e 100644 --- a/poincare/src/variable_context.cpp +++ b/poincare/src/variable_context.cpp @@ -11,17 +11,17 @@ VariableContext::VariableContext(char name, Context * parentContext) : { } -void VariableContext::setExpressionForSymbolName(Expression * expression, const Symbol * symbol) { +void VariableContext::setExpressionForSymbolName(Evaluation * expression, const Symbol * symbol) { if (symbol->name() == m_name) { - assert(expression->type() == Expression::Type::Complex); - /* WARNING: We assume that the evaluation of expression is a reel */ - m_value = Complex::Float(expression->approximate(*m_parentContext, Preferences::sharedPreferences()->angleUnit())); + assert(expression->numberOfOperands() == 1); + /* WARNING: We assume that the evaluation of expression is a real */ + m_value = Complex::Float(expression->toFloat()); } else { m_parentContext->setExpressionForSymbolName(expression, symbol); } } -const Expression * VariableContext::expressionForSymbol(const Symbol * symbol) { +const Evaluation * VariableContext::expressionForSymbol(const Symbol * symbol) { if (symbol->name() == m_name) { return &m_value; } else { diff --git a/poincare/test/addition.cpp b/poincare/test/addition.cpp index fb193b93a..5d58dbca5 100644 --- a/poincare/test/addition.cpp +++ b/poincare/test/addition.cpp @@ -2,100 +2,32 @@ #include #include #include +#include "helper.h" using namespace Poincare; -QUIZ_CASE(poincare_addition_approximate) { - GlobalContext globalContext; - Expression * a = Expression::parse("1+2"); - assert(a->approximate(globalContext) == 3.0f); - delete a; -} - QUIZ_CASE(poincare_addition_evaluate) { - GlobalContext globalContext; - Expression * a = Expression::parse("1+2"); - Expression * e = a->evaluate(globalContext); - assert(e->approximate(globalContext) == 3.0f); - delete a; - delete e; + Complex a[1] = {Complex::Float(3.0f)}; + assert_parsed_expression_evaluate_to("1+2", a, 1); - char expText1[8] ={'3','+',Ion::Charset::IComplex, '+', '4', '+', Ion::Charset::IComplex, 0}; - a = Expression::parse(expText1); - e = a->evaluate(globalContext); - assert(((Complex *)e)->a() == 7.0f && ((Complex *)e)->b() == 2.0f); - delete a; - delete e; + Complex b[1] = {Complex::Cartesian(6.0f, 2.0f)}; + assert_parsed_expression_evaluate_to("2+I+4+I", b, 1); #if MATRICES_ARE_DEFINED - a = Expression::parse("[[1,2][3,4][5,6]]+3"); - e = a->evaluate(globalContext); - assert(e->operand(0)->approximate(globalContext) == 4.0f); - assert(e->operand(1)->approximate(globalContext) == 5.0f); - assert(e->operand(2)->approximate(globalContext) == 6.0f); - assert(e->operand(3)->approximate(globalContext) == 7.0f); - assert(e->operand(4)->approximate(globalContext) == 8.0f); - assert(e->operand(5)->approximate(globalContext) == 9.0f); - delete a; - delete e; + Complex c[6] = {Complex::Float(4.0f), Complex::Float(5.0f), Complex::Float(6.0f), Complex::Float(7.0f), Complex::Float(8.0f), Complex::Float(9.0f)}; + assert_parsed_expression_evaluate_to("[[1,2][3,4][5,6]]+3", c, 6); - char expText2[100] ={'[','[','1',',','2','+', Ion::Charset::IComplex,']','[','3',',','4',']','[','5',',','6',']',']','+','3','+',Ion::Charset::IComplex, 0}; - a = Expression::parse(expText2); - e = a->evaluate(globalContext); - assert(((Complex *)e->operand(0))->a() == 4.0f && ((Complex *)e->operand(0))->b() == 1.0f); - assert(((Complex *)e->operand(1))->a() == 5.0f && ((Complex *)e->operand(1))->b() == 2.0f); - assert(((Complex *)e->operand(2))->a() == 6.0f && ((Complex *)e->operand(2))->b() == 1.0f); - assert(((Complex *)e->operand(3))->a() == 7.0f && ((Complex *)e->operand(3))->b() == 1.0f); - assert(((Complex *)e->operand(4))->a() == 8.0f && ((Complex *)e->operand(4))->b() == 1.0f); - assert(((Complex *)e->operand(5))->a() == 9.0f && ((Complex *)e->operand(5))->b() == 1.0f); - delete a; - delete e; + Complex d[6] = {Complex::Cartesian(4.0f, 1.0f), Complex::Cartesian(5.0f, 2.0f), Complex::Cartesian(6.0f, 1.0f), Complex::Cartesian(7.0f, 1.0f), Complex::Cartesian(8.0f, 1.0f), Complex::Cartesian(9.0f, 1.0f)}; + assert_parsed_expression_evaluate_to("[[1,2+I][3,4][5,6]]+3+I", d, 6); - a = Expression::parse("3+[[1,2][3,4][5,6]]"); - e = a->evaluate(globalContext); - assert(e->operand(0)->approximate(globalContext) == 4.0f); - assert(e->operand(1)->approximate(globalContext) == 5.0f); - assert(e->operand(2)->approximate(globalContext) == 6.0f); - assert(e->operand(3)->approximate(globalContext) == 7.0f); - assert(e->operand(4)->approximate(globalContext) == 8.0f); - assert(e->operand(5)->approximate(globalContext) == 9.0f); - delete a; - delete e; + assert_parsed_expression_evaluate_to("3+[[1,2][3,4][5,6]]", c, 6); - char expText3[100] ={'3','+',Ion::Charset::IComplex, '+','[','[','1',',','2','+', Ion::Charset::IComplex,']','[','3',',','4',']','[','5',',','6',']',']', 0}; - a = Expression::parse(expText3); - e = a->evaluate(globalContext); - assert(((Complex *)e->operand(0))->a() == 4.0f && ((Complex *)e->operand(0))->b() == 1.0f); - assert(((Complex *)e->operand(1))->a() == 5.0f && ((Complex *)e->operand(1))->b() == 2.0f); - assert(((Complex *)e->operand(2))->a() == 6.0f && ((Complex *)e->operand(2))->b() == 1.0f); - assert(((Complex *)e->operand(3))->a() == 7.0f && ((Complex *)e->operand(3))->b() == 1.0f); - assert(((Complex *)e->operand(4))->a() == 8.0f && ((Complex *)e->operand(4))->b() == 1.0f); - assert(((Complex *)e->operand(5))->a() == 9.0f && ((Complex *)e->operand(5))->b() == 1.0f); - delete a; - delete e; + assert_parsed_expression_evaluate_to("3+I+[[1,2+I][3,4][5,6]]", d, 6); - a = Expression::parse("[[1,2][3,4][5,6]]+[[1,2][3,4][5,6]]"); - e = a->evaluate(globalContext); - assert(e->operand(0)->approximate(globalContext) == 2.0f); - assert(e->operand(1)->approximate(globalContext) == 4.0f); - assert(e->operand(2)->approximate(globalContext) == 6.0f); - assert(e->operand(3)->approximate(globalContext) == 8.0f); - assert(e->operand(4)->approximate(globalContext) == 10.0f); - assert(e->operand(5)->approximate(globalContext) == 12.0f); - delete a; - delete e; + Complex e[6] = {Complex::Float(2.0f), Complex::Float(4.0f), Complex::Float(6.0f), Complex::Float(8.0f), Complex::Float(10.0f), Complex::Float(12.0f)}; + assert_parsed_expression_evaluate_to("[[1,2][3,4][5,6]]+[[1,2][3,4][5,6]]", e, 6); - char expText4[100] ={'[','[','1',',','2','+', Ion::Charset::IComplex,']','[','3',',','4',']','[','5',',','6',']',']','+', - '[','[','1',',','2','+', Ion::Charset::IComplex,']','[','3',',','4',']','[','5',',','6','+', Ion::Charset::IComplex,']',']',0}; - a = Expression::parse(expText4); - e = a->evaluate(globalContext); - assert(((Complex *)e->operand(0))->a() == 2.0f && ((Complex *)e->operand(0))->b() == 0.0f); - assert(((Complex *)e->operand(1))->a() == 4.0f && ((Complex *)e->operand(1))->b() == 2.0f); - assert(((Complex *)e->operand(2))->a() == 6.0f && ((Complex *)e->operand(2))->b() == 0.0f); - assert(((Complex *)e->operand(3))->a() == 8.0f && ((Complex *)e->operand(3))->b() == 0.0f); - assert(((Complex *)e->operand(4))->a() == 10.0f && ((Complex *)e->operand(4))->b() == 0.0f); - assert(((Complex *)e->operand(5))->a() == 12.0f && ((Complex *)e->operand(5))->b() == 1.0f); - delete a; - delete e; + Complex f[6] = {Complex::Cartesian(2.0f, 0.0f), Complex::Cartesian(4.0f, 2.0f), Complex::Cartesian(6.0f, 0.0f), Complex::Cartesian(8.0f, 0.0f), Complex::Cartesian(10.0f, 0.0f), Complex::Cartesian(12.0f, 0.0f)}; + assert_parsed_expression_evaluate_to("[[1,2+I][3,4][5,6]]+[[1,2+I][3,4][5,6]]", f, 6); #endif } diff --git a/poincare/test/complex.cpp b/poincare/test/complex.cpp index 0025c6765..c4b135124 100644 --- a/poincare/test/complex.cpp +++ b/poincare/test/complex.cpp @@ -14,7 +14,7 @@ constexpr Expression::ComplexFormat Polar = Expression::ComplexFormat::Polar; void assert_cartesian_complex_converts_to(float a, float b, const char * result, Expression::FloatDisplayMode mode = Scientific, Expression::ComplexFormat format = Cartesian, int significantDigits = 7, int bufferSize = 13+13+7+1) { int tagSize = 8; unsigned char tag = 'X'; - char * taggedBuffer = (char *)malloc(bufferSize+2*tagSize); + char * taggedBuffer = new char[bufferSize+2*tagSize]; memset(taggedBuffer, tag, bufferSize+2*tagSize); char * buffer = taggedBuffer + tagSize; @@ -47,7 +47,7 @@ void assert_cartesian_complex_converts_to(float a, float b, const char * result, assert(strcmp(buffer, result) == 0); - free(taggedBuffer); + delete[] taggedBuffer; } QUIZ_CASE(poincare_complex_to_text) { @@ -92,20 +92,16 @@ QUIZ_CASE(poincare_complex_cartesian_to_text) { assert_cartesian_complex_converts_to(64078208.0f, 119229408.0f, "1.353576E8*e^(1.07765*i)", Decimal, Polar); } -QUIZ_CASE(poincare_complex_approximate) { - GlobalContext globalContext; - Expression * a = new Complex(Complex::Float(123.456f)); - assert(a->approximate(globalContext) == 123.456f); - delete a; -} - QUIZ_CASE(poincare_complex_evaluate) { GlobalContext globalContext; Expression * a = new Complex(Complex::Float(123.456f)); - Expression * e = a->evaluate(globalContext); - assert(e->approximate(globalContext) == 123.456f); + Evaluation * m = a->evaluate(globalContext); + assert(m->complexOperand(0)->a() == 123.456f); + assert(m->complexOperand(0)->b() == 0.0f); + assert(m->numberOfOperands() == 1); + delete a; - delete e; + delete m; } QUIZ_CASE(poincare_complex_constructor) { diff --git a/poincare/test/fraction.cpp b/poincare/test/fraction.cpp index f13f5fb37..e56f2da01 100644 --- a/poincare/test/fraction.cpp +++ b/poincare/test/fraction.cpp @@ -3,62 +3,33 @@ #include #include #include +#include "helper.h" using namespace Poincare; -QUIZ_CASE(poincare_fraction_approximate) { - GlobalContext globalContext; - Expression * f = Expression::parse("1/2"); - assert(f->approximate(globalContext) == 0.5f); - delete f; -} - QUIZ_CASE(poincare_fraction_evaluate) { - GlobalContext globalContext; - Expression * a = Expression::parse("1/2"); - Expression * e = a->evaluate(globalContext); - assert(e->approximate(globalContext) == 0.5f); - delete a; - delete e; + Complex a[1] = {Complex::Float(0.5f)}; + assert_parsed_expression_evaluate_to("1/2", a, 1); - char expText1[50] ={'(','3','+',Ion::Charset::IComplex,')', '/', '(','4', '+', Ion::Charset::IComplex, ')',0}; - a = Expression::parse(expText1); - e = a->evaluate(globalContext); - assert(((Complex *)e)->a() == 13.0f/17.0f && ((Complex *)e)->b() == 1.0f/17.0f); - delete a; - delete e; + Complex b[1] = {Complex::Cartesian(13.0f/17.0f, 1.0f/17.0f)}; + assert_parsed_expression_evaluate_to("(3+I)/(4+I)", b, 1); #if MATRICES_ARE_DEFINED - a = Expression::parse("[[1,2][3,4][5,6]]/2"); - e = a->evaluate(globalContext); - assert(e->operand(0)->approximate(globalContext) == 0.5f); - assert(e->operand(1)->approximate(globalContext) == 1.0f); - assert(e->operand(2)->approximate(globalContext) == 1.5f); - assert(e->operand(3)->approximate(globalContext) == 2.0f); - assert(e->operand(4)->approximate(globalContext) == 2.5f); - assert(e->operand(5)->approximate(globalContext) == 3.0f); - delete a; - delete e; + Complex c[6] = {Complex::Float(0.5f), Complex::Float(1.0f), Complex::Float(1.5f), Complex::Float(2.0f), Complex::Float(2.5f), Complex::Float(3.0f)}; + assert_parsed_expression_evaluate_to("[[1,2][3,4][5,6]]/2", c, 6); - char expText2[100] ={'[','[','1',',','2','+', Ion::Charset::IComplex,']','[','3',',','4',']','[','5',',','6',']',']','/','(','4','+',Ion::Charset::IComplex, ')',0}; - a = Expression::parse(expText2); - e = a->evaluate(globalContext); - assert(((Complex *)e->operand(0))->a() == 4.0f/17.0f && ((Complex *)e->operand(0))->b() == -1.0f/17.0f); - assert(((Complex *)e->operand(1))->a() == 9.0f/17.0f && ((Complex *)e->operand(1))->b() == 2.0f/17.0f); - assert(((Complex *)e->operand(2))->a() == 12.0f/17.0f && ((Complex *)e->operand(2))->b() == -3.0f/17.0f); - assert(((Complex *)e->operand(3))->a() == 16.0f/17.0f && ((Complex *)e->operand(3))->b() == -4.0f/17.0f); - assert(((Complex *)e->operand(4))->a() == 20.0f/17.0f && ((Complex *)e->operand(4))->b() == -5.0f/17.0f); - assert(((Complex *)e->operand(5))->a() == 24.0f/17.0f && ((Complex *)e->operand(5))->b() == -6.0f/17.0f); - delete a; - delete e; + Complex d[6] = {Complex::Cartesian(4.0f/17.0f, -1.0f/17.0f), Complex::Cartesian(9.0f/17.0f, 2.0/17.0f), Complex::Cartesian(12.0f/17.0f, -3.0f/17.0f), Complex::Cartesian(16.0f/17.0f, -4.0f/17.0f), Complex::Cartesian(20.0f/17.0f, -5.0f/17.0f), Complex::Cartesian(24.0f/17.0f, -6.0/17.0f)}; + assert_parsed_expression_evaluate_to("[[1,2+I][3,4][5,6]]/(4+I)", d, 6); + + Complex e[4] = {Complex::Float(2.0f), Complex::Float(-1.0f), Complex::Float(1.0f), Complex::Float(0.0f)}; + assert_parsed_expression_evaluate_to("[[1,2][3,4]]/[[3,4][5,6]]", e, 4); + + Complex f[4] = {Complex::Float(-9.0f), Complex::Float(6.0f), Complex::Float(15.0f/2.0f), Complex::Float(-9.0f/2.0f)}; + assert_parsed_expression_evaluate_to("3/[[3,4][5,6]]", f, 4); + + // TODO: add this test when inverse of complex matrix is implemented + /*Complex g[4] = {Complex::Cartesian(-9.0f, -12.0f), Complex::Cartesian(6.0f, 8.0f), Complex::Cartesian(15.0f/2.0f, 10.0f), Complex::Cartesian(-9.0f/2.0f, -6.0f)}; + assert_parsed_expression_evaluate_to("(3+4i)/[[1,2+i][3,4][5,6]]", g, 4);*/ - a = Expression::parse("[[1,2][3,4]]/[[3,4][5,6]]"); - e = a->evaluate(globalContext); - assert(fabsf(e->operand(0)->approximate(globalContext) - 2.0f) < 0.000001f); - assert(fabsf(e->operand(1)->approximate(globalContext) - -1.0f) < 0.000001f); - assert(fabsf(e->operand(2)->approximate(globalContext) - 1.0f) < 0.000001f); - assert(fabsf(e->operand(3)->approximate(globalContext) - 0.0f) < 0.000001f); - delete a; - delete e; #endif } diff --git a/poincare/test/function.cpp b/poincare/test/function.cpp index b41b8c690..58610f5c7 100644 --- a/poincare/test/function.cpp +++ b/poincare/test/function.cpp @@ -3,6 +3,7 @@ #include #include #include +#include "helper.h" using namespace Poincare; @@ -143,231 +144,124 @@ QUIZ_CASE(poincare_parse_function) { } -QUIZ_CASE(poincare_function_approximate) { - GlobalContext globalContext; - Expression * e = Expression::parse("abs(-1)"); - assert(e->approximate(globalContext) == 1.0f); - delete e; - - char argText[10] = {'a', 'r', 'g', '(', '2', '+', Ion::Charset::IComplex, ')', 0}; - e = Expression::parse(argText); - assert(fabsf(e->approximate(globalContext)-atanf(0.5f)) <= 0.000001f); - delete e; - - e = Expression::parse("binomial(10, 4)"); - assert(e->approximate(globalContext) == 210.0f); - delete e; - - e = Expression::parse("ceil(0.2)"); - assert(e->approximate(globalContext) == 1.0f); - delete e; - - e = Expression::parse("diff(2*x, 2)"); - assert(e->approximate(globalContext) == 2.0f); - delete e; - -#if MATRICES_ARE_DEFINED - e = Expression::parse("det([[1,23,3][4,5,6][7,8,9]])"); - assert(fabsf(e->approximate(globalContext)-126.0f) <= 0.0001f); - delete e; -#endif - - e = Expression::parse("floor(2.3)"); - assert(e->approximate(globalContext) == 2.0f); - delete e; - - e = Expression::parse("frac(2.3)"); - assert(fabsf(e->approximate(globalContext)-0.3f) <= 0.000001f); - delete e; - - e = Expression::parse("gcd(234,394)"); - assert(e->approximate(globalContext) == 2.0f); - delete e; - - char imText[10] = {'i', 'm', '(', '2', '+', '3','*', Ion::Charset::IComplex, ')', 0}; - e = Expression::parse(imText); - assert(e->approximate(globalContext) == 3.0f); - delete e; - - e = Expression::parse("int(x, 1, 2)"); - assert(e->approximate(globalContext) == 3.0f/2.0f); - delete e; - - e = Expression::parse("lcm(234,394)"); - assert(e->approximate(globalContext) == 46098.0f); - delete e; - - e = Expression::parse("ln(2)"); - assert(e->approximate(globalContext) == logf(2.0f)); - delete e; - - e = Expression::parse("log(2)"); - assert(e->approximate(globalContext) == log10f(2.0f)); - delete e; - - e = Expression::parse("permute(10, 4)"); - assert(e->approximate(globalContext) == 5040.0f); - delete e; - - e = Expression::parse("product(n, 4, 10)"); - assert(e->approximate(globalContext) == 604800.0f); - delete e; - - e = Expression::parse("quo(29, 10)"); - assert(e->approximate(globalContext) == 2.0f); - delete e; - - char reText[10] = {'r', 'e', '(', '2', '+', Ion::Charset::IComplex, ')', 0}; - e = Expression::parse(reText); - assert(e->approximate(globalContext) == 2.0f); - delete e; - - e = Expression::parse("rem(29, 10)"); - assert(e->approximate(globalContext) == 9.0f); - delete e; - - e = Expression::parse("root(2,3)"); - assert(e->approximate(globalContext) == powf(2.0f, 1.0f/3.0f)); - delete e; - - char text[5] = {Ion::Charset::Root, '(', '2', ')', 0}; - e = Expression::parse(text); - assert(e->approximate(globalContext) == sqrtf(2.0f)); - delete e; - - e = Expression::parse("round(2.3245,3)"); - assert(e->approximate(globalContext) == 2.325f); - delete e; - - e = Expression::parse("sum(n, 4, 10)"); - assert(e->approximate(globalContext) == 49.0f); - delete e; - -#if MATRICES_ARE_DEFINED - e = Expression::parse("trace([[1,2,3][4,5,6][7,8,9]])"); - assert(e->approximate(globalContext) == 15.0f); - delete e; -#endif -} - QUIZ_CASE(poincare_function_evaluate) { - GlobalContext globalContext; - char text[11] = {'a','b','s','(','3','+','2','*',Ion::Charset::IComplex,')', 0}; - Expression * a = Expression::parse(text); - Expression * e = a->evaluate(globalContext); - assert(((Complex *)e)->a() == sqrtf(3.0f*3.0f+2.0f*2.0f) && - ((Complex *)e)->b() == 0.0f); - delete a; - delete e; + Complex a0[1] = {Complex::Float(1.0f)}; + assert_parsed_expression_evaluate_to("abs(-1)", a0, 1); - a = Expression::parse("confidence(0.1, 100)"); - e = a->evaluate(globalContext); - assert(fabsf(e->operand(0)->approximate(globalContext)- 0.1f + sqrtf(1.0f/100.0f)) <= 0.00001f); - assert(fabsf(e->operand(1)->approximate(globalContext) - 0.1f - sqrtf(1.0f/100.0f)) <= 0.00001f); - delete a; - delete e; + Complex a1[1] = {Complex::Float(sqrtf(3.0f*3.0f+2.0f*2.0f))}; + assert_parsed_expression_evaluate_to("abs(3+2I)", a1, 1); + + Complex a2[4] = {Complex::Float(1.0f), Complex::Float(2.0f), Complex::Float(3.0f), Complex::Float(4.0f)}; + assert_parsed_expression_evaluate_to("abs([[1,-2][3,-4]])", a2, 4); + + Complex a3[4] = {Complex::Float(sqrtf(3.0f*3.0f+2.0f*2.0f)), Complex::Float(sqrtf(3.0f*3.0f+4.0f*4.0f)), Complex::Float(sqrtf(5.0f*5.0f+2.0f*2.0f)), Complex::Float(sqrtf(3.0f*3.0f+2.0f*2.0f))}; + assert_parsed_expression_evaluate_to("abs([[3+2I,3+4I][5+2I,3+2I]])", a3, 4); + + Complex b[1] = {Complex::Float(210.0f)}; + assert_parsed_expression_evaluate_to("binomial(10, 4)", b, 1); + + Complex c[1] = {Complex::Float(1.0f)}; + assert_parsed_expression_evaluate_to("ceil(0.2)", c, 1); + + Complex d[1] = {Complex::Float(2.0f)}; + assert_parsed_expression_evaluate_to("diff(2*x, 2)", d, 1); #if MATRICES_ARE_DEFINED - a = Expression::parse("dim([[1,2,3][4,5,-6]])"); - e = a->evaluate(globalContext); - assert(fabsf(e->operand(0)->approximate(globalContext)-2.0f) <= 0.00001f); - assert(fabsf(e->operand(1)->approximate(globalContext) -3.0f) <= 0.00001f); - delete a; - delete e; + Complex e[1] = {Complex::Float(126.0f)}; + assert_parsed_expression_evaluate_to("det([[1,23,3][4,5,6][7,8,9]])", e, 1); #endif - char conjText[20] ={'c','o', 'n','j', '(', '3', '+', '2', '*', Ion::Charset::IComplex, ')', 0}; - a = Expression::parse(conjText); - e = a->evaluate(globalContext); - assert(fabsf(3.0f - ((Complex *)e)->a()) <= 0.00001f && - fabsf(-2.0f - ((Complex *)e)->b()) <= 0.00001f); - delete a; - delete e; + Complex f[1] = {Complex::Float(2.0f)}; + assert_parsed_expression_evaluate_to("floor(2.3)", f, 1); + + Complex g[1] = {Complex::Float(0.3f)}; + assert_parsed_expression_evaluate_to("frac(2.3)", g, 1); + + Complex h[1] = {Complex::Float(2.0f)}; + assert_parsed_expression_evaluate_to("gcd(234,394)", h, 1); + + Complex i[1] = {Complex::Float(3.0f)}; + assert_parsed_expression_evaluate_to("im(2+3I)", i, 1); + + Complex j[1] = {Complex::Float(3.0f/2.0f)}; + assert_parsed_expression_evaluate_to("int(x, 1, 2)", j, 1); + + Complex k[1] = {Complex::Float(46098.0f)}; + assert_parsed_expression_evaluate_to("lcm(234,394)", k, 1); + + Complex l[1] = {Complex::Float(logf(2.0f))}; + assert_parsed_expression_evaluate_to("ln(2)", l, 1); + + Complex m[1] = {Complex::Float(log10f(2.0f))}; + assert_parsed_expression_evaluate_to("log(2)", m, 1); + + Complex n[1] = {Complex::Float(5040.0f)}; + assert_parsed_expression_evaluate_to("permute(10, 4)", n, 1); + + Complex o[1] = {Complex::Float(604800.0f)}; + assert_parsed_expression_evaluate_to("product(n, 4, 10)", o, 1); + + Complex p[1] = {Complex::Float(2.0f)}; + assert_parsed_expression_evaluate_to("re(2+I)", p, 1); + + Complex q[1] = {Complex::Float(9.0f)}; + assert_parsed_expression_evaluate_to("rem(29, 10)", q, 1); + + Complex r[1] = {Complex::Float(powf(2.0f, 1.0f/3.0f))}; + assert_parsed_expression_evaluate_to("root(2,3)", r, 1); + + Complex s[1] = {Complex::Float(sqrtf(2.0f))}; + assert_parsed_expression_evaluate_to("R(2)", s, 1); + + Complex t[1] = {Complex::Float(49.0f)}; + assert_parsed_expression_evaluate_to("sum(n, 4, 10)", t, 1); #if MATRICES_ARE_DEFINED - a = Expression::parse("inverse([[1,2,3][4,5,-6][7,8,9]])"); - e = a->evaluate(globalContext); - assert(fabsf(e->operand(0)->approximate(globalContext)-(-31.0f/24.0f)) <= 0.00001f); - assert(fabsf(e->operand(1)->approximate(globalContext) -(-1.0f/12.0f)) <= 0.00001f); - assert(fabsf(e->operand(2)->approximate(globalContext) -(3.0f/8.0f)) <= 0.00001f); - assert(fabsf(e->operand(3)->approximate(globalContext) -(13.0f/12.0f)) <= 0.00001f); - assert(fabsf(e->operand(4)->approximate(globalContext) -(1.0f/6.0f)) <= 0.00001f); - assert(fabsf(e->operand(5)->approximate(globalContext) -(-1.0f/4.0f)) <= 0.00001f); - assert(fabsf(e->operand(6)->approximate(globalContext) -(1.0f/24.0f)) <= 0.00001f); - assert(fabsf(e->operand(7)->approximate(globalContext) -(-1.0f/12.0f)) <= 0.00001f); - assert(fabsf(e->operand(8)->approximate(globalContext) -(1.0f/24.0f)) <= 0.00001f); - delete a; - delete e; + Complex u[1] = {Complex::Float(15.0f)}; + assert_parsed_expression_evaluate_to("trace([[1,2,3][4,5,6][7,8,9]])", u, 1); #endif - a = Expression::parse("prediction(0.1, 100)"); - e = a->evaluate(globalContext); - assert(fabsf(e->operand(0)->approximate(globalContext)- 0.1f + sqrtf(1.0f/100.0f)) <= 0.00001f); - assert(fabsf(e->operand(1)->approximate(globalContext) - 0.1f - sqrtf(1.0f/100.0f)) <= 0.00001f); - delete a; - delete e; - - a = Expression::parse("prediction95(0.1, 100)"); - e = a->evaluate(globalContext); - assert(fabsf(e->operand(0)->approximate(globalContext)- 0.1f + 1.96f*sqrtf((0.1f*0.9f)/100.0f)) <= 0.00001f); - assert(fabsf(e->operand(1)->approximate(globalContext) - 0.1f - 1.96f*sqrtf((0.1f*0.9f)/100.0f)) <= 0.00001f); - delete a; - delete e; - - char productText[20] ={'p', 'r', 'o', 'd', 'u', 'c', 't', '(', '2', '+', 'n', '*', Ion::Charset::IComplex, ',', '1', ',','5',')', 0}; - a = Expression::parse(productText); - e = a->evaluate(globalContext); - assert(fabsf(-100.0f - ((Complex *)e)->a()) <= 0.00001f && - fabsf(-540.0f - ((Complex *)e)->b()) <= 0.00001f); - delete a; - delete e; - - char rooText1[20] ={'r','o','o','t', '(', '3', '+', Ion::Charset::IComplex, ',', '3',')', 0}; - a = Expression::parse(rooText1); - e = a->evaluate(globalContext); - assert(fabsf(1.4593656008f - ((Complex *)e)->a()) <= 0.00001f && - fabsf(0.1571201229f - ((Complex *)e)->b()) <= 0.00001f); - delete e; - - char rooText2[20] ={'r','o','o','t', '(', '3', ',','3', '+', Ion::Charset::IComplex, ')', 0}; - a = Expression::parse(rooText2); - e = a->evaluate(globalContext); - assert(fabsf(1.38200696233f - ((Complex *)e)->a()) <= 0.00001f && - fabsf(-0.152442779f - ((Complex *)e)->b()) <= 0.00001f); - delete e; - - - char text2[20] ={Ion::Charset::Root, '(', '3', '+', Ion::Charset::IComplex,')', 0}; - a = Expression::parse(text2); - e = a->evaluate(globalContext); - assert((1.75532f - 0.00001f) <= (((Complex *)e)->a()) && - (((Complex *)e)->a()) <= (1.75532f + 0.00001f) && - 0.28485f - 0.00001f <= (((Complex *)e)->b()) && - (((Complex *)e)->b()) <= 0.28485f + 0.00001f); - delete a; - delete e; - - char sumText[20] ={'s', 'u', 'm', '(', '2', '+', 'n', '*', Ion::Charset::IComplex, ',', '1', ',','5',')', 0}; - a = Expression::parse(sumText); - e = a->evaluate(globalContext); - assert(fabsf(10.0f - ((Complex *)e)->a()) <= 0.00001f && - fabsf(15.0f - ((Complex *)e)->b()) <= 0.00001f); - delete a; - delete e; + Complex v[2] = {Complex::Float(0.1f - sqrtf(1.0f/100.0f)), Complex::Float(0.1f + sqrtf(1.0f/100.0f))}; + assert_parsed_expression_evaluate_to("confidence(0.1, 100)", v, 2); #if MATRICES_ARE_DEFINED - a = Expression::parse("transpose([[1,2,3][4,5,-6][7,8,9]])"); - e = a->evaluate(globalContext); - assert(fabsf(e->operand(0)->approximate(globalContext)-1.0f) <= 0.00001f); - assert(fabsf(e->operand(1)->approximate(globalContext) -4.0f) <= 0.00001f); - assert(fabsf(e->operand(2)->approximate(globalContext) -7.0f) <= 0.00001f); - assert(fabsf(e->operand(3)->approximate(globalContext) -2.0f) <= 0.00001f); - assert(fabsf(e->operand(4)->approximate(globalContext) -5.0f) <= 0.00001f); - assert(fabsf(e->operand(5)->approximate(globalContext) -8.0f) <= 0.00001f); - assert(fabsf(e->operand(6)->approximate(globalContext) -3.0f) <= 0.00001f); - assert(fabsf(e->operand(7)->approximate(globalContext) -(-6.0f)) <= 0.00001f); - assert(fabsf(e->operand(8)->approximate(globalContext) -9.0f) <= 0.00001f); - delete a; - delete e; + Complex w[2] = {Complex::Float(2.0f), Complex::Float(3.0f)}; + assert_parsed_expression_evaluate_to("dim([[1,2,3][4,5,-6]])", w, 2); #endif + + Complex x[1] = {Complex::Cartesian(3.0f, -2.0f)}; + assert_parsed_expression_evaluate_to("conj(3+2*I)", x, 1); + +#if MATRICES_ARE_DEFINED + Complex y[9] = {Complex::Float(-31.0f/24.0f), Complex::Float(-1.0f/12.0f), Complex::Float(3.0f/8.0f), Complex::Float(13.0f/12.0f), Complex::Float(1.0f/6.0f), Complex::Float(-1.0f/4.0f), Complex::Float(1.0f/24.0f),Complex::Float(-1.0f/12.0f), Complex::Float(1.0f/24.0f)}; + assert_parsed_expression_evaluate_to("inverse([[1,2,3][4,5,-6][7,8,9]])", y, 9); +#endif + + Complex z[2] = {Complex::Float(0.1f-sqrtf(1.0f/100.0f)), Complex::Float(0.1f+sqrtf(1.0f/100.0f))}; + assert_parsed_expression_evaluate_to("prediction(0.1, 100)", z, 2); + + Complex aa[2] = {Complex::Float(0.1f-1.96f*sqrtf((0.1f*(1.0f-0.1f))/100.0f)), Complex::Float(0.1f+1.96f*sqrtf((0.1f*(1.0f-0.1f))/100.0f))}; + assert_parsed_expression_evaluate_to("prediction95(0.1, 100)", aa, 2); + + Complex ab[1] = {Complex::Cartesian(-100.0f, -540.0f)}; + assert_parsed_expression_evaluate_to("product(2+n*I, 1, 5)", ab, 1); + + Complex ac[1] = {Complex::Cartesian(1.4593656008f, 0.1571201229f)}; + assert_parsed_expression_evaluate_to("root(3+I, 3)", ac, 1); + + Complex ad[1] = {Complex::Cartesian(1.38200696233f, -0.152442779f)}; + assert_parsed_expression_evaluate_to("root(3, 3+I)", ad, 1); + + Complex ae[1] = {Complex::Cartesian(1.75532f, 0.28485f)}; + assert_parsed_expression_evaluate_to("R(3+I)", ae, 1); + + Complex af[1] = {Complex::Cartesian(10.0f, 15.0f)}; + assert_parsed_expression_evaluate_to("sum(2+n*I,1,5)", af, 1); +#if MATRICES_ARE_DEFINED + Complex ag[9] = {Complex::Float(1.0f), Complex::Float(4.0f), Complex::Float(7.0f), Complex::Float(2.0f), Complex::Float(5.0f), Complex::Float(8.0f), Complex::Float(3.0f), Complex::Float(-6.0f), Complex::Float(9.0f)}; + assert_parsed_expression_evaluate_to("transpose([[1,2,3][4,5,-6][7,8,9]])", ag, 9); +#endif + + Complex ah[1] = {Complex::Float(2.325f)}; + assert_parsed_expression_evaluate_to("round(2.3245,3)", ah, 1); } diff --git a/poincare/test/helper.cpp b/poincare/test/helper.cpp new file mode 100644 index 000000000..efc85ed47 --- /dev/null +++ b/poincare/test/helper.cpp @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include +#include + +using namespace Poincare; + +void assert_parsed_expression_evaluate_to(const char * expression, Complex * results, int numberOfEntries, Expression::AngleUnit angleUnit) { + char buffer[200]; + strlcpy(buffer, expression, 200); + for (size_t i=0; ievaluate(globalContext, angleUnit); + for (int i = 0; i < numberOfEntries; i++) { + assert(fabsf(m->complexOperand(i)->a() - results[i].a()) < 0.0001f); + assert(fabsf(m->complexOperand(i)->b() - results[i].b()) < 0.0001f); + } + delete a; + delete m; +} diff --git a/poincare/test/helper.h b/poincare/test/helper.h new file mode 100644 index 000000000..bf15fca49 --- /dev/null +++ b/poincare/test/helper.h @@ -0,0 +1,6 @@ +#include + +constexpr Poincare::Expression::AngleUnit Degree = Poincare::Expression::AngleUnit::Degree; +constexpr Poincare::Expression::AngleUnit Radian = Poincare::Expression::AngleUnit::Radian; + +void assert_parsed_expression_evaluate_to(const char * expression, Poincare::Complex * results, int numberOfEntries, Poincare::Expression::AngleUnit angleUnit = Degree); diff --git a/poincare/test/integer.cpp b/poincare/test/integer.cpp index 0852e7ef9..7a54d409d 100644 --- a/poincare/test/integer.cpp +++ b/poincare/test/integer.cpp @@ -52,33 +52,20 @@ QUIZ_CASE(poincare_integer_divide) { assert(Integer("3293920983029832").divide_by(Integer("389090928")) == Integer("8465684")); } -QUIZ_CASE(poincare_integer_approximate) { +void assert_integer_evals_to(int i, float result) { GlobalContext globalContext; - assert(Integer(1).approximate(globalContext) == 1.0f); - assert(Integer("12345678").approximate(globalContext) == 12345678.0f); - assert(Integer("0").approximate(globalContext) == 0); - assert(Integer("-0").approximate(globalContext) == -0); - assert(Integer(-1).approximate(globalContext) == -1); + Evaluation * m = Integer(i).evaluate(globalContext); + assert(m->complexOperand(0)->a() == result); + assert(m->complexOperand(0)->b() == 0.0f); + assert(m->numberOfOperands() == 1); + delete m; } QUIZ_CASE(poincare_integer_evaluate) { - GlobalContext globalContext; - Expression * e = Integer(1).evaluate(globalContext); - assert(e->approximate(globalContext) == 1.0f); - delete e; - e = Integer(12345678).evaluate(globalContext); - assert(e->approximate(globalContext) == 12345678.0f); - delete e; - e = Integer(0).evaluate(globalContext); - assert(e->approximate(globalContext) == 0.0f); - delete e; - e = Integer(-0).evaluate(globalContext); - assert(e->approximate(globalContext) == 0.0f); - delete e; - e = Integer(-0).evaluate(globalContext); - assert(e->approximate(globalContext) == 0.0f); - delete e; - e = Integer(-1).evaluate(globalContext); - assert(e->approximate(globalContext) == -1.0f); - delete e; + assert_integer_evals_to(1, 1.0f); + assert_integer_evals_to(12345678, 12345678.0f); + assert_integer_evals_to(0, 0.0f); + assert_integer_evals_to(-0, 0.0f); + assert_integer_evals_to(-1, -1.0f); + assert_integer_evals_to(12345678, 12345678.0f); } diff --git a/poincare/test/matrix.cpp b/poincare/test/matrix.cpp index ae5d01695..a099a677a 100644 --- a/poincare/test/matrix.cpp +++ b/poincare/test/matrix.cpp @@ -1,19 +1,13 @@ #include #include #include +#include "helper.h" using namespace Poincare; QUIZ_CASE(poincare_matrix_evaluate) { #if MATRICES_ARE_DEFINED - GlobalContext globalContext; - Expression * f = Expression::parse("[[1,2,3][4,5,6]]"); - assert(f->operand(0)->approximate(globalContext) == 1.0f); - assert(f->operand(1)->approximate(globalContext) == 2.0f); - assert(f->operand(2)->approximate(globalContext) == 3.0f); - assert(f->operand(3)->approximate(globalContext) == 4.0f); - assert(f->operand(4)->approximate(globalContext) == 5.0f); - assert(f->operand(5)->approximate(globalContext) == 6.0f); - delete f; + Complex a[6] = {Complex::Float(1.0f), Complex::Float(2.0f), Complex::Float(3.0f), Complex::Float(4.0f), Complex::Float(5.0f), Complex::Float(6.0f)}; + assert_parsed_expression_evaluate_to("[[1,2,3][4,5,6]]", a, 6); #endif } diff --git a/poincare/test/parser.cpp b/poincare/test/parser.cpp index c4c85ce00..2ee8e23db 100644 --- a/poincare/test/parser.cpp +++ b/poincare/test/parser.cpp @@ -3,43 +3,35 @@ #include #include #include +#include "helper.h" using namespace Poincare; -constexpr Expression::AngleUnit Degree = Expression::AngleUnit::Degree; -constexpr Expression::AngleUnit Radian = Expression::AngleUnit::Radian; - -void assert_expression_parses_to(const char * text, float result, Context * context, Expression::AngleUnit angleUnit = Degree) { - char buffer_text[100] = {}; - for (uint32_t i=0; iapproximate(*context, angleUnit) - result) < 0.0001f); -} - QUIZ_CASE(poincare_parser) { - GlobalContext globalContext; - assert_expression_parses_to("1.2*e^(1)", 1.2*M_E, &globalContext); - assert_expression_parses_to("e^2*e^(1)", powf(M_E, 2.0f)*M_E, &globalContext); - assert_expression_parses_to("2*3^4+2", 2.0f*powf(3.0f, 4.0f)+2.0f, &globalContext); - assert_expression_parses_to("-2*3^4+2", -2.0f*powf(3.0f, 4.0f)+2.0f, &globalContext); - assert_expression_parses_to("-sin(3)*2-3", -sinf(3.0f)*2.0f-3.0f, &globalContext, Radian); - assert_expression_parses_to("-.003", -0.003f, &globalContext); - assert_expression_parses_to(".02E2", 2.0f, &globalContext); - assert_expression_parses_to("5-2/3", 5.0f-2.0f/3.0f, &globalContext); - assert_expression_parses_to("2/3-5", 2.0f/3.0f-5.0f, &globalContext); - assert_expression_parses_to("-2/3-5", -2.0f/3.0f-5.0f, &globalContext); - assert_expression_parses_to("sin(3)2(4+2)", sinf(3.0f)*2.0f*(4.0f+2.0f), &globalContext, Radian); - assert_expression_parses_to("4/2*(2+3)", 4.0f/2.0f*(2.0f+3.0f), &globalContext, Radian); - assert_expression_parses_to("4/2*(2+3)", 4.0f/2.0f*(2.0f+3.0f), &globalContext, Radian); + Complex a[1] = {Complex::Float(1.2f*M_E)}; + assert_parsed_expression_evaluate_to("1.2*X^(1)", a, 1); + Complex b[1] = {Complex::Float(powf(M_E, 2.0f)*M_E)}; + assert_parsed_expression_evaluate_to("X^2*X^(1)", b, 1); + Complex c[1] = {Complex::Float(2.0f*powf(3.0f, 4.0f)+2.0f)}; + assert_parsed_expression_evaluate_to("2*3^4+2", c, 1); + Complex d[1] = {Complex::Float(-2.0f*powf(3.0f, 4.0f)+2.0f)}; + assert_parsed_expression_evaluate_to("-2*3^4+2", d,1); + Complex e[1] = {Complex::Float(-sinf(3.0f)*2.0f-3.0f)}; + assert_parsed_expression_evaluate_to("-sin(3)*2-3", e, 1, Radian); + Complex f[1] = {Complex::Float(-0.003f)}; + assert_parsed_expression_evaluate_to("-.003", f, 1); + Complex g[1] = {Complex::Float(2.0f)}; + assert_parsed_expression_evaluate_to(".02E2", g, 1); + Complex h[1] = {Complex::Float(5.0f-2.0f/3.0f)}; + assert_parsed_expression_evaluate_to("5-2/3", h, 1); + Complex i[1] = {Complex::Float(2.0f/3.0f-5.0f)}; + assert_parsed_expression_evaluate_to("2/3-5", i, 1); + Complex j[1] = {Complex::Float(-2.0f/3.0f-5.0f)}; + assert_parsed_expression_evaluate_to("-2/3-5", j, 1); + Complex k[1] = {Complex::Float(sinf(3.0f)*2.0f*(4.0f+2.0f))}; + assert_parsed_expression_evaluate_to("sin(3)2(4+2)", k, 1, Radian); + Complex l[1] = {Complex::Float(4.0f/2.0f*(2.0f+3.0f))}; + assert_parsed_expression_evaluate_to("4/2*(2+3)", l, 1, Radian); + Complex m[1] = {Complex::Float(4.0f/2.0f*(2.0f+3.0f))}; + assert_parsed_expression_evaluate_to("4/2*(2+3)", m, 1, Radian); } diff --git a/poincare/test/power.cpp b/poincare/test/power.cpp index 24d65b352..344ef7937 100644 --- a/poincare/test/power.cpp +++ b/poincare/test/power.cpp @@ -2,47 +2,22 @@ #include #include #include +#include "helper.h" using namespace Poincare; -QUIZ_CASE(poincare_power_approximate) { - GlobalContext globalContext; - Expression * p = Expression::parse("2^3"); - assert(p->approximate(globalContext) == 8.0f); - delete p; -} - QUIZ_CASE(poincare_power_evaluate) { - GlobalContext globalContext; - Expression * a = Expression::parse("2^3"); - Expression * e = a->evaluate(globalContext); - assert(e->approximate(globalContext) == 8.0f); - delete a; - delete e; + Complex a[1] = {Complex::Float(8.0f)}; + assert_parsed_expression_evaluate_to("2^3", a, 1); - char expText1[15] ={'(','3','+',Ion::Charset::IComplex, ')', '^', '4', 0}; - a = Expression::parse(expText1); - e = a->evaluate(globalContext); - assert(28.0f - 0.00001f <= (((Complex *)e)->a()) && (((Complex *)e)->a()) <= 28.0f + 0.00001f && - 96.0f - 0.00001f <= (((Complex *)e)->b()) && (((Complex *)e)->b()) <= 96.0f + 0.00001f); - delete a; - delete e; + Complex b[1] = {Complex::Cartesian(28.0f, 96.0f)}; + assert_parsed_expression_evaluate_to("(3+I)^4", b, 1); - char expText2[15] ={'4', '^','(','3','+',Ion::Charset::IComplex, ')', 0}; - a = Expression::parse(expText2); - e = a->evaluate(globalContext); - assert(((Complex *)e)->a() == 11.7412464f && ((Complex *)e)->b() == 62.9137754f); - delete a; - delete e; + Complex c[1] = {Complex::Cartesian(11.7412464f, 62.9137754f)}; + assert_parsed_expression_evaluate_to("4^(3+I)", c, 1); #if MATRICES_ARE_DEFINED - a = Expression::parse("[[1,2][3,4]]^3"); - e = a->evaluate(globalContext); - assert(e->operand(0)->approximate(globalContext) == 37.0f); - assert(e->operand(1)->approximate(globalContext) == 54.0f); - assert(e->operand(2)->approximate(globalContext) == 81.0f); - assert(e->operand(3)->approximate(globalContext) == 118.0f); - delete a; - delete e; + Complex d[4] = {Complex::Float(37.0f), Complex::Float(54.0f), Complex::Float(81.0f), Complex::Float(118.0f)}; + assert_parsed_expression_evaluate_to("[[1,2][3,4]]^3", d, 4); #endif } diff --git a/poincare/test/product.cpp b/poincare/test/product.cpp index e92da9927..6b3e298e9 100644 --- a/poincare/test/product.cpp +++ b/poincare/test/product.cpp @@ -2,113 +2,32 @@ #include #include #include +#include "helper.h" using namespace Poincare; -QUIZ_CASE(poincare_product_approximate) { - GlobalContext globalContext; - Expression * p = Expression::parse("1*2"); - assert(p->approximate(globalContext) == 2.0f); - delete p; -} - QUIZ_CASE(poincare_product_evaluate) { - GlobalContext globalContext; - Expression * a = Expression::parse("1*2"); - Expression * e = a->evaluate(globalContext); - assert(e->approximate(globalContext) == 2.0f); - delete a; - delete e; + Complex a[1] = {Complex::Float(2.0f)}; + assert_parsed_expression_evaluate_to("1*2", a, 1); - char expText1[15] ={'(','3','+',Ion::Charset::IComplex, ')', '*', '(','4', '+', Ion::Charset::IComplex, ')', 0}; - a = Expression::parse(expText1); - e = a->evaluate(globalContext); - assert(((Complex *)e)->a() == 11.0f && ((Complex *)e)->b() == 7.0f); - delete a; - delete e; + Complex b[1] = {Complex::Cartesian(11.0f, 7.0f)}; + assert_parsed_expression_evaluate_to("(3+I)*(4+I)", b, 1); #if MATRICES_ARE_DEFINED - a = Expression::parse("[[1,2][3,4][5,6]]*2"); - e = a->evaluate(globalContext); - assert(e->operand(0)->approximate(globalContext) == 2.0f); - assert(e->operand(1)->approximate(globalContext) == 4.0f); - assert(e->operand(2)->approximate(globalContext) == 6.0f); - assert(e->operand(3)->approximate(globalContext) == 8.0f); - assert(e->operand(4)->approximate(globalContext) == 10.0f); - assert(e->operand(5)->approximate(globalContext) == 12.0f); - delete a; - delete e; + Complex c[6] = {Complex::Float(2.0f), Complex::Float(4.0f), Complex::Float(6.0f), Complex::Float(8.0f), Complex::Float(10.0f), Complex::Float(12.0f)}; + assert_parsed_expression_evaluate_to("[[1,2][3,4][5,6]]*2", c, 6); + Complex d[6] = {Complex::Cartesian(3.0f, 1.0f), Complex::Cartesian(5.0f, 5.0f), Complex::Cartesian(9.0f, 3.0f), Complex::Cartesian(12.0f, 4.0f), Complex::Cartesian(15.0f, 5.0f), Complex::Cartesian(18.0f, 6.0f)}; + assert_parsed_expression_evaluate_to("[[1,2+I][3,4][5,6]]*(3+I)", d, 6); - char expText2[100] ={'[','[','1',',','2','+', Ion::Charset::IComplex,']','[','3',',','4',']','[','5',',','6',']',']','*', '(','3','+',Ion::Charset::IComplex, ')', 0}; - a = Expression::parse(expText2); - e = a->evaluate(globalContext); - assert(((Complex *)e->operand(0))->a() == 3.0f && ((Complex *)e->operand(0))->b() == 1.0f); - assert(((Complex *)e->operand(1))->a() == 5.0f && ((Complex *)e->operand(1))->b() == 5.0f); - assert(((Complex *)e->operand(2))->a() == 9.0f && ((Complex *)e->operand(2))->b() == 3.0f); - assert(((Complex *)e->operand(3))->a() == 12.0f && ((Complex *)e->operand(3))->b() == 4.0f); - assert(((Complex *)e->operand(4))->a() == 15.0f && ((Complex *)e->operand(4))->b() == 5.0f); - assert(((Complex *)e->operand(5))->a() == 18.0f && ((Complex *)e->operand(5))->b() == 6.0f); - delete a; - delete e; + assert_parsed_expression_evaluate_to("2*[[1,2][3,4][5,6]]", c, 6); - a = Expression::parse("3*[[1,2][3,4][5,6]]"); - e = a->evaluate(globalContext); - assert(e->operand(0)->approximate(globalContext) == 3.0f); - assert(e->operand(1)->approximate(globalContext) == 6.0f); - assert(e->operand(2)->approximate(globalContext) == 9.0f); - assert(e->operand(3)->approximate(globalContext) == 12.0f); - assert(e->operand(4)->approximate(globalContext) == 15.0f); - assert(e->operand(5)->approximate(globalContext) == 18.0f); - delete a; - delete e; + assert_parsed_expression_evaluate_to("(3+I)*[[1,2+I][3,4][5,6]]", d, 6); - char expText3[100] ={'(','3','+',Ion::Charset::IComplex, ')','*','[','[','1',',','2','+', Ion::Charset::IComplex,']','[','3',',','4',']','[','5',',','6',']',']', 0}; - a = Expression::parse(expText3); - e = a->evaluate(globalContext); - assert(((Complex *)e->operand(0))->a() == 3.0f && ((Complex *)e->operand(0))->b() == 1.0f); - assert(((Complex *)e->operand(1))->a() == 5.0f && ((Complex *)e->operand(1))->b() == 5.0f); - assert(((Complex *)e->operand(2))->a() == 9.0f && ((Complex *)e->operand(2))->b() == 3.0f); - assert(((Complex *)e->operand(3))->a() == 12.0f && ((Complex *)e->operand(3))->b() == 4.0f); - assert(((Complex *)e->operand(4))->a() == 15.0f && ((Complex *)e->operand(4))->b() == 5.0f); - assert(((Complex *)e->operand(5))->a() == 18.0f && ((Complex *)e->operand(5))->b() == 6.0f); - delete a; - delete e; + Complex e[12] = {Complex::Float(11.0f), Complex::Float(14.0f), Complex::Float(17.0f), Complex::Float(20.0f), Complex::Float(23.0f), Complex::Float(30.0f), Complex::Float(37.0f), Complex::Float(44.0f), Complex::Float(35.0f), Complex::Float(46.0f), Complex::Float(57.0f), Complex::Float(68.0f)}; + assert_parsed_expression_evaluate_to("[[1,2][3,4][5,6]]*[[1,2,3,4][5,6,7,8]]", e, 12); - a = Expression::parse("[[1,2][3,4][5,6]]*[[1,2,3,4][5,6,7,8]]"); - e = a->evaluate(globalContext); - assert(e->operand(0)->approximate(globalContext) == 11.0f); - assert(e->operand(1)->approximate(globalContext) == 14.0f); - assert(e->operand(2)->approximate(globalContext) == 17.0f); - assert(e->operand(3)->approximate(globalContext) == 20.0f); - assert(e->operand(4)->approximate(globalContext) == 23.0f); - assert(e->operand(5)->approximate(globalContext) == 30.0f); - assert(e->operand(6)->approximate(globalContext) == 37.0f); - assert(e->operand(7)->approximate(globalContext) == 44.0f); - assert(e->operand(8)->approximate(globalContext) == 35.0f); - assert(e->operand(9)->approximate(globalContext) == 46.0f); - assert(e->operand(10)->approximate(globalContext) == 57.0f); - assert(e->operand(11)->approximate(globalContext) == 68.0f); - delete a; - delete e; - - char expText4[100] ={'[','[','1',',','2','+', Ion::Charset::IComplex,']','[','3',',','4',']','[','5',',','6',']',']','*', - '[','[','1',',','2','+', Ion::Charset::IComplex,',','3',',','4',']','[','5',',','6','+', Ion::Charset::IComplex,',', '7',',','8',']',']',0}; - a = Expression::parse(expText4); - e = a->evaluate(globalContext); - assert(((Complex *)e->operand(0))->a() == 11.0f && ((Complex *)e->operand(0))->b() == 5.0f); - assert(((Complex *)e->operand(1))->a() == 13.0f && ((Complex *)e->operand(1))->b() == 9.0f); - assert(((Complex *)e->operand(2))->a() == 17.0f && ((Complex *)e->operand(2))->b() == 7.0f); - assert(((Complex *)e->operand(3))->a() == 20.0f && ((Complex *)e->operand(3))->b() == 8.0f); - assert(((Complex *)e->operand(4))->a() == 23.0f && ((Complex *)e->operand(4))->b() == 0.0f); - assert(((Complex *)e->operand(5))->a() == 30.0f && ((Complex *)e->operand(5))->b() == 7.0f); - assert(((Complex *)e->operand(6))->a() == 37.0f && ((Complex *)e->operand(6))->b() == 0.0f); - assert(((Complex *)e->operand(7))->a() == 44.0f && ((Complex *)e->operand(7))->b() == 0.0f); - assert(((Complex *)e->operand(8))->a() == 35.0f && ((Complex *)e->operand(8))->b() == 0.0f); - assert(((Complex *)e->operand(9))->a() == 46.0f && ((Complex *)e->operand(9))->b() == 11.0f); - assert(((Complex *)e->operand(10))->a() == 57.0f && ((Complex *)e->operand(10))->b() == 0.0f); - assert(((Complex *)e->operand(11))->a() == 68.0f && ((Complex *)e->operand(11))->b() == 0.0f); - delete a; - delete e; + Complex f[12] = {Complex::Cartesian(11.0f, 5.0f), Complex::Cartesian(13.0f, 9.0f), Complex::Cartesian(17.0f, 7.0f), Complex::Cartesian(20.0f, 8.0f), Complex::Cartesian(23.0f, 0.0f), Complex::Cartesian(30.0f, 7.0f), Complex::Cartesian(37.0f, 0.0f), Complex::Cartesian(44.0f, 0.0f), Complex::Cartesian(35.0f, 0.0f), Complex::Cartesian(46.0f, 11.0f), Complex::Cartesian(57.0f, 0.0f), Complex::Cartesian(68.0f, 0.0f)}; + assert_parsed_expression_evaluate_to("[[1,2+I][3,4][5,6]]*[[1,2+I,3,4][5,6+I,7,8]]", f, 12); #endif } diff --git a/poincare/test/subtraction.cpp b/poincare/test/subtraction.cpp index 093eb3074..96899d6f5 100644 --- a/poincare/test/subtraction.cpp +++ b/poincare/test/subtraction.cpp @@ -2,100 +2,34 @@ #include #include #include +#include "helper.h" using namespace Poincare; -QUIZ_CASE(poincare_subtraction_approximate) { - GlobalContext globalContext; - Expression * s = Expression::parse("1-2"); - assert(s->approximate(globalContext) == -1.0f); - delete s; -} - QUIZ_CASE(poincare_substraction_evaluate) { - GlobalContext globalContext; - Expression * a = Expression::parse("1-2"); - Expression * e = a->evaluate(globalContext); - assert(e->approximate(globalContext) == -1.0f); - delete a; - delete e; + Complex a[1] = {Complex::Float(-1.0f)}; + assert_parsed_expression_evaluate_to("1-2", a, 1); - char expText1[10] ={'3','+',Ion::Charset::IComplex, '-', '(', '4', '+', Ion::Charset::IComplex, ')', 0}; - a = Expression::parse(expText1); - e = a->evaluate(globalContext); - assert(((Complex *)e)->a() == -1.0f && ((Complex *)e)->b() == 0.0f); - delete a; - delete e; + Complex b[1] = {Complex::Cartesian(-1.0f, 0.0f)}; + assert_parsed_expression_evaluate_to("3+I-(4+I)", b, 1); #if MATRICES_ARE_DEFINED - a = Expression::parse("[[1,2][3,4][5,6]]-3"); - e = a->evaluate(globalContext); - assert(e->operand(0)->approximate(globalContext) == -2.0f); - assert(e->operand(1)->approximate(globalContext) == -1.0f); - assert(e->operand(2)->approximate(globalContext) == 0.0f); - assert(e->operand(3)->approximate(globalContext) == 1.0f); - assert(e->operand(4)->approximate(globalContext) == 2.0f); - assert(e->operand(5)->approximate(globalContext) == 3.0f); - delete a; - delete e; + Complex c[6] = {Complex::Float(-2.0f), Complex::Float(-1.0f), Complex::Float(0.0f), Complex::Float(1.0f), Complex::Float(2.0f), Complex::Float(3.0f)}; + assert_parsed_expression_evaluate_to("[[1,2][3,4][5,6]]-3", c, 6); - char expText2[100] ={'[','[','1',',','2','+', Ion::Charset::IComplex,']','[','3',',','4',']','[','5',',','6',']',']','-','(', '4', '+', Ion::Charset::IComplex, ')', 0}; - a = Expression::parse(expText2); - e = a->evaluate(globalContext); - assert(((Complex *)e->operand(0))->a() == -3.0f && ((Complex *)e->operand(0))->b() == -1.0f); - assert(((Complex *)e->operand(1))->a() == -2.0f && ((Complex *)e->operand(1))->b() == 0.0f); - assert(((Complex *)e->operand(2))->a() == -1.0f && ((Complex *)e->operand(2))->b() == -1.0f); - assert(((Complex *)e->operand(3))->a() == 0.0f && ((Complex *)e->operand(3))->b() == -1.0f); - assert(((Complex *)e->operand(4))->a() == 1.0f && ((Complex *)e->operand(4))->b() == -1.0f); - assert(((Complex *)e->operand(5))->a() == 2.0f && ((Complex *)e->operand(5))->b() == -1.0f); - delete a; - delete e; + Complex d[6] = {Complex::Cartesian(-3.0f, -1.0f), Complex::Cartesian(-2.0f, 0.0f), Complex::Cartesian(-1.0f, -1.0f), Complex::Cartesian(0.0f, -1.0f), Complex::Cartesian(1.0f, -1.0f), Complex::Cartesian(2.0f, -1.0f)}; + assert_parsed_expression_evaluate_to("[[1,2+I][3,4][5,6]]-(4+I)", d, 6); - a = Expression::parse("3-[[1,2][3,4][5,6]]"); - e = a->evaluate(globalContext); - assert(e->operand(0)->approximate(globalContext) == 2.0f); - assert(e->operand(1)->approximate(globalContext) == 1.0f); - assert(e->operand(2)->approximate(globalContext) == 0.0f); - assert(e->operand(3)->approximate(globalContext) == -1.0f); - assert(e->operand(4)->approximate(globalContext) == -2.0f); - assert(e->operand(5)->approximate(globalContext) == -3.0f); - delete a; - delete e; + Complex e[6] = {Complex::Float(2.0f), Complex::Float(1.0f), Complex::Float(0.0f), Complex::Float(-1.0f), Complex::Float(-2.0f), Complex::Float(-3.0f)}; + assert_parsed_expression_evaluate_to("3-[[1,2][3,4][5,6]]", e, 6); - char expText3[100] ={'3','+',Ion::Charset::IComplex, '-','[','[','1',',','2','+', Ion::Charset::IComplex,']','[','3',',','4',']','[','5',',','6',']',']', 0}; - a = Expression::parse(expText3); - e = a->evaluate(globalContext); - assert(((Complex *)e->operand(0))->a() == 2.0f && ((Complex *)e->operand(0))->b() == 1.0f); - assert(((Complex *)e->operand(1))->a() == 1.0f && ((Complex *)e->operand(1))->b() == 0.0f); - assert(((Complex *)e->operand(2))->a() == 0.0f && ((Complex *)e->operand(2))->b() == 1.0f); - assert(((Complex *)e->operand(3))->a() == -1.0f && ((Complex *)e->operand(3))->b() == 1.0f); - assert(((Complex *)e->operand(4))->a() == -2.0f && ((Complex *)e->operand(4))->b() == 1.0f); - assert(((Complex *)e->operand(5))->a() == -3.0f && ((Complex *)e->operand(5))->b() == 1.0f); - delete a; - delete e; + Complex f[6] = {Complex::Cartesian(2.0f, 1.0f), Complex::Cartesian(1.0f, 0.0f), Complex::Cartesian(0.0f, 1.0f), Complex::Cartesian(-1.0f, 1.0f), Complex::Cartesian(-2.0f, 1.0f), Complex::Cartesian(-3.0f, 1.0f)}; + assert_parsed_expression_evaluate_to("3+I-[[1,2+I][3,4][5,6]]", f, 6); - a = Expression::parse("[[1,2][3,4][5,6]]-[[6,5][4,3][2,1]]"); - e = a->evaluate(globalContext); - assert(e->operand(0)->approximate(globalContext) == -5.0f); - assert(e->operand(1)->approximate(globalContext) == -3.0f); - assert(e->operand(2)->approximate(globalContext) == -1.0f); - assert(e->operand(3)->approximate(globalContext) == 1.0f); - assert(e->operand(4)->approximate(globalContext) == 3.0f); - assert(e->operand(5)->approximate(globalContext) == 5.0f); - delete a; - delete e; + Complex g[6] = {Complex::Float(-5.0f), Complex::Float(-3.0f), Complex::Float(-1.0f), Complex::Float(1.0f), Complex::Float(3.0f), Complex::Float(5.0f)}; + assert_parsed_expression_evaluate_to("[[1,2][3,4][5,6]]-[[6,5][4,3][2,1]]", g, 6); - char expText4[100] ={'[','[','1',',','2','+', Ion::Charset::IComplex,']','[','3',',','4',']','[','5',',','6',']',']','-', - '[','[','1',',','2','+', Ion::Charset::IComplex,']','[','3',',','4',']','[','5',',','6','+', Ion::Charset::IComplex,']',']',0}; - a = Expression::parse(expText4); - e = a->evaluate(globalContext); - assert(((Complex *)e->operand(0))->a() == 0.0f && ((Complex *)e->operand(0))->b() == 0.0f); - assert(((Complex *)e->operand(1))->a() == 0.0f && ((Complex *)e->operand(1))->b() == 0.0f); - assert(((Complex *)e->operand(2))->a() == 0.0f && ((Complex *)e->operand(2))->b() == 0.0f); - assert(((Complex *)e->operand(3))->a() == 0.0f && ((Complex *)e->operand(3))->b() == 0.0f); - assert(((Complex *)e->operand(4))->a() == 0.0f && ((Complex *)e->operand(4))->b() == 0.0f); - assert(((Complex *)e->operand(5))->a() == 0.0f && ((Complex *)e->operand(5))->b() == -1.0f); - delete a; - delete e; + Complex h[6] = {Complex::Float(0.0f), Complex::Float(0.0f), Complex::Float(0.0f), Complex::Float(0.0f), Complex::Float(0.0f), Complex::Float(0.0f)}; + assert_parsed_expression_evaluate_to("[[1,2+I][3,4][5,6]]-[[1,2+I][3,4][5,6]]", h, 6); #endif } diff --git a/poincare/test/symbol.cpp b/poincare/test/symbol.cpp index 292449d39..07afde663 100644 --- a/poincare/test/symbol.cpp +++ b/poincare/test/symbol.cpp @@ -3,6 +3,7 @@ #include #include #include +#include "helper.h" using namespace Poincare; @@ -34,21 +35,11 @@ QUIZ_CASE(poincare_parse_symbol) { QUIZ_CASE(poincare_symbol_approximate) { - GlobalContext globalContext; - char piText[2] = {Ion::Charset::SmallPi, 0}; - Expression * e = Expression::parse(piText); - assert(fabsf(e->approximate(globalContext)-(float)M_PI) <= 0.0001f); - delete e; - - char eText[2] = {Ion::Charset::Exponential, 0}; - e = Expression::parse(eText); - assert(fabsf(e->approximate(globalContext)-(float)M_E) <= 0.0001f); - - delete e; - - char floatText[10] = {'1', '.', '2', Ion::Charset::Exponent, '3', 0}; - e = Expression::parse(floatText); - assert(fabsf(e->approximate(globalContext)-1200.0f) <= 0.0001f); - delete e; + Complex a[1] = {Complex::Float(M_PI)}; + assert_parsed_expression_evaluate_to("P", a, 1); + Complex b[1] = {Complex::Float(M_E)}; + assert_parsed_expression_evaluate_to("X", b, 1); + Complex c[1] = {Complex::Float(1200.0f)}; + assert_parsed_expression_evaluate_to("1.2E3", c, 1); } diff --git a/poincare/test/trigo.cpp b/poincare/test/trigo.cpp index a440c578c..703d0dbb6 100644 --- a/poincare/test/trigo.cpp +++ b/poincare/test/trigo.cpp @@ -2,6 +2,7 @@ #include #include #include +#include "helper.h" using namespace Poincare; @@ -92,63 +93,29 @@ QUIZ_CASE(poincare_parse_trigo) { } } -void assert_parsed_expression_approximate_to(const char * exp, float res) { - Expression * e = Expression::parse(exp); - GlobalContext globalContext; - assert(fabsf(e->approximate(globalContext, Expression::AngleUnit::Radian) - res) < 0.0001f); - delete e; -} - -QUIZ_CASE(poincare_trigo_approximate) { - assert_parsed_expression_approximate_to("cos(3)",-0.98999249660044542f); - assert_parsed_expression_approximate_to("sin(3)", 0.14112000805986721f); - assert_parsed_expression_approximate_to("tan(3)",-0.1425465430742778f); - assert_parsed_expression_approximate_to("cosh(3)",10.067661995777765f); - assert_parsed_expression_approximate_to("cosh(3)",10.067661995777765f); - assert_parsed_expression_approximate_to("sinh(3)", 10.017874927409903f); - assert_parsed_expression_approximate_to("tanh(3)", 0.9950547537f); - assert_parsed_expression_approximate_to("acos(0.3)", 1.266103672779499f); - assert_parsed_expression_approximate_to("asin(0.3)", 0.304692654f); - assert_parsed_expression_approximate_to("atan(0.3)", 0.2914567945f); - assert_parsed_expression_approximate_to("acosh(3)", 1.762747174f); - assert_parsed_expression_approximate_to("asinh(0.3)", 0.2956730476f); - assert_parsed_expression_approximate_to("atanh(0.3)", 0.3095196042f); -} - -void assert_parsed_expression_evaluates_to(const char * exp, float a, float b) { - char buffer[100]; - strlcpy(buffer, exp, 100); - for (uint16_t i=0; ievaluate(globalContext, Expression::AngleUnit::Radian); - assert(fabsf((((Complex *)e)->a()) - a) < 0.0001f); - assert(fabsf((((Complex *)e)->b()) - b) < 0.0001f); - delete f; - delete e; -} - QUIZ_CASE(poincare_trigo_evaluate) { - assert_parsed_expression_evaluates_to("cos(2)", -0.4161468365f, 0.0f); - assert_parsed_expression_evaluates_to("cos(j-4)",-1.0086248134f, -0.8893951958f); - assert_parsed_expression_evaluates_to("sin(2)",0.9092974268f, 0.0f); - assert_parsed_expression_evaluates_to("sin(j-4)", 1.16780727488f, -0.768162763456f); - assert_parsed_expression_evaluates_to("tan(2)",-2.18503986326151899f, 0.0f); - assert_parsed_expression_evaluates_to("tan(j-4)", -0.27355308280730f, 1.002810507583504f); - assert_parsed_expression_evaluates_to("cosh(2)", 3.762195691f, 0.0f); - assert_parsed_expression_evaluates_to("cosh(j-4)",14.754701170483756280f,-22.96367349919304059f); - assert_parsed_expression_evaluates_to("sinh(2)",3.62686040784701876f, 0.0f); - assert_parsed_expression_evaluates_to("sinh(j-4)", -14.744805188558725031023f, 22.979085577886129555168f); - assert_parsed_expression_evaluates_to("tanh(2)",0.9640275800758168839464f, 0.0f); - assert_parsed_expression_evaluates_to("tanh(j-4)", -1.00027905623446556836909f, 0.000610240921376259f); + Complex a[1] = {Complex::Float(-0.4161468365f)}; + assert_parsed_expression_evaluate_to("cos(2)", a, 1, Radian); + Complex a1[1] = {Complex::Cartesian(-1.0086248134f, -0.8893951958f)}; + assert_parsed_expression_evaluate_to("cos(I-4)", a1, 1, Radian); + Complex b[1] = {Complex::Float(0.9092974268f)}; + assert_parsed_expression_evaluate_to("sin(2)", b, 1, Radian); + Complex b1[1] = {Complex::Cartesian( 1.16780727488f, -0.768162763456f)}; + assert_parsed_expression_evaluate_to("sin(I-4)", b1, 1, Radian); + Complex c[1] = {Complex::Float(-2.18503986326151899f)}; + assert_parsed_expression_evaluate_to("tan(2)", c, 1, Radian); + Complex c1[1] = {Complex::Cartesian(-0.27355308280730f, 1.002810507583504f)}; + assert_parsed_expression_evaluate_to("tan(I-4)", c1, 1, Radian); + Complex a2[1] = {Complex::Float(3.762195691f)}; + assert_parsed_expression_evaluate_to("cosh(2)", a2, 1, Radian); + Complex a3[1] = {Complex::Cartesian(14.754701170483756280f,-22.96367349919304059f)}; + assert_parsed_expression_evaluate_to("cosh(I-4)", a3, 1, Radian); + Complex b2[1] = {Complex::Float(3.62686040784701876f)}; + assert_parsed_expression_evaluate_to("sinh(2)", b2, 1, Radian); + Complex b3[1] = {Complex::Cartesian(-14.744805188558725031023f, 22.979085577886129555168f)}; + assert_parsed_expression_evaluate_to("sinh(I-4)", b3, 1, Radian); + Complex c2[1] = {Complex::Float(0.9640275800758168839464f)}; + assert_parsed_expression_evaluate_to("tanh(2)", c2, 1, Radian); + Complex c3[1] = {Complex::Cartesian(-1.00027905623446556836909f, 0.000610240921376259f)}; + assert_parsed_expression_evaluate_to("tanh(I-4)", c3, 1, Radian); }